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 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 484902524cSMatthias Ringwald void btstack_run_lopo_deinit(void){ 494902524cSMatthias Ringwald btstack_timer = NULL; 504902524cSMatthias Ringwald } 514902524cSMatthias Ringwald 524902524cSMatthias Ringwald void btstack_run_loop_add_timer(btstack_timer_source_t * timer){ 534902524cSMatthias Ringwald btstack_timer = timer; 544902524cSMatthias Ringwald } 554902524cSMatthias Ringwald 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 614902524cSMatthias Ringwald void btstack_run_loop_set_timer(btstack_timer_source_t * timer, uint32_t timeout_in_ms){ 624902524cSMatthias Ringwald } 634902524cSMatthias Ringwald 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 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 724902524cSMatthias Ringwald void * btstack_run_loop_get_timer_context(btstack_timer_source_t * timer){ 734902524cSMatthias Ringwald return timer->context; 744902524cSMatthias Ringwald } 754902524cSMatthias Ringwald 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 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 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; 135*500d8180SMilanka Ringwald mock_hci_emit_le_connection_complete(0, some_address, ancs_con_handle, ERROR_CODE_SUCCESS); 136*500d8180SMilanka 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 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 1524902524cSMatthias Ringwald TEST(ANCS_CLIENT, ignored_events){ 1534902524cSMatthias Ringwald // default hci event 1544902524cSMatthias Ringwald uint8_t some_other_event[] = { 0, 0}; 155*500d8180SMilanka Ringwald mock_hci_emit_event(some_other_event, sizeof(some_other_event)); 1564902524cSMatthias Ringwald // default hci le subevent 1574902524cSMatthias Ringwald uint8_t some_le_event[] = { HCI_EVENT_LE_META, 1, 0}; 158*500d8180SMilanka Ringwald mock_hci_emit_event(some_le_event, sizeof(some_le_event)); 1594902524cSMatthias Ringwald // encypted but different con handle 160*500d8180SMilanka Ringwald mock_hci_emit_connection_encrypted(ancs_con_handle+1, 1); 1614902524cSMatthias Ringwald // encypted but different state 162*500d8180SMilanka Ringwald mock_hci_emit_connection_encrypted(ancs_con_handle, 1); 1634902524cSMatthias Ringwald // non-encypted 164*500d8180SMilanka Ringwald mock_hci_emit_connection_encrypted(ancs_con_handle, 0); 1654902524cSMatthias Ringwald // disconnected different handle 166*500d8180SMilanka Ringwald mock_hci_emit_disconnection_complete(ancs_con_handle+1,0); 1674902524cSMatthias Ringwald // disconnected different handle 168*500d8180SMilanka Ringwald mock_hci_emit_disconnection_complete(ancs_con_handle,0); 1694902524cSMatthias Ringwald } 1704902524cSMatthias Ringwald 1714902524cSMatthias Ringwald TEST(ANCS_CLIENT, connect_no_service){ 1724902524cSMatthias Ringwald connect(); 1734902524cSMatthias Ringwald mock_gatt_client_run(); 1744902524cSMatthias Ringwald } 1754902524cSMatthias Ringwald 1764902524cSMatthias Ringwald TEST(ANCS_CLIENT, connect_unexpected_event_during_service_disc){ 1774902524cSMatthias Ringwald connect(); 1784902524cSMatthias Ringwald mock_gatt_client_emit_dummy_event(); 1794902524cSMatthias Ringwald } 1804902524cSMatthias Ringwald 1814902524cSMatthias Ringwald TEST(ANCS_CLIENT, connect_unexpected_events){ 1824902524cSMatthias Ringwald setup_service(true, true); 1834902524cSMatthias Ringwald connect(); 1844902524cSMatthias Ringwald mock_gatt_client_run_once(); 1854902524cSMatthias Ringwald mock_gatt_client_emit_dummy_event(); 1864902524cSMatthias Ringwald mock_gatt_client_run_once(); 1874902524cSMatthias Ringwald mock_gatt_client_emit_dummy_event(); 1884902524cSMatthias Ringwald mock_gatt_client_run_once(); 1894902524cSMatthias Ringwald mock_gatt_client_emit_dummy_event(); 1904902524cSMatthias Ringwald mock_gatt_client_run_once(); 1914902524cSMatthias Ringwald mock_gatt_client_emit_dummy_event(); 1924902524cSMatthias Ringwald } 1934902524cSMatthias Ringwald 1944902524cSMatthias Ringwald TEST(ANCS_CLIENT, connect){ 1954902524cSMatthias Ringwald setup_service(true, true); 1964902524cSMatthias Ringwald connect(); 1974902524cSMatthias Ringwald mock_gatt_client_run(); 1984902524cSMatthias Ringwald CHECK_TRUE(ancs_connected); 1994902524cSMatthias Ringwald } 2004902524cSMatthias Ringwald 2014902524cSMatthias Ringwald TEST(ANCS_CLIENT, connect_extra_characteristic){ 2024902524cSMatthias Ringwald setup_service(true, true); 2034902524cSMatthias Ringwald mock_gatt_client_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL, 0); 2044902524cSMatthias Ringwald connect(); 2054902524cSMatthias Ringwald mock_gatt_client_run(); 2064902524cSMatthias Ringwald } 2074902524cSMatthias Ringwald 2084902524cSMatthias Ringwald TEST(ANCS_CLIENT, disconnect){ 2094902524cSMatthias Ringwald setup_service(true, true); 2104902524cSMatthias Ringwald connect(); 2114902524cSMatthias Ringwald mock_gatt_client_run(); 212*500d8180SMilanka Ringwald mock_hci_emit_disconnection_complete(ancs_con_handle,0); 2134902524cSMatthias Ringwald } 2144902524cSMatthias Ringwald 2154902524cSMatthias Ringwald TEST(ANCS_CLIENT, notification_characteristic){ 2164902524cSMatthias Ringwald setup_service(true, true); 2174902524cSMatthias Ringwald connect(); 2184902524cSMatthias Ringwald mock_gatt_client_run(); 2194902524cSMatthias Ringwald const uint8_t data[] = {}; 2204902524cSMatthias Ringwald mock_gatt_client_send_notification(ancs_notification_source_characteristic, data, sizeof(data)); 2214902524cSMatthias Ringwald } 2224902524cSMatthias Ringwald 2234902524cSMatthias Ringwald TEST(ANCS_CLIENT, data_source_characteristic){ 2244902524cSMatthias Ringwald setup_service(true, true); 2254902524cSMatthias Ringwald connect(); 2264902524cSMatthias Ringwald mock_gatt_client_run(); 2274902524cSMatthias Ringwald // simulate notification 2284902524cSMatthias Ringwald const uint8_t notification_data[] = {0,0,0,0,0,0,0,0}; 2294902524cSMatthias Ringwald mock_gatt_client_send_notification(ancs_notification_source_characteristic, notification_data, sizeof(notification_data)); 2304902524cSMatthias Ringwald // command id = 0 / CommandIDGetNotificationAttributes 2314902524cSMatthias Ringwald // notification uid 0x1111 2324902524cSMatthias Ringwald // attribute id 1 2334902524cSMatthias Ringwald // len 1 2344902524cSMatthias Ringwald // attribute id 2 2354902524cSMatthias Ringwald // len 0 2364902524cSMatthias Ringwald const uint8_t data[] = { 0, 0,0,0,0, 1, 1, 0, 'a', 2, 0, 0}; 2374902524cSMatthias Ringwald mock_gatt_client_send_notification(ancs_data_source_characteristic, data, sizeof(data)); 2384902524cSMatthias Ringwald } 2394902524cSMatthias Ringwald 2404902524cSMatthias Ringwald TEST(ANCS_CLIENT, data_source_characteristic_no_handler){ 2414902524cSMatthias Ringwald ancs_client_register_callback(NULL); 2424902524cSMatthias Ringwald setup_service(true, true); 2434902524cSMatthias Ringwald connect(); 2444902524cSMatthias Ringwald mock_gatt_client_run(); 2454902524cSMatthias Ringwald // simulate notification 2464902524cSMatthias Ringwald const uint8_t notification_data[] = {0,0,0,0,0,0,0,0}; 2474902524cSMatthias Ringwald mock_gatt_client_send_notification(ancs_notification_source_characteristic, notification_data, sizeof(notification_data)); 2484902524cSMatthias Ringwald // command id = 0 / CommandIDGetNotificationAttributes 2494902524cSMatthias Ringwald // notification uid 0x1111 2504902524cSMatthias Ringwald // attribute id 1 2514902524cSMatthias Ringwald // len 1 2524902524cSMatthias Ringwald // attribute id 2 2534902524cSMatthias Ringwald // len 0 2544902524cSMatthias Ringwald const uint8_t data[] = { 0, 0,0,0,0, 1, 1, 0, 'a', 2, 0, 0}; 2554902524cSMatthias Ringwald mock_gatt_client_send_notification(ancs_data_source_characteristic, data, sizeof(data)); 2564902524cSMatthias Ringwald } 2574902524cSMatthias Ringwald 2584902524cSMatthias Ringwald TEST(ANCS_CLIENT, notifications_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_notification_with_handle(ancs_notification_source_characteristic, 0x0001, data, sizeof(data)); 2644902524cSMatthias Ringwald } 2654902524cSMatthias Ringwald 2664902524cSMatthias Ringwald TEST(ANCS_CLIENT, indications_other){ 2674902524cSMatthias Ringwald setup_service(true, true); 2684902524cSMatthias Ringwald connect(); 2694902524cSMatthias Ringwald mock_gatt_client_run(); 2704902524cSMatthias Ringwald const uint8_t data[] = {}; 2714902524cSMatthias Ringwald mock_gatt_client_send_indication_with_handle(ancs_notification_source_characteristic, 0x0001, data, sizeof(data)); 2724902524cSMatthias Ringwald } 2734902524cSMatthias Ringwald 2744902524cSMatthias Ringwald TEST(ANCS_CLIENT, notifications_invalid_parser){ 2754902524cSMatthias Ringwald setup_service(true, true); 2764902524cSMatthias Ringwald ancs_client_set_invalid_parser_state(); 2774902524cSMatthias Ringwald connect(); 2784902524cSMatthias Ringwald mock_gatt_client_run(); 2794902524cSMatthias Ringwald const uint8_t data[] = {1,2,3,4,5,6}; 2804902524cSMatthias Ringwald mock_gatt_client_send_notification(ancs_data_source_characteristic, data, sizeof(data)); 2814902524cSMatthias Ringwald } 2824902524cSMatthias Ringwald 2834902524cSMatthias Ringwald int main (int argc, const char * argv[]){ 2844902524cSMatthias Ringwald return CommandLineTestRunner::RunAllTests(argc, argv); 2854902524cSMatthias Ringwald } 286