pebble/tests/fw/applib/bluetooth/test_ble_ibeacon.c
2025-01-27 11:38:16 -08:00

132 lines
4.7 KiB
C

/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "applib/bluetooth/ble_ibeacon.h"
#include <btutil/bt_device.h>
#include "clar.h"
// Stubs
///////////////////////////////////////////////////////////
#include "stubs_logging.h"
#include "stubs_passert.h"
#include "stubs_pbl_malloc.h"
#include "stubs_pebble_tasks.h"
#include "stubs_rand_ptr.h"
#include "stubs_ble_syscalls.h"
// The test data and descriptions in this file are captured using the FrontLine
// Bluetooth sniffer.
// AD Element, Length: 26, AD Type: Manufacturer Specific, Manufacturer ID:
// Apple, Inc. (0x004c) Additional Data: 0x 02 15 97 6e bb 18 d3 e9 43 c0 8a
// 63 8d 2b 60 d9 04 2a 00 0c 00 22 c5
// This excludes the "Manufacturer Specific" opcode (0xff) but it
// includes the Apple Inc company ID:
static BLEAdData *create_apple_ibeacon_ad_data(void) {
static const uint8_t apple_ibeacon_ad_element[] =
{
0x1a, // 26 bytes
0xff, // Manufacturer Specific AD Type
0x4c, 0x00, // Apple
0x02, // iBeacon
0x15, // Number of bytes to follow
0x97, 0x6e, 0xbb, 0x18, 0xd3, 0xe9, 0x43, 0xc0, // Proximity UUID
0x8a, 0x63, 0x8d, 0x2b, 0x60, 0xd9, 0x04, 0x2a,
0x00, 0x0c, // Minor (BE)
0x00, 0x22, // Major (BE)
0xc5 // TX Power
};
const size_t ad_data_length = sizeof(apple_ibeacon_ad_element);
BLEAdData *ad_data = (BLEAdData *) malloc(sizeof(BLEAdData) + ad_data_length);
ad_data->ad_data_length = ad_data_length;
ad_data->scan_resp_data_length = 0;
memcpy(ad_data->data, apple_ibeacon_ad_element, ad_data_length);
return ad_data;
}
void test_ble_ibeacon__parse_ibeacon_data(void) {
BLEAdData *apple_ibeacon_ad_data = create_apple_ibeacon_ad_data();
BLEiBeacon ibeacon;
const int8_t rssi = -60;
bool is_ibeacon = ble_ibeacon_parse(apple_ibeacon_ad_data, rssi, &ibeacon);
cl_assert(is_ibeacon);
uint8_t uuid_bytes[] = "\x97\x6e\xbb\x18\xd3\xe9\x43\xc0\x8a\x63\x8d\x2b" \
"\x60\xd9\x04\x2a";
Uuid uuid = UuidMakeFromBEBytes(uuid_bytes);
cl_assert(uuid_equal(&ibeacon.uuid, &uuid));
cl_assert_equal_i(ibeacon.major, 12);
cl_assert_equal_i(ibeacon.minor, 34);
cl_assert_equal_i(ibeacon.rssi, -60);
cl_assert_equal_i(ibeacon.calibrated_tx_power, -59);
// cl_assert_equal_i(ibeacon.distance_cm, 110);
free(apple_ibeacon_ad_data);
}
void test_ble_ibeacon__ibeacon_compose(void) {
BLEAdData *apple_ibeacon_ad_data = create_apple_ibeacon_ad_data();
BLEiBeacon ibeacon;
const int8_t rssi = -60;
ble_ibeacon_parse(apple_ibeacon_ad_data, rssi, &ibeacon);
BLEAdData *new_ibeacon_ad_data = ble_ad_create();
cl_assert_equal_b(ble_ibeacon_compose(&ibeacon, new_ibeacon_ad_data), true);
const size_t ad_data_size = apple_ibeacon_ad_data->ad_data_length +
apple_ibeacon_ad_data->scan_resp_data_length;
cl_assert_equal_i(new_ibeacon_ad_data->ad_data_length,
apple_ibeacon_ad_data->ad_data_length);
cl_assert_equal_i(new_ibeacon_ad_data->scan_resp_data_length,
apple_ibeacon_ad_data->scan_resp_data_length);
cl_assert_equal_i(memcmp(new_ibeacon_ad_data->data,
apple_ibeacon_ad_data->data,
ad_data_size), 0);
free(apple_ibeacon_ad_data);
ble_ad_destroy(new_ibeacon_ad_data);
}
static BLEAdData *create_too_short_ad_data(void) {
static const uint8_t too_short_ad_element[] =
{ 0x1a, // 26 bytes
0xff, // Manufacturer Specific AD Type
0x4c, 0x00, // Apple
0x02, // iBeacon
0x14, // Number of bytes to follow -- Internally inconsistent!
0x97, 0x6e, 0xbb, 0x18, 0xd3, 0xe9, 0x43, 0xc0, // Proximity UUID
0x8a, 0x63, 0x8d, 0x2b, 0x60, 0xd9, 0x04, 0x2a,
0x00, 0x0c, // Minor (BE)
0x00, 0x22, // Major (BE)
0xc5 // TX Power
};
BLEAdData *ad_data = (BLEAdData *) malloc(sizeof(BLEAdData) +
sizeof(too_short_ad_element));
ad_data->ad_data_length = sizeof(too_short_ad_element);
ad_data->scan_resp_data_length = 0;
return ad_data;
}
void test_ble_ibeacon__ibeacon_data_too_short(void) {
BLEAdData *too_short_to_ibeacon = create_too_short_ad_data();
bool is_ibeacon = ble_ibeacon_parse(too_short_to_ibeacon, 0, NULL);
cl_assert(!is_ibeacon);
free(too_short_to_ibeacon);
}