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