xref: /btstack/test/gatt-service-client/ancs_client_test.cpp (revision 500d8180fa32d9bb205d49465fb0f7fa20250313)
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