14902524cSMatthias Ringwald // *****************************************************************************
24902524cSMatthias Ringwald //
34902524cSMatthias Ringwald // test ANCS Client
44902524cSMatthias Ringwald //
54902524cSMatthias Ringwald // *****************************************************************************
64902524cSMatthias Ringwald
74902524cSMatthias Ringwald
84902524cSMatthias Ringwald #include <stdint.h>
94902524cSMatthias Ringwald #include <stdio.h>
104902524cSMatthias Ringwald #include <stdlib.h>
114902524cSMatthias Ringwald #include <string.h>
124902524cSMatthias Ringwald
134902524cSMatthias Ringwald #include "CppUTest/TestHarness.h"
144902524cSMatthias Ringwald #include "CppUTest/CommandLineTestRunner.h"
154902524cSMatthias Ringwald #include "CppUTestExt/MockSupport.h"
164902524cSMatthias Ringwald
174902524cSMatthias Ringwald #include "bluetooth.h"
184902524cSMatthias Ringwald #include "bluetooth_gatt.h"
194902524cSMatthias Ringwald #include "btstack_debug.h"
204902524cSMatthias Ringwald #include "btstack_event.h"
214902524cSMatthias Ringwald #include "btstack_memory.h"
224902524cSMatthias Ringwald #include "btstack_util.h"
234902524cSMatthias Ringwald #include "hci.h"
244902524cSMatthias Ringwald
254902524cSMatthias Ringwald #include "ble/gatt-service/ancs_client.h"
264902524cSMatthias Ringwald #include "mock_gatt_client.h"
274902524cSMatthias Ringwald
284902524cSMatthias Ringwald extern "C" void ancs_client_set_invalid_parser_state(void);
294902524cSMatthias Ringwald
304902524cSMatthias Ringwald // mock hci
314902524cSMatthias Ringwald
324902524cSMatthias Ringwald static const uint8_t ancs_service_uuid[] = {0x79,0x05,0xF4,0x31,0xB5,0xCE,0x4E,0x99,0xA4,0x0F,0x4B,0x1E,0x12,0x2D,0x00,0xD0};
334902524cSMatthias Ringwald static const uint8_t ancs_notification_source_uuid[] = {0x9F,0xBF,0x12,0x0D,0x63,0x01,0x42,0xD9,0x8C,0x58,0x25,0xE6,0x99,0xA2,0x1D,0xBD};
344902524cSMatthias Ringwald static const uint8_t ancs_control_point_uuid[] = {0x69,0xD1,0xD8,0xF3,0x45,0xE1,0x49,0xA8,0x98,0x21,0x9B,0xBD,0xFD,0xAA,0xD9,0xD9};
354902524cSMatthias Ringwald static const uint8_t ancs_data_source_uuid[] = {0x22,0xEA,0xC6,0xE9,0x24,0xD6,0x4B,0xB5,0xBE,0x44,0xB3,0x6A,0xCE,0x7C,0x7B,0xFB};
364902524cSMatthias Ringwald
374902524cSMatthias Ringwald static const hci_con_handle_t ancs_con_handle = 0x001;
384902524cSMatthias Ringwald static bool ancs_connected;
394902524cSMatthias Ringwald
404902524cSMatthias Ringwald // mock sm
sm_request_pairing(hci_con_handle_t con_handle)414902524cSMatthias Ringwald void sm_request_pairing(hci_con_handle_t con_handle){
424902524cSMatthias Ringwald }
434902524cSMatthias Ringwald
444902524cSMatthias Ringwald // temp btstack run loop mock
454902524cSMatthias Ringwald
464902524cSMatthias Ringwald static btstack_timer_source_t * btstack_timer = NULL;
474902524cSMatthias Ringwald
btstack_run_lopo_deinit(void)484902524cSMatthias Ringwald void btstack_run_lopo_deinit(void){
494902524cSMatthias Ringwald btstack_timer = NULL;
504902524cSMatthias Ringwald }
514902524cSMatthias Ringwald
btstack_run_loop_add_timer(btstack_timer_source_t * timer)524902524cSMatthias Ringwald void btstack_run_loop_add_timer(btstack_timer_source_t * timer){
534902524cSMatthias Ringwald btstack_timer = timer;
544902524cSMatthias Ringwald }
554902524cSMatthias Ringwald
btstack_run_loop_remove_timer(btstack_timer_source_t * timer)564902524cSMatthias Ringwald int btstack_run_loop_remove_timer(btstack_timer_source_t * timer){
574902524cSMatthias Ringwald btstack_timer = NULL;
584902524cSMatthias Ringwald return 1;
594902524cSMatthias Ringwald }
604902524cSMatthias Ringwald
btstack_run_loop_set_timer(btstack_timer_source_t * timer,uint32_t timeout_in_ms)614902524cSMatthias Ringwald void btstack_run_loop_set_timer(btstack_timer_source_t * timer, uint32_t timeout_in_ms){
624902524cSMatthias Ringwald }
634902524cSMatthias Ringwald
btstack_run_loop_set_timer_handler(btstack_timer_source_t * timer,void (* process)(btstack_timer_source_t * _timer))644902524cSMatthias Ringwald void btstack_run_loop_set_timer_handler(btstack_timer_source_t * timer, void (*process)(btstack_timer_source_t * _timer)){
654902524cSMatthias Ringwald timer->process = process;
664902524cSMatthias Ringwald }
674902524cSMatthias Ringwald
btstack_run_loop_set_timer_context(btstack_timer_source_t * timer,void * context)684902524cSMatthias Ringwald void btstack_run_loop_set_timer_context(btstack_timer_source_t * timer, void * context){
694902524cSMatthias Ringwald timer->context = context;
704902524cSMatthias Ringwald }
714902524cSMatthias Ringwald
btstack_run_loop_get_timer_context(btstack_timer_source_t * timer)724902524cSMatthias Ringwald void * btstack_run_loop_get_timer_context(btstack_timer_source_t * timer){
734902524cSMatthias Ringwald return timer->context;
744902524cSMatthias Ringwald }
754902524cSMatthias Ringwald
mock_btstack_run_loop_trigger_timer(void)764902524cSMatthias Ringwald void mock_btstack_run_loop_trigger_timer(void){
774902524cSMatthias Ringwald btstack_assert(btstack_timer != NULL);
784902524cSMatthias Ringwald (*btstack_timer->process)(btstack_timer);
794902524cSMatthias Ringwald }
804902524cSMatthias Ringwald
ancs_client_event_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)814902524cSMatthias Ringwald static void ancs_client_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
824902524cSMatthias Ringwald UNUSED(packet_type);
834902524cSMatthias Ringwald UNUSED(channel);
844902524cSMatthias Ringwald UNUSED(size);
854902524cSMatthias Ringwald
864902524cSMatthias Ringwald switch (hci_event_gattservice_meta_get_subevent_code(packet)){
874902524cSMatthias Ringwald case ANCS_SUBEVENT_CLIENT_CONNECTED:
884902524cSMatthias Ringwald ancs_connected = true;
894902524cSMatthias Ringwald break;
904902524cSMatthias Ringwald default:
914902524cSMatthias Ringwald break;
924902524cSMatthias Ringwald }
934902524cSMatthias Ringwald }
944902524cSMatthias Ringwald
TEST_GROUP(ANCS_CLIENT)954902524cSMatthias Ringwald TEST_GROUP(ANCS_CLIENT){
964902524cSMatthias Ringwald mock_gatt_client_service_t * service;
974902524cSMatthias Ringwald mock_gatt_client_characteristic_t * ancs_data_source_characteristic;
984902524cSMatthias Ringwald mock_gatt_client_characteristic_t * ancs_notification_source_characteristic;
994902524cSMatthias Ringwald mock_gatt_client_characteristic_t * ancs_control_point_characteristic;
1004902524cSMatthias Ringwald mock_gatt_client_characteristic_descriptor_t * descriptor;
1014902524cSMatthias Ringwald
1024902524cSMatthias Ringwald uint8_t value_buffer[3];
1034902524cSMatthias Ringwald
1044902524cSMatthias Ringwald void setup(void){
1054902524cSMatthias Ringwald ancs_connected = false;
1064902524cSMatthias Ringwald mock_gatt_client_reset();
1074902524cSMatthias Ringwald ancs_client_init();
1084902524cSMatthias Ringwald ancs_client_register_callback(&ancs_client_event_handler);
1094902524cSMatthias Ringwald }
1104902524cSMatthias Ringwald
1114902524cSMatthias Ringwald void setup_service(bool add_characteristics, bool add_descriptors){
1124902524cSMatthias Ringwald // TODO: setup ANCS Service
1134902524cSMatthias Ringwald service = mock_gatt_client_add_primary_service_uuid128(ancs_service_uuid);
1144902524cSMatthias Ringwald
1154902524cSMatthias Ringwald if (!add_characteristics) return;
1164902524cSMatthias Ringwald ancs_control_point_characteristic = mock_gatt_client_add_characteristic_uuid128(ancs_control_point_uuid, ATT_PROPERTY_NOTIFY);
1174902524cSMatthias Ringwald if (add_descriptors) {
1184902524cSMatthias Ringwald descriptor = mock_gatt_client_add_characteristic_descriptor_uuid16(ORG_BLUETOOTH_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION);
1194902524cSMatthias Ringwald }
1204902524cSMatthias Ringwald ancs_data_source_characteristic = mock_gatt_client_add_characteristic_uuid128(ancs_data_source_uuid, ATT_PROPERTY_NOTIFY);
1214902524cSMatthias Ringwald if (add_descriptors) {
1224902524cSMatthias Ringwald descriptor = mock_gatt_client_add_characteristic_descriptor_uuid16(ORG_BLUETOOTH_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION);
1234902524cSMatthias Ringwald }
1244902524cSMatthias Ringwald ancs_notification_source_characteristic = mock_gatt_client_add_characteristic_uuid128(ancs_notification_source_uuid, ATT_PROPERTY_NOTIFY);
1254902524cSMatthias Ringwald if (add_descriptors) {
1264902524cSMatthias Ringwald descriptor = mock_gatt_client_add_characteristic_descriptor_uuid16(ORG_BLUETOOTH_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION);
1274902524cSMatthias Ringwald }
1284902524cSMatthias Ringwald // mock_gatt_client_dump_services();
1294902524cSMatthias Ringwald
1304902524cSMatthias Ringwald }
1314902524cSMatthias Ringwald
1324902524cSMatthias Ringwald void connect(void){
1334902524cSMatthias Ringwald // simulated connected
1344902524cSMatthias Ringwald bd_addr_t some_address;
135500d8180SMilanka Ringwald mock_hci_emit_le_connection_complete(0, some_address, ancs_con_handle, ERROR_CODE_SUCCESS);
136500d8180SMilanka Ringwald mock_hci_emit_connection_encrypted(ancs_con_handle, 1);
1374902524cSMatthias Ringwald }
1384902524cSMatthias Ringwald
1394902524cSMatthias Ringwald void teardown(void){
1404902524cSMatthias Ringwald }
1414902524cSMatthias Ringwald };
1424902524cSMatthias Ringwald
1434902524cSMatthias Ringwald
TEST(ANCS_CLIENT,resolve_ids)1444902524cSMatthias Ringwald TEST(ANCS_CLIENT, resolve_ids){
1454902524cSMatthias Ringwald for (int i = 0; i<6; i++){
1464902524cSMatthias Ringwald const char * name = ancs_client_attribute_name_for_id(i);
1474902524cSMatthias Ringwald CHECK_TRUE(name != NULL);
1484902524cSMatthias Ringwald }
1494902524cSMatthias Ringwald CHECK_EQUAL(NULL, ancs_client_attribute_name_for_id(6));
1504902524cSMatthias Ringwald }
1514902524cSMatthias Ringwald
TEST(ANCS_CLIENT,ignored_events)1524902524cSMatthias Ringwald TEST(ANCS_CLIENT, ignored_events){
1534902524cSMatthias Ringwald // default hci event
1544902524cSMatthias Ringwald uint8_t some_other_event[] = { 0, 0};
155500d8180SMilanka Ringwald mock_hci_emit_event(some_other_event, sizeof(some_other_event));
156*8182555fSMilanka Ringwald
1574902524cSMatthias Ringwald // default hci le subevent
1584902524cSMatthias Ringwald uint8_t some_le_event[] = { HCI_EVENT_LE_META, 1, 0};
159500d8180SMilanka Ringwald mock_hci_emit_event(some_le_event, sizeof(some_le_event));
1604902524cSMatthias Ringwald // encypted but different con handle
161500d8180SMilanka Ringwald mock_hci_emit_connection_encrypted(ancs_con_handle+1, 1);
1624902524cSMatthias Ringwald // encypted but different state
163500d8180SMilanka Ringwald mock_hci_emit_connection_encrypted(ancs_con_handle, 1);
1644902524cSMatthias Ringwald // non-encypted
165500d8180SMilanka Ringwald mock_hci_emit_connection_encrypted(ancs_con_handle, 0);
1664902524cSMatthias Ringwald // disconnected different handle
167500d8180SMilanka Ringwald mock_hci_emit_disconnection_complete(ancs_con_handle+1,0);
1684902524cSMatthias Ringwald // disconnected different handle
169500d8180SMilanka Ringwald mock_hci_emit_disconnection_complete(ancs_con_handle,0);
170*8182555fSMilanka Ringwald
171*8182555fSMilanka Ringwald // some hci gap meta subevent
172*8182555fSMilanka Ringwald uint8_t some_gap_meta_event[] = { HCI_EVENT_META_GAP, 1, HCI_SUBEVENT_LE_CONNECTION_COMPLETE + 1};
173*8182555fSMilanka Ringwald mock_hci_emit_event(some_gap_meta_event, sizeof(some_gap_meta_event));
1744902524cSMatthias Ringwald }
1754902524cSMatthias Ringwald
TEST(ANCS_CLIENT,connect_no_service)1764902524cSMatthias Ringwald TEST(ANCS_CLIENT, connect_no_service){
1774902524cSMatthias Ringwald connect();
1784902524cSMatthias Ringwald mock_gatt_client_run();
1794902524cSMatthias Ringwald }
1804902524cSMatthias Ringwald
TEST(ANCS_CLIENT,connect_unexpected_event_during_service_disc)1814902524cSMatthias Ringwald TEST(ANCS_CLIENT, connect_unexpected_event_during_service_disc){
1824902524cSMatthias Ringwald connect();
1834902524cSMatthias Ringwald mock_gatt_client_emit_dummy_event();
1844902524cSMatthias Ringwald }
1854902524cSMatthias Ringwald
TEST(ANCS_CLIENT,connect)1864902524cSMatthias Ringwald TEST(ANCS_CLIENT, connect){
1874902524cSMatthias Ringwald setup_service(true, true);
1884902524cSMatthias Ringwald connect();
1894902524cSMatthias Ringwald mock_gatt_client_run();
1904902524cSMatthias Ringwald CHECK_TRUE(ancs_connected);
1914902524cSMatthias Ringwald }
1924902524cSMatthias Ringwald
TEST(ANCS_CLIENT,connect_extra_characteristic)1934902524cSMatthias Ringwald TEST(ANCS_CLIENT, connect_extra_characteristic){
1944902524cSMatthias Ringwald setup_service(true, true);
1954902524cSMatthias Ringwald mock_gatt_client_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL, 0);
1964902524cSMatthias Ringwald connect();
1974902524cSMatthias Ringwald mock_gatt_client_run();
1984902524cSMatthias Ringwald }
1994902524cSMatthias Ringwald
TEST(ANCS_CLIENT,disconnect)2004902524cSMatthias Ringwald TEST(ANCS_CLIENT, disconnect){
2014902524cSMatthias Ringwald setup_service(true, true);
2024902524cSMatthias Ringwald connect();
2034902524cSMatthias Ringwald mock_gatt_client_run();
204500d8180SMilanka Ringwald mock_hci_emit_disconnection_complete(ancs_con_handle,0);
2054902524cSMatthias Ringwald }
2064902524cSMatthias Ringwald
TEST(ANCS_CLIENT,notification_characteristic)2074902524cSMatthias Ringwald TEST(ANCS_CLIENT, notification_characteristic){
2084902524cSMatthias Ringwald setup_service(true, true);
2094902524cSMatthias Ringwald connect();
2104902524cSMatthias Ringwald mock_gatt_client_run();
2114902524cSMatthias Ringwald const uint8_t data[] = {};
2124902524cSMatthias Ringwald mock_gatt_client_send_notification(ancs_notification_source_characteristic, data, sizeof(data));
2134902524cSMatthias Ringwald }
2144902524cSMatthias Ringwald
TEST(ANCS_CLIENT,data_source_characteristic)2154902524cSMatthias Ringwald TEST(ANCS_CLIENT, data_source_characteristic){
2164902524cSMatthias Ringwald setup_service(true, true);
2174902524cSMatthias Ringwald connect();
2184902524cSMatthias Ringwald mock_gatt_client_run();
2194902524cSMatthias Ringwald // simulate notification
2204902524cSMatthias Ringwald const uint8_t notification_data[] = {0,0,0,0,0,0,0,0};
2214902524cSMatthias Ringwald mock_gatt_client_send_notification(ancs_notification_source_characteristic, notification_data, sizeof(notification_data));
2224902524cSMatthias Ringwald // command id = 0 / CommandIDGetNotificationAttributes
2234902524cSMatthias Ringwald // notification uid 0x1111
2244902524cSMatthias Ringwald // attribute id 1
2254902524cSMatthias Ringwald // len 1
2264902524cSMatthias Ringwald // attribute id 2
2274902524cSMatthias Ringwald // len 0
2284902524cSMatthias Ringwald const uint8_t data[] = { 0, 0,0,0,0, 1, 1, 0, 'a', 2, 0, 0};
2294902524cSMatthias Ringwald mock_gatt_client_send_notification(ancs_data_source_characteristic, data, sizeof(data));
2304902524cSMatthias Ringwald }
2314902524cSMatthias Ringwald
TEST(ANCS_CLIENT,data_source_characteristic_no_handler)2324902524cSMatthias Ringwald TEST(ANCS_CLIENT, data_source_characteristic_no_handler){
2334902524cSMatthias Ringwald ancs_client_register_callback(NULL);
2344902524cSMatthias Ringwald setup_service(true, true);
2354902524cSMatthias Ringwald connect();
2364902524cSMatthias Ringwald mock_gatt_client_run();
2374902524cSMatthias Ringwald // simulate notification
2384902524cSMatthias Ringwald const uint8_t notification_data[] = {0,0,0,0,0,0,0,0};
2394902524cSMatthias Ringwald mock_gatt_client_send_notification(ancs_notification_source_characteristic, notification_data, sizeof(notification_data));
2404902524cSMatthias Ringwald // command id = 0 / CommandIDGetNotificationAttributes
2414902524cSMatthias Ringwald // notification uid 0x1111
2424902524cSMatthias Ringwald // attribute id 1
2434902524cSMatthias Ringwald // len 1
2444902524cSMatthias Ringwald // attribute id 2
2454902524cSMatthias Ringwald // len 0
2464902524cSMatthias Ringwald const uint8_t data[] = { 0, 0,0,0,0, 1, 1, 0, 'a', 2, 0, 0};
2474902524cSMatthias Ringwald mock_gatt_client_send_notification(ancs_data_source_characteristic, data, sizeof(data));
2484902524cSMatthias Ringwald }
2494902524cSMatthias Ringwald
TEST(ANCS_CLIENT,notifications_other)2504902524cSMatthias Ringwald TEST(ANCS_CLIENT, notifications_other){
2514902524cSMatthias Ringwald setup_service(true, true);
2524902524cSMatthias Ringwald connect();
2534902524cSMatthias Ringwald mock_gatt_client_run();
2544902524cSMatthias Ringwald const uint8_t data[] = {};
2554902524cSMatthias Ringwald mock_gatt_client_send_notification_with_handle(ancs_notification_source_characteristic, 0x0001, data, sizeof(data));
2564902524cSMatthias Ringwald }
2574902524cSMatthias Ringwald
TEST(ANCS_CLIENT,indications_other)2584902524cSMatthias Ringwald TEST(ANCS_CLIENT, indications_other){
2594902524cSMatthias Ringwald setup_service(true, true);
2604902524cSMatthias Ringwald connect();
2614902524cSMatthias Ringwald mock_gatt_client_run();
2624902524cSMatthias Ringwald const uint8_t data[] = {};
2634902524cSMatthias Ringwald mock_gatt_client_send_indication_with_handle(ancs_notification_source_characteristic, 0x0001, data, sizeof(data));
2644902524cSMatthias Ringwald }
2654902524cSMatthias Ringwald
TEST(ANCS_CLIENT,notifications_invalid_parser)2664902524cSMatthias Ringwald TEST(ANCS_CLIENT, notifications_invalid_parser){
2674902524cSMatthias Ringwald setup_service(true, true);
2684902524cSMatthias Ringwald ancs_client_set_invalid_parser_state();
2694902524cSMatthias Ringwald connect();
2704902524cSMatthias Ringwald mock_gatt_client_run();
2714902524cSMatthias Ringwald const uint8_t data[] = {1,2,3,4,5,6};
2724902524cSMatthias Ringwald mock_gatt_client_send_notification(ancs_data_source_characteristic, data, sizeof(data));
2734902524cSMatthias Ringwald }
2744902524cSMatthias Ringwald
TEST(ANCS_CLIENT,connect_unexpected_events)275*8182555fSMilanka Ringwald TEST(ANCS_CLIENT, connect_unexpected_events){
276*8182555fSMilanka Ringwald printf("connect_unexpected_events\n");
277*8182555fSMilanka Ringwald setup_service(true, true);
278*8182555fSMilanka Ringwald connect();
279*8182555fSMilanka Ringwald mock_gatt_client_run_once();
280*8182555fSMilanka Ringwald mock_gatt_client_emit_dummy_event();
281*8182555fSMilanka Ringwald mock_gatt_client_run_once();
282*8182555fSMilanka Ringwald mock_gatt_client_emit_dummy_event();
283*8182555fSMilanka Ringwald mock_gatt_client_run_once();
284*8182555fSMilanka Ringwald mock_gatt_client_emit_dummy_event();
285*8182555fSMilanka Ringwald mock_gatt_client_run_once();
286*8182555fSMilanka Ringwald mock_gatt_client_emit_dummy_event();
287*8182555fSMilanka Ringwald }
288*8182555fSMilanka Ringwald
TEST(ANCS_CLIENT,connect_unexpected_events_in_idle_state)289*8182555fSMilanka Ringwald TEST(ANCS_CLIENT, connect_unexpected_events_in_idle_state){
290*8182555fSMilanka Ringwald printf("connect_unexpected_events\n");
291*8182555fSMilanka Ringwald connect();
292*8182555fSMilanka Ringwald mock_gatt_client_run_once();
293*8182555fSMilanka Ringwald mock_gatt_client_emit_dummy_event();
294*8182555fSMilanka Ringwald }
295*8182555fSMilanka Ringwald
main(int argc,const char * argv[])2964902524cSMatthias Ringwald int main (int argc, const char * argv[]){
2974902524cSMatthias Ringwald return CommandLineTestRunner::RunAllTests(argc, argv);
2984902524cSMatthias Ringwald }
299