1 2 // ***************************************************************************** 3 // 4 // test Battery Service Client 5 // 6 // ***************************************************************************** 7 8 9 #include <stdint.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 #include "CppUTest/TestHarness.h" 15 #include "CppUTest/CommandLineTestRunner.h" 16 #include "CppUTestExt/MockSupport.h" 17 18 #include "bluetooth.h" 19 #include "bluetooth_gatt.h" 20 #include "btstack_debug.h" 21 #include "btstack_event.h" 22 #include "btstack_memory.h" 23 #include "btstack_util.h" 24 #include "hci.h" 25 26 #include "ble/gatt-service/battery_service_client.h" 27 #include "mock_gatt_client.h" 28 29 static const hci_con_handle_t con_handle = 0x01; 30 static bool connected; 31 static uint8_t num_instances = 0; 32 // temp btstack run loop mock 33 34 static btstack_timer_source_t * btstack_timer = NULL; 35 static uint8_t battery_level[10]; 36 static uint16_t battery_level_size; 37 38 void btstack_run_lopo_deinit(void){ 39 btstack_timer = NULL; 40 } 41 42 void btstack_run_loop_add_timer(btstack_timer_source_t * timer){ 43 btstack_timer = timer; 44 } 45 46 int btstack_run_loop_remove_timer(btstack_timer_source_t * timer){ 47 btstack_timer = NULL; 48 return 1; 49 } 50 51 void btstack_run_loop_set_timer(btstack_timer_source_t * timer, uint32_t timeout_in_ms){ 52 } 53 54 void btstack_run_loop_set_timer_handler(btstack_timer_source_t * timer, void (*process)(btstack_timer_source_t * _timer)){ 55 timer->process = process; 56 } 57 58 void btstack_run_loop_set_timer_context(btstack_timer_source_t * timer, void * context){ 59 timer->context = context; 60 } 61 62 void * btstack_run_loop_get_timer_context(btstack_timer_source_t * timer){ 63 return timer->context; 64 } 65 66 void mock_btstack_run_loop_trigger_timer(void){ 67 btstack_assert(btstack_timer != NULL); 68 (*btstack_timer->process)(btstack_timer); 69 } 70 71 // simulate btstack_memory_battery_service_client_get 72 73 static bool mock_btstack_memory_battery_service_client_no_memory; 74 static battery_service_client_t * mock_btstack_memory_battery_service_client_last_alloc; 75 76 void btstack_memory_init(void){ 77 mock_btstack_memory_battery_service_client_no_memory = false; 78 mock_btstack_memory_battery_service_client_last_alloc = NULL; 79 } 80 81 void mock_btstack_memory_battery_service_client_simulate_no_memory(void){ 82 mock_btstack_memory_battery_service_client_no_memory = true; 83 } 84 85 battery_service_client_t * mock_btstack_memory_battery_service_client_get_last_alloc(void){ 86 btstack_assert(mock_btstack_memory_battery_service_client_last_alloc != NULL); 87 return mock_btstack_memory_battery_service_client_last_alloc; 88 } 89 90 battery_service_client_t * btstack_memory_battery_service_client_get(void){ 91 if (mock_btstack_memory_battery_service_client_no_memory){ 92 return NULL; 93 } 94 mock_btstack_memory_battery_service_client_last_alloc = (battery_service_client_t *) malloc(sizeof(battery_service_client_t)); 95 memset(mock_btstack_memory_battery_service_client_last_alloc, 0, sizeof(battery_service_client_t)); 96 return mock_btstack_memory_battery_service_client_last_alloc; 97 } 98 99 void btstack_memory_battery_service_client_free(battery_service_client_t *battery_service_client){ 100 free(battery_service_client); 101 } 102 103 static void gatt_client_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 104 UNUSED(packet_type); 105 UNUSED(channel); 106 UNUSED(size); 107 108 uint8_t status; 109 uint8_t att_status; 110 111 if (hci_event_packet_get_type(packet) != HCI_EVENT_GATTSERVICE_META){ 112 return; 113 } 114 115 switch (hci_event_gattservice_meta_get_subevent_code(packet)){ 116 case GATTSERVICE_SUBEVENT_BATTERY_SERVICE_CONNECTED: 117 status = gattservice_subevent_battery_service_connected_get_status(packet); 118 switch (status){ 119 case ERROR_CODE_SUCCESS: 120 num_instances = gattservice_subevent_battery_service_connected_get_num_instances(packet); 121 connected = true; 122 break; 123 default: 124 connected = false; 125 break; 126 } 127 break; 128 129 case GATTSERVICE_SUBEVENT_BATTERY_SERVICE_LEVEL: 130 att_status = gattservice_subevent_battery_service_level_get_att_status(packet); 131 if (att_status != ATT_ERROR_SUCCESS){ 132 // printf("Battery level read failed, ATT Error 0x%02x\n", att_status); 133 break; 134 } 135 136 // printf("Battery level 0x%02x\n", gattservice_subevent_battery_service_level_get_level(packet)); 137 CHECK_EQUAL(battery_level[0], gattservice_subevent_battery_service_level_get_level(packet)); 138 CHECK_EQUAL(0, gattservice_subevent_battery_service_level_get_sevice_index(packet)); 139 break; 140 141 default: 142 break; 143 } 144 } 145 146 TEST_GROUP(BATTERY_SERVICE_CLIENT){ 147 uint16_t battery_service_cid; 148 uint32_t poll_interval_ms; 149 mock_gatt_client_service_t * service; 150 mock_gatt_client_characteristic_t * characteristic; 151 mock_gatt_client_characteristic_descriptor_t * descriptor; 152 153 uint8_t value_buffer[3]; 154 155 void setup(void){ 156 battery_service_cid = 1; 157 connected = false; 158 poll_interval_ms = 2000; 159 160 uint16_t i; 161 for (i = 0; i < sizeof(value_buffer); i++){ 162 value_buffer[i] = (i+1)*11; 163 } 164 165 btstack_memory_init(); 166 mock_gatt_client_reset(); 167 battery_service_client_init(); 168 } 169 170 void set_battery_level_of_size(uint16_t value_length){ 171 battery_level_size = btstack_min(value_length, sizeof(battery_level)); 172 uint8_t i; 173 for (i=0; i<battery_level_size; i++){ 174 battery_level[i] = i+1; 175 } 176 mock_gatt_client_set_characteristic_value(characteristic, battery_level, battery_level_size); 177 } 178 179 void setup_service(bool add_characteristics, bool add_descriptors){ 180 service = mock_gatt_client_add_primary_service_uuid16(ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE); 181 if (!add_characteristics) return; 182 183 characteristic = mock_gatt_client_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL, ATT_PROPERTY_NOTIFY); 184 185 if (!add_descriptors) return; 186 descriptor = mock_gatt_client_add_characteristic_descriptor_uuid16(ORG_BLUETOOTH_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION); 187 mock_gatt_client_set_descriptor_characteristic_value(descriptor, value_buffer, sizeof(value_buffer)); 188 189 // mock_gatt_client_dump_services(); 190 } 191 192 void setup_service_without_notify_capabality(bool add_characteristics, bool add_descriptors){ 193 service = mock_gatt_client_add_primary_service_uuid16(ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE); 194 if (!add_characteristics) return; 195 196 characteristic = mock_gatt_client_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL, ATT_PROPERTY_READ); 197 198 if (!add_descriptors) return; 199 descriptor = mock_gatt_client_add_characteristic_descriptor_uuid16(ORG_BLUETOOTH_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION); 200 mock_gatt_client_set_descriptor_characteristic_value(descriptor, value_buffer, sizeof(value_buffer)); 201 202 // mock_gatt_client_dump_services(); 203 } 204 205 void connect(void){ 206 uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, &battery_service_cid); 207 CHECK_EQUAL(ERROR_CODE_SUCCESS, status); 208 mock_gatt_client_run(); 209 } 210 211 void teardown(void){ 212 battery_service_client_deinit(); 213 } 214 }; 215 216 TEST(BATTERY_SERVICE_CLIENT, unhandled_gatt_event){ 217 mock_gatt_client_emit_dummy_event(); 218 } 219 220 TEST(BATTERY_SERVICE_CLIENT, gatt_event_in_wrong_state){ 221 uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, NULL); 222 CHECK_EQUAL(ERROR_CODE_SUCCESS, status); 223 // mock_gatt_client_run_once(); 224 // mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS); 225 } 226 227 TEST(BATTERY_SERVICE_CLIENT, connect_no_memory){ 228 mock_btstack_memory_battery_service_client_simulate_no_memory(); 229 uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, NULL); 230 CHECK_EQUAL(BTSTACK_MEMORY_ALLOC_FAILED, status); 231 } 232 233 TEST(BATTERY_SERVICE_CLIENT, connect_no_cid){ 234 uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, NULL); 235 CHECK_EQUAL(ERROR_CODE_SUCCESS, status); 236 237 mock_gatt_client_run(); 238 CHECK_EQUAL(false, connected); 239 } 240 241 TEST(BATTERY_SERVICE_CLIENT, connect_no_service){ 242 uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, &battery_service_cid); 243 CHECK_EQUAL(ERROR_CODE_SUCCESS, status); 244 245 mock_gatt_client_run(); 246 CHECK_EQUAL(false, connected); 247 } 248 249 250 TEST(BATTERY_SERVICE_CLIENT, connect_with_service_no_chr_no_desc){ 251 setup_service(false, false); 252 connect(); 253 CHECK_EQUAL(false, connected); 254 } 255 256 TEST(BATTERY_SERVICE_CLIENT, connect_with_service_and_chr_no_desc){ 257 setup_service(true, false); 258 connect(); 259 CHECK_EQUAL(true, connected); 260 } 261 262 TEST(BATTERY_SERVICE_CLIENT, connect_with_service_and_chr_and_desc){ 263 setup_service(true, true); 264 connect(); 265 CHECK_EQUAL(true, connected); 266 } 267 268 TEST(BATTERY_SERVICE_CLIENT, connect_with_one_invalid_and_one_valid_service){ 269 setup_service(false, false); 270 setup_service(true, true); 271 connect(); 272 CHECK_EQUAL(true, connected); 273 } 274 275 276 TEST(BATTERY_SERVICE_CLIENT, double_connect){ 277 setup_service(true, true); 278 connect(); 279 CHECK_EQUAL(true, connected); 280 uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, &battery_service_cid); 281 CHECK_EQUAL(ERROR_CODE_COMMAND_DISALLOWED, status); 282 } 283 284 TEST(BATTERY_SERVICE_CLIENT, connect_discover_primary_service_error){ 285 mock_gatt_client_set_att_error_discover_primary_services(); 286 setup_service(true, true); 287 connect(); 288 CHECK_EQUAL(false, connected); 289 } 290 291 TEST(BATTERY_SERVICE_CLIENT, connect_discover_characteristics_error){ 292 mock_gatt_client_set_att_error_discover_characteristics(); 293 setup_service(true, true); 294 connect(); 295 CHECK_EQUAL(false, connected); 296 } 297 298 TEST(BATTERY_SERVICE_CLIENT, connect_discover_characteristic_descriptors_error){ 299 mock_gatt_client_set_att_error_discover_characteristic_descriptors(); 300 setup_service(true, true); 301 connect(); 302 CHECK_EQUAL(true, connected); 303 } 304 305 TEST(BATTERY_SERVICE_CLIENT, connect_ignore_too_many_service){ 306 uint8_t i; 307 for (i = 0; i < MAX_NUM_BATTERY_SERVICES + 2; i++){ 308 setup_service(true, true); 309 } 310 setup_service(true, true); 311 connect(); 312 313 CHECK_EQUAL(num_instances, MAX_NUM_BATTERY_SERVICES); 314 CHECK_EQUAL(true, connected); 315 } 316 317 TEST(BATTERY_SERVICE_CLIENT, disconnect_not_connected){ 318 uint8_t status; 319 320 status = battery_service_client_disconnect(battery_service_cid); 321 CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status); 322 } 323 324 TEST(BATTERY_SERVICE_CLIENT, double_disconnect){ 325 uint8_t status; 326 327 setup_service(true, true); 328 connect(); 329 CHECK_EQUAL(true, connected); 330 331 status = battery_service_client_disconnect(battery_service_cid); 332 CHECK_EQUAL(ERROR_CODE_SUCCESS, status); 333 334 status = battery_service_client_disconnect(battery_service_cid); 335 CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status); 336 } 337 338 339 TEST(BATTERY_SERVICE_CLIENT, notify_battery_value_invalid_0){ 340 setup_service(true, true); 341 connect(); 342 CHECK_EQUAL(true, connected); 343 344 set_battery_level_of_size(0); 345 mock_gatt_client_send_notification(characteristic, battery_level, battery_level_size); 346 // TODO: check battery level was not received 347 } 348 349 350 TEST(BATTERY_SERVICE_CLIENT, notify_battery_value_invalid_5){ 351 setup_service(true, true); 352 connect(); 353 CHECK_EQUAL(true, connected); 354 355 set_battery_level_of_size(5); 356 mock_gatt_client_send_notification(characteristic, battery_level, battery_level_size); 357 // TODO: check battery level was not received 358 } 359 360 TEST(BATTERY_SERVICE_CLIENT, notify_battery_value_wrong_handle){ 361 setup_service(true, true); 362 connect(); 363 CHECK_EQUAL(true, connected); 364 365 set_battery_level_of_size(1); 366 mock_gatt_client_send_notification_with_handle(characteristic, 0x1234, battery_level, battery_level_size); 367 // TODO: check battery level was not received 368 } 369 370 TEST(BATTERY_SERVICE_CLIENT, notify_battery_value_wrong_handle_multiple){ 371 setup_service(true, true); 372 setup_service(true, true); 373 connect(); 374 CHECK_EQUAL(true, connected); 375 376 set_battery_level_of_size(1); 377 mock_gatt_client_send_notification_with_handle(characteristic, 0x1234, battery_level, battery_level_size); 378 // TODO: check battery level was not received 379 } 380 381 TEST(BATTERY_SERVICE_CLIENT, notify_battery_value_valid){ 382 setup_service(true, true); 383 connect(); 384 CHECK_EQUAL(true, connected); 385 386 set_battery_level_of_size(1); 387 mock_gatt_client_send_notification(characteristic, battery_level, battery_level_size); 388 // TODO: check battery level was received 389 } 390 391 TEST(BATTERY_SERVICE_CLIENT, multiple_connection){ 392 battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, &battery_service_cid); 393 battery_service_client_connect(con_handle+1, &gatt_client_event_handler, poll_interval_ms, &battery_service_cid); 394 battery_service_client_read_battery_level(10, 0); 395 } 396 397 TEST(BATTERY_SERVICE_CLIENT, read_battery_level_wrong_cid){ 398 uint8_t status = battery_service_client_read_battery_level(10, 0); 399 CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status); 400 } 401 402 TEST(BATTERY_SERVICE_CLIENT, read_battery_level_wrong_state){ 403 // without calling mock_gatt_client_run(), state remains in BATTERY_SERVICE_CLIENT_STATE_W2_QUERY_SERVICE 404 uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, &battery_service_cid); 405 CHECK_EQUAL(ERROR_CODE_SUCCESS, status); 406 CHECK_EQUAL(false, connected); 407 408 status = battery_service_client_read_battery_level(battery_service_cid, 0); 409 CHECK_EQUAL(GATT_CLIENT_IN_WRONG_STATE, status); 410 } 411 412 TEST(BATTERY_SERVICE_CLIENT, read_battery_level_wrong_state_in_packet_handler){ 413 setup_service(true, true); 414 connect(); 415 CHECK_EQUAL(true, connected); 416 mock_btstack_memory_battery_service_client_get_last_alloc()->state = BATTERY_SERVICE_CLIENT_STATE_IDLE; 417 mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS); 418 } 419 420 TEST(BATTERY_SERVICE_CLIENT, read_battery_level_wrong_service_index){ 421 setup_service(true, true); 422 connect(); 423 CHECK_EQUAL(true, connected); 424 425 uint8_t status = battery_service_client_read_battery_level(battery_service_cid, 10); 426 CHECK_EQUAL(ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE, status); 427 } 428 429 TEST(BATTERY_SERVICE_CLIENT, poll_battery_value_invalid){ 430 setup_service(true, true); 431 mock_gatt_client_enable_notification(characteristic, false); 432 set_battery_level_of_size(5); 433 434 435 connect(); 436 CHECK_EQUAL(true, connected); 437 438 uint8_t status = battery_service_client_read_battery_level(battery_service_cid, 0); 439 CHECK_EQUAL(ERROR_CODE_SUCCESS, status); 440 } 441 442 TEST(BATTERY_SERVICE_CLIENT, poll_battery_value){ 443 setup_service(true, true); 444 set_battery_level_of_size(1); 445 446 mock_gatt_client_enable_notification(characteristic, false); 447 448 connect(); 449 CHECK_EQUAL(true, connected); 450 451 uint8_t status = battery_service_client_read_battery_level(battery_service_cid, 0); 452 CHECK_EQUAL(ERROR_CODE_SUCCESS, status); 453 } 454 455 TEST(BATTERY_SERVICE_CLIENT, poll_battery_value_with_error){ 456 setup_service(true, true); 457 set_battery_level_of_size(1); 458 459 mock_gatt_client_enable_notification(characteristic, false); 460 461 connect(); 462 CHECK_EQUAL(true, connected); 463 464 uint8_t status = battery_service_client_read_battery_level(battery_service_cid, 0); 465 CHECK_EQUAL(ERROR_CODE_SUCCESS, status); 466 mock_gatt_client_emit_complete(1); 467 } 468 469 TEST(BATTERY_SERVICE_CLIENT, poll_battery_value_zero_poll_interval){ 470 setup_service(true, true); 471 set_battery_level_of_size(1); 472 473 mock_gatt_client_enable_notification(characteristic, false); 474 475 uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, 0, &battery_service_cid); 476 CHECK_EQUAL(ERROR_CODE_SUCCESS, status); 477 mock_gatt_client_run(); 478 CHECK_EQUAL(true, connected); 479 480 status = battery_service_client_read_battery_level(battery_service_cid, 0); 481 CHECK_EQUAL(ERROR_CODE_SUCCESS, status); 482 } 483 484 485 TEST(BATTERY_SERVICE_CLIENT, poll_battery_value_trigger_timer){ 486 setup_service(true, true); 487 set_battery_level_of_size(1); 488 489 mock_gatt_client_enable_notification(characteristic, false); 490 491 connect(); 492 CHECK_EQUAL(true, connected); 493 mock_btstack_run_loop_trigger_timer(); 494 mock_gatt_client_run(); 495 } 496 497 TEST(BATTERY_SERVICE_CLIENT, poll_battery_value_trigger_timer_unxpected_complete){ 498 setup_service(true, true); 499 set_battery_level_of_size(1); 500 501 mock_gatt_client_enable_notification(characteristic, false); 502 503 connect(); 504 CHECK_EQUAL(true, connected); 505 mock_btstack_run_loop_trigger_timer(); 506 mock_gatt_client_run(); 507 508 // polling done, emit another complete event 509 mock_gatt_client_emit_complete(0); 510 } 511 512 513 TEST(BATTERY_SERVICE_CLIENT, mixed_poll_and_notify_battery_value){ 514 setup_service(true, true); 515 mock_gatt_client_enable_notification(characteristic, true); 516 517 setup_service(true, true); 518 mock_gatt_client_enable_notification(characteristic, false); 519 520 setup_service(true, true); 521 mock_gatt_client_enable_notification(characteristic, true); 522 523 connect(); 524 CHECK_EQUAL(true, connected); 525 } 526 527 TEST(BATTERY_SERVICE_CLIENT, hci_disconnect_event){ 528 setup_service(true, true); 529 connect(); 530 CHECK_EQUAL(true, connected); 531 532 mock_hci_emit_disconnection_complete(con_handle, 0); 533 uint8_t status = battery_service_client_disconnect(battery_service_cid); 534 CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status); 535 536 mock_hci_emit_disconnection_complete(HCI_CON_HANDLE_INVALID, 0); 537 } 538 539 TEST(BATTERY_SERVICE_CLIENT, ignored_events){ 540 setup_service(true, true); 541 connect(); 542 CHECK_EQUAL(true, connected); 543 544 // unexpected event 545 mock_hci_emit_connection_encrypted(con_handle, 0); 546 // event with wrong con handle 547 mock_hci_emit_disconnection_complete(HCI_CON_HANDLE_INVALID, 0); 548 } 549 550 int main (int argc, const char * argv[]){ 551 return CommandLineTestRunner::RunAllTests(argc, argv); 552 } 553