test/gatt-service-client: more tests

This commit is contained in:
Milanka Ringwald 2021-06-10 15:45:59 +02:00
parent 7e693ad3d4
commit f837410276
2 changed files with 269 additions and 28 deletions

View File

@ -20,8 +20,6 @@ VPATH += ${BTSTACK_ROOT}/test/mock
COMMON = \
btstack_linked_list.c \
btstack_memory.c \
btstack_memory_pool.c \
btstack_util.c \
hci_dump.c \
mock_gatt_client.c \

View File

@ -15,11 +15,13 @@
#include "CppUTest/CommandLineTestRunner.h"
#include "CppUTestExt/MockSupport.h"
#include "hci.h"
#include "btstack_util.h"
#include "bluetooth.h"
#include "bluetooth_gatt.h"
#include "btstack_debug.h"
#include "btstack_event.h"
#include "btstack_memory.h"
#include "btstack_util.h"
#include "hci.h"
#include "ble/gatt-service/battery_service_client.h"
#include "mock_gatt_client.h"
@ -30,6 +32,8 @@ static uint8_t num_instances = 0;
// temp btstack run loop mock
static btstack_timer_source_t * btstack_timer = NULL;
static uint8_t battery_level[10];
static uint16_t battery_level_size;
void btstack_run_lopo_deinit(void){
btstack_timer = NULL;
@ -39,10 +43,6 @@ void btstack_run_loop_add_timer(btstack_timer_source_t * timer){
btstack_timer = timer;
}
void * btstack_run_loop_get_timer_context(btstack_timer_source_t * timer){
return btstack_timer;
}
int btstack_run_loop_remove_timer(btstack_timer_source_t * timer){
btstack_timer = NULL;
return 1;
@ -51,14 +51,55 @@ int btstack_run_loop_remove_timer(btstack_timer_source_t * timer){
void btstack_run_loop_set_timer(btstack_timer_source_t * timer, uint32_t timeout_in_ms){
}
void btstack_run_loop_set_timer_context(btstack_timer_source_t * timer, void * context){
void btstack_run_loop_set_timer_handler(btstack_timer_source_t * timer, void (*process)(btstack_timer_source_t * _timer)){
timer->process = process;
}
void btstack_run_loop_set_timer_handler(btstack_timer_source_t * timer, void (*process)(btstack_timer_source_t * _timer)){
void btstack_run_loop_set_timer_context(btstack_timer_source_t * timer, void * context){
timer->context = context;
}
void * btstack_run_loop_get_timer_context(btstack_timer_source_t * timer){
return timer->context;
}
void mock_btstack_run_loop_trigger_timer(void){
btstack_assert(btstack_timer != NULL);
(*btstack_timer->process)(btstack_timer);
}
// simulate btstack_memory_battery_service_client_get
static bool mock_btstack_memory_battery_service_client_no_memory;
static battery_service_client_t * mock_btstack_memory_battery_service_client_last_alloc;
void btstack_memory_init(void){
mock_btstack_memory_battery_service_client_no_memory = false;
mock_btstack_memory_battery_service_client_last_alloc = NULL;
}
void mock_btstack_memory_battery_service_client_simulate_no_memory(void){
mock_btstack_memory_battery_service_client_no_memory = true;
}
battery_service_client_t * mock_btstack_memory_battery_service_client_get_last_alloc(void){
btstack_assert(mock_btstack_memory_battery_service_client_last_alloc != NULL);
return mock_btstack_memory_battery_service_client_last_alloc;
}
battery_service_client_t * btstack_memory_battery_service_client_get(void){
if (mock_btstack_memory_battery_service_client_no_memory){
return NULL;
}
mock_btstack_memory_battery_service_client_last_alloc = (battery_service_client_t *) malloc(sizeof(battery_service_client_t));
memset(mock_btstack_memory_battery_service_client_last_alloc, 0, sizeof(battery_service_client_t));
return mock_btstack_memory_battery_service_client_last_alloc;
}
void btstack_memory_battery_service_client_free(battery_service_client_t *battery_service_client){
free(battery_service_client);
}
static void gatt_client_event_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
UNUSED(packet_type);
UNUSED(channel);
@ -76,15 +117,11 @@ static void gatt_client_event_handler(uint8_t packet_type, uint16_t channel, uin
status = gattservice_subevent_battery_service_connected_get_status(packet);
switch (status){
case ERROR_CODE_SUCCESS:
printf("Battery service client connected, found %d services, poll bitmap 0x%02x\n",
gattservice_subevent_battery_service_connected_get_num_instances(packet),
gattservice_subevent_battery_service_connected_get_poll_bitmap(packet));
num_instances = gattservice_subevent_battery_service_connected_get_num_instances(packet);
connected = true;
break;
default:
printf("Battery service client connection failed, err 0x%02x.\n", status);
connected = false;
break;
}
break;
@ -93,12 +130,12 @@ static void gatt_client_event_handler(uint8_t packet_type, uint16_t channel, uin
att_status = gattservice_subevent_battery_service_level_get_att_status(packet);
if (att_status != ATT_ERROR_SUCCESS){
printf("Battery level read failed, ATT Error 0x%02x\n", att_status);
} else {
printf("Service index: %d, Battery level: %d\n",
gattservice_subevent_battery_service_level_get_sevice_index(packet),
gattservice_subevent_battery_service_level_get_level(packet));
}
break;
}
printf("Battery level 0x%02x\n", gattservice_subevent_battery_service_level_get_level(packet));
CHECK_EQUAL(battery_level[0], gattservice_subevent_battery_service_level_get_level(packet));
CHECK_EQUAL(0, gattservice_subevent_battery_service_level_get_sevice_index(packet));
break;
default:
@ -122,13 +159,23 @@ TEST_GROUP(BATTERY_SERVICE_CLIENT){
uint16_t i;
for (i = 0; i < sizeof(value_buffer); i++){
value_buffer[i] = (i+1)*10 + i + 1;
value_buffer[i] = (i+1)*11;
}
btstack_memory_init();
mock_gatt_client_reset();
battery_service_client_init();
}
void set_battery_level_of_size(uint16_t value_length){
battery_level_size = btstack_min(value_length, sizeof(battery_level));
uint8_t i;
for (i=0; i<battery_level_size; i++){
battery_level[i] = i+1;
}
mock_gatt_client_set_characteristic_value(characteristic, battery_level, battery_level_size);
}
void setup_service(bool add_characteristics, bool add_descriptors){
service = mock_gatt_client_add_primary_service_uuid16(ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE);
if (!add_characteristics) return;
@ -137,7 +184,20 @@ TEST_GROUP(BATTERY_SERVICE_CLIENT){
if (!add_descriptors) return;
descriptor = mock_gatt_client_add_characteristic_descriptor_uuid16(ORG_BLUETOOTH_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION);
mock_gatt_client_set_characteristic_value(descriptor, value_buffer, sizeof(value_buffer));
mock_gatt_client_set_descriptor_characteristic_value(descriptor, value_buffer, sizeof(value_buffer));
// mock_gatt_client_dump_services();
}
void setup_service_without_notify_capabality(bool add_characteristics, bool add_descriptors){
service = mock_gatt_client_add_primary_service_uuid16(ORG_BLUETOOTH_SERVICE_BATTERY_SERVICE);
if (!add_characteristics) return;
characteristic = mock_gatt_client_add_characteristic_uuid16(ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL, ATT_PROPERTY_READ);
if (!add_descriptors) return;
descriptor = mock_gatt_client_add_characteristic_descriptor_uuid16(ORG_BLUETOOTH_DESCRIPTOR_GATT_CLIENT_CHARACTERISTIC_CONFIGURATION);
mock_gatt_client_set_descriptor_characteristic_value(descriptor, value_buffer, sizeof(value_buffer));
// mock_gatt_client_dump_services();
}
@ -153,6 +213,31 @@ TEST_GROUP(BATTERY_SERVICE_CLIENT){
}
};
TEST(BATTERY_SERVICE_CLIENT, unhandled_gatt_event){
mock_gatt_client_emit_dummy_event();
}
TEST(BATTERY_SERVICE_CLIENT, gatt_event_in_wrong_state){
uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, NULL);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
// mock_gatt_client_run_once();
// mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
}
TEST(BATTERY_SERVICE_CLIENT, connect_no_memory){
mock_btstack_memory_battery_service_client_simulate_no_memory();
uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, NULL);
CHECK_EQUAL(BTSTACK_MEMORY_ALLOC_FAILED, status);
}
TEST(BATTERY_SERVICE_CLIENT, connect_no_cid){
uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, NULL);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
mock_gatt_client_run();
CHECK_EQUAL(false, connected);
}
TEST(BATTERY_SERVICE_CLIENT, connect_no_service){
uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, &battery_service_cid);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
@ -168,6 +253,12 @@ TEST(BATTERY_SERVICE_CLIENT, connect_with_service_no_chr_no_desc){
CHECK_EQUAL(false, connected);
}
TEST(BATTERY_SERVICE_CLIENT, connect_invalid_handle){
setup_service(true, true);
// mock_gatt_client_simulate_invalid_con_handle();
// connect();
// CHECK_EQUAL(false, connected);
}
TEST(BATTERY_SERVICE_CLIENT, connect_with_service_and_chr_no_desc){
setup_service(true, false);
@ -184,7 +275,6 @@ TEST(BATTERY_SERVICE_CLIENT, connect_with_service_and_chr_and_desc){
TEST(BATTERY_SERVICE_CLIENT, connect_with_one_invalid_and_one_valid_service){
setup_service(false, false);
setup_service(true, true);
mock_gatt_client_dump_services();
connect();
CHECK_EQUAL(true, connected);
}
@ -194,7 +284,6 @@ TEST(BATTERY_SERVICE_CLIENT, double_connect){
setup_service(true, true);
connect();
CHECK_EQUAL(true, connected);
uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, &battery_service_cid);
CHECK_EQUAL(ERROR_CODE_COMMAND_DISALLOWED, status);
}
@ -248,12 +337,70 @@ TEST(BATTERY_SERVICE_CLIENT, double_disconnect){
status = battery_service_client_disconnect(battery_service_cid);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
status = battery_service_client_disconnect(battery_service_cid);
CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status);
}
TEST(BATTERY_SERVICE_CLIENT, notify_battery_value_invalid_0){
setup_service(true, true);
connect();
CHECK_EQUAL(true, connected);
set_battery_level_of_size(0);
mock_gatt_client_send_notification(characteristic, battery_level, battery_level_size);
// TODO: check battery level was not received
}
TEST(BATTERY_SERVICE_CLIENT, notify_battery_value_invalid_5){
setup_service(true, true);
connect();
CHECK_EQUAL(true, connected);
set_battery_level_of_size(5);
mock_gatt_client_send_notification(characteristic, battery_level, battery_level_size);
// TODO: check battery level was not received
}
TEST(BATTERY_SERVICE_CLIENT, notify_battery_value_wrong_handle){
setup_service(true, true);
connect();
CHECK_EQUAL(true, connected);
set_battery_level_of_size(1);
mock_gatt_client_send_notification_with_handle(characteristic, 0x1234, battery_level, battery_level_size);
// TODO: check battery level was not received
}
TEST(BATTERY_SERVICE_CLIENT, notify_battery_value_wrong_handle_multiple){
setup_service(true, true);
setup_service(true, true);
connect();
CHECK_EQUAL(true, connected);
set_battery_level_of_size(1);
mock_gatt_client_send_notification_with_handle(characteristic, 0x1234, battery_level, battery_level_size);
// TODO: check battery level was not received
}
TEST(BATTERY_SERVICE_CLIENT, notify_battery_value_valid){
setup_service(true, true);
connect();
CHECK_EQUAL(true, connected);
set_battery_level_of_size(1);
mock_gatt_client_send_notification(characteristic, battery_level, battery_level_size);
// TODO: check battery level was received
}
TEST(BATTERY_SERVICE_CLIENT, multiple_connection){
battery_service_client_connect(con_handle, &gatt_client_event_handler, poll_interval_ms, &battery_service_cid);
battery_service_client_connect(con_handle+1, &gatt_client_event_handler, poll_interval_ms, &battery_service_cid);
battery_service_client_read_battery_level(10, 0);
}
TEST(BATTERY_SERVICE_CLIENT, read_battery_level_wrong_cid){
uint8_t status = battery_service_client_read_battery_level(10, 0);
CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status);
@ -269,6 +416,14 @@ TEST(BATTERY_SERVICE_CLIENT, read_battery_level_wrong_state){
CHECK_EQUAL(GATT_CLIENT_IN_WRONG_STATE, status);
}
TEST(BATTERY_SERVICE_CLIENT, read_battery_level_wrong_state_in_packet_handler){
setup_service(true, true);
connect();
CHECK_EQUAL(true, connected);
mock_btstack_memory_battery_service_client_get_last_alloc()->state = BATTERY_SERVICE_CLIENT_STATE_IDLE;
mock_gatt_client_emit_complete(ERROR_CODE_SUCCESS);
}
TEST(BATTERY_SERVICE_CLIENT, read_battery_level_wrong_service_index){
setup_service(true, true);
connect();
@ -278,15 +433,103 @@ TEST(BATTERY_SERVICE_CLIENT, read_battery_level_wrong_service_index){
CHECK_EQUAL(ERROR_CODE_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE, status);
}
TEST(BATTERY_SERVICE_CLIENT, read_battery_level){
TEST(BATTERY_SERVICE_CLIENT, poll_battery_value_invalid){
setup_service(true, true);
mock_gatt_client_enable_notification(characteristic, false);
set_battery_level_of_size(5);
connect();
CHECK_EQUAL(true, connected);
uint8_t status = battery_service_client_read_battery_level(battery_service_cid, 0);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
}
TEST(BATTERY_SERVICE_CLIENT, poll_battery_value){
setup_service(true, true);
set_battery_level_of_size(1);
mock_gatt_client_enable_notification(characteristic, false);
connect();
CHECK_EQUAL(true, connected);
uint8_t status = battery_service_client_read_battery_level(battery_service_cid, 0);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
}
TEST(BATTERY_SERVICE_CLIENT, poll_battery_value_with_error){
setup_service(true, true);
set_battery_level_of_size(1);
mock_gatt_client_enable_notification(characteristic, false);
connect();
CHECK_EQUAL(true, connected);
uint8_t status = battery_service_client_read_battery_level(battery_service_cid, 0);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
mock_gatt_client_emit_complete(1);
}
TEST(BATTERY_SERVICE_CLIENT, poll_battery_value_zero_poll_interval){
setup_service(true, true);
set_battery_level_of_size(1);
mock_gatt_client_enable_notification(characteristic, false);
uint8_t status = battery_service_client_connect(con_handle, &gatt_client_event_handler, 0, &battery_service_cid);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
mock_gatt_client_run();
CHECK_EQUAL(true, connected);
status = battery_service_client_read_battery_level(battery_service_cid, 0);
CHECK_EQUAL(ERROR_CODE_SUCCESS, status);
}
TEST(BATTERY_SERVICE_CLIENT, poll_battery_value_trigger_timer){
setup_service(true, true);
set_battery_level_of_size(1);
mock_gatt_client_enable_notification(characteristic, false);
connect();
CHECK_EQUAL(true, connected);
mock_btstack_run_loop_trigger_timer();
mock_gatt_client_run();
}
TEST(BATTERY_SERVICE_CLIENT, poll_battery_value_trigger_timer_unxpected_complete){
setup_service(true, true);
set_battery_level_of_size(1);
mock_gatt_client_enable_notification(characteristic, false);
connect();
CHECK_EQUAL(true, connected);
mock_btstack_run_loop_trigger_timer();
mock_gatt_client_run();
// polling done, emit another complete event
mock_gatt_client_emit_complete(0);
}
TEST(BATTERY_SERVICE_CLIENT, mixed_poll_and_notify_battery_value){
setup_service(true, true);
mock_gatt_client_enable_notification(characteristic, true);
setup_service(true, true);
mock_gatt_client_enable_notification(characteristic, false);
setup_service(true, true);
mock_gatt_client_enable_notification(characteristic, true);
connect();
CHECK_EQUAL(true, connected);
}
int main (int argc, const char * argv[]){
return CommandLineTestRunner::RunAllTests(argc, argv);