From 8206902c42ac2dd8d1990987d7217d06ca3fc55b Mon Sep 17 00:00:00 2001 From: Milanka Ringwald Date: Wed, 15 Dec 2021 20:38:34 +0100 Subject: [PATCH] test/gatt_server: test connection complete and disconnect events --- test/gatt_server/CMakeLists.txt | 4 ++ test/gatt_server/gatt_server_test.cpp | 85 ++++++++++++++++++++++++--- test/gatt_server/mock.c | 62 ++++++++++--------- 3 files changed, 114 insertions(+), 37 deletions(-) diff --git a/test/gatt_server/CMakeLists.txt b/test/gatt_server/CMakeLists.txt index a20a256a8..3bcbae66d 100644 --- a/test/gatt_server/CMakeLists.txt +++ b/test/gatt_server/CMakeLists.txt @@ -47,6 +47,10 @@ set(SOURCES mock.c ) +# Enable ASAN +add_compile_options( -g -fsanitize=address) +add_link_options( -fsanitize=address) + # create static lib add_library(btstack STATIC ${SOURCES}) diff --git a/test/gatt_server/gatt_server_test.cpp b/test/gatt_server/gatt_server_test.cpp index a8430c3ce..43a8bfd2d 100644 --- a/test/gatt_server/gatt_server_test.cpp +++ b/test/gatt_server/gatt_server_test.cpp @@ -31,7 +31,9 @@ static const uint8_t uuid128_no_bluetooth_base[] = { 0xFB, 0x34, 0x9B, 0x5F, 0 extern "C" void l2cap_can_send_fixed_channel_packet_now_set_status(uint8_t status); extern "C" void mock_call_att_server_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); -extern "C" void att_init_connection(uint16_t con_handle); +extern "C" void hci_setup_le_connection(uint16_t con_handle); +extern "C" void mock_call_att_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); +extern "C" void mock_l2cap_set_max_mtu(uint16_t mtu); static uint8_t att_request[255]; static uint16_t att_write_request(uint16_t request_type, uint16_t attribute_handle, uint16_t value_length, const uint8_t * value){ @@ -64,20 +66,30 @@ static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_h static void att_client_indication_callback(void * context){ } +static void att_client_notification_callback(void * context){ +} +static void att_event_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { +} + TEST_GROUP(ATT_SERVER){ uint16_t att_con_handle; mock_btstack_tlv_t tlv_context; const btstack_tlv_t * tlv_impl; + btstack_context_callback_registration_t indication_callback; + btstack_context_callback_registration_t notification_callback; void setup(void){ - att_con_handle = 0x00; + att_con_handle = 0x01; + + hci_setup_le_connection(att_con_handle); - att_init_connection(att_con_handle); tlv_impl = mock_btstack_tlv_init_instance(&tlv_context); btstack_tlv_set_instance(tlv_impl, &tlv_context); l2cap_can_send_fixed_channel_packet_now_set_status(1); + indication_callback.callback = &att_client_indication_callback; + notification_callback.callback = &att_client_notification_callback; // init att db util and add a service and characteristic att_db_util_init(); @@ -111,10 +123,10 @@ TEST_GROUP(ATT_SERVER){ void teardown(void) { mock_btstack_tlv_deinit(&tlv_context); + hci_deinit(); } }; - TEST(ATT_SERVER, gatt_server_get_value_handle_for_characteristic_with_uuid16){ // att_dump_attributes(); uint16_t value_handle; @@ -207,7 +219,6 @@ TEST(ATT_SERVER, att_server_get_mtu){ TEST(ATT_SERVER, att_server_request_can_send_now_event){ att_server_request_can_send_now_event(att_con_handle); - } TEST(ATT_SERVER, att_server_can_send_packet_now){ @@ -218,11 +229,7 @@ TEST(ATT_SERVER, att_server_can_send_packet_now){ CHECK_EQUAL(0, status); } -static btstack_context_callback_registration_t indication_callback; - TEST(ATT_SERVER, att_server_request_to_send_indication){ - - indication_callback.callback = &att_client_indication_callback; int status = att_server_request_to_send_indication(&indication_callback, 0x55); CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status); @@ -235,13 +242,73 @@ TEST(ATT_SERVER, att_server_request_to_send_indication){ CHECK_EQUAL(ERROR_CODE_COMMAND_DISALLOWED, status); } +TEST(ATT_SERVER, att_server_request_to_send_notification){ + int status = att_server_request_to_send_notification(¬ification_callback, 0x55); + CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status); + + l2cap_can_send_fixed_channel_packet_now_set_status(0); + + status = att_server_request_to_send_notification(¬ification_callback, att_con_handle); + CHECK_EQUAL(ERROR_CODE_SUCCESS, status); + + status = att_server_request_to_send_notification(¬ification_callback, att_con_handle); + CHECK_EQUAL(ERROR_CODE_COMMAND_DISALLOWED, status); +} + +TEST(ATT_SERVER, att_server_register_can_send_now_callback){ + int status = att_server_register_can_send_now_callback(¬ification_callback, 0x55); + CHECK_EQUAL(ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER, status); + + att_server_register_packet_handler(&att_event_packet_handler); +} + TEST(ATT_SERVER, opcode_ATT_WRITE_REQUEST){ uint16_t value_handle = gatt_server_get_client_configuration_handle_for_characteristic_with_uuid16(0, 0xffff, ORG_BLUETOOTH_CHARACTERISTIC_BATTERY_LEVEL); uint8_t buffer[] = {1, 0}; + uint16_t att_request_len = att_write_request(ATT_WRITE_REQUEST, value_handle, sizeof(buffer), buffer); mock_call_att_server_packet_handler(ATT_DATA_PACKET, att_con_handle, &att_request[0], att_request_len); } +TEST(ATT_SERVER, connection_complete_event){ + uint8_t buffer[21]; + buffer[0] = HCI_EVENT_LE_META; + buffer[1] = 19; + buffer[2] = HCI_SUBEVENT_LE_CONNECTION_COMPLETE; + + // call with wrong con_handle + little_endian_store_16(buffer,4,HCI_CON_HANDLE_INVALID); + mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer)); + + // call with correct con_handle + little_endian_store_16(buffer,4,att_con_handle); + mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer)); + + // use max MTU > ATT_REQUEST_BUFFER_SIZE + mock_l2cap_set_max_mtu(ATT_REQUEST_BUFFER_SIZE + 10); + mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer)); + + // wrong subevent + buffer[2] = 0xFF; + mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer)); +} + +TEST(ATT_SERVER, connection_disconnect_complete_event) { + uint8_t buffer[6]; + buffer[0] = HCI_EVENT_DISCONNECTION_COMPLETE; + buffer[1] = 19; + buffer[2] = 0; + + // call with wrong con_handle + little_endian_store_16(buffer, 3, HCI_CON_HANDLE_INVALID); + mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer)); + + // call with correct con_handle + little_endian_store_16(buffer, 3, att_con_handle); + mock_call_att_packet_handler(HCI_EVENT_PACKET, 0, &buffer[0], sizeof(buffer)); +} + + int main (int argc, const char * argv[]){ return CommandLineTestRunner::RunAllTests(argc, argv); } diff --git a/test/gatt_server/mock.c b/test/gatt_server/mock.c index efbf6656b..2d3cb9ad8 100644 --- a/test/gatt_server/mock.c +++ b/test/gatt_server/mock.c @@ -18,8 +18,8 @@ static btstack_packet_handler_t att_server_packet_handler; static void (*registered_hci_event_handler) (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) = NULL; static btstack_linked_list_t connections; -static const uint16_t max_mtu = 23; -static uint8_t l2cap_stack_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + 8 + max_mtu]; // pre buffer + HCI Header + L2CAP header +static uint16_t max_mtu = 23; +static uint8_t l2cap_stack_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + 8 + ATT_DEFAULT_MTU]; // pre buffer + HCI Header + L2CAP header static uint16_t gatt_client_handle = 0x40; static hci_connection_t hci_connection; @@ -62,7 +62,7 @@ int gap_reconnect_security_setup_active(hci_con_handle_t con_handle){ return 0; } -void att_init_connection(uint16_t con_handle){ +void hci_setup_le_connection(uint16_t con_handle){ hci_connection.att_connection.mtu = 23; hci_connection.att_connection.con_handle = con_handle; hci_connection.att_connection.max_mtu = 23; @@ -72,17 +72,32 @@ void att_init_connection(uint16_t con_handle){ hci_connection.att_server.ir_le_device_db_index = 0; + hci_connection.con_handle = con_handle; + if (btstack_linked_list_empty(&connections)){ btstack_linked_list_add(&connections, (btstack_linked_item_t *)&hci_connection); } } -void hci_add_event_handler(btstack_packet_callback_registration_t * callback_handler){ - registered_hci_event_handler = callback_handler->callback; +void mock_l2cap_set_max_mtu(uint16_t mtu){ + max_mtu = mtu; } -bool hci_can_send_acl_le_packet_now(void){ - return true; +void hci_deinit(void){ + hci_connection.att_connection.mtu = 0; + hci_connection.att_connection.con_handle = HCI_CON_HANDLE_INVALID; + hci_connection.att_connection.max_mtu = 0; + hci_connection.att_connection.encryption_key_size = 0; + hci_connection.att_connection.authenticated = 0; + hci_connection.att_connection.authorized = 0; + hci_connection.att_server.ir_le_device_db_index = 0; + hci_connection.att_server.notification_requests = NULL; + hci_connection.att_server.indication_requests = NULL; + connections = NULL; +} + +void hci_add_event_handler(btstack_packet_callback_registration_t * callback_handler){ + registered_hci_event_handler = callback_handler->callback; } bool hci_can_send_command_packet_now(void){ @@ -120,8 +135,7 @@ uint16_t l2cap_max_mtu(void){ } uint16_t l2cap_max_le_mtu(void){ - // printf("l2cap_max_mtu\n"); - return max_mtu; + return max_mtu; } void l2cap_init(void){} @@ -150,7 +164,7 @@ void l2cap_request_can_send_fix_channel_now_event(uint16_t handle, uint16_t chan uint8_t l2cap_send_prepared_connectionless(uint16_t handle, uint16_t cid, uint16_t len){ att_connection_t att_connection; - att_init_connection(handle); + hci_setup_le_connection(handle); uint8_t response[max_mtu]; uint16_t response_len = att_handle_request(&att_connection, l2cap_get_outgoing_buffer(), len, &response[0]); if (response_len){ @@ -204,30 +218,17 @@ hci_connection_t * hci_connection_for_bd_addr_and_type(const bd_addr_t addr, bd_ return NULL; } hci_connection_t * hci_connection_for_handle(hci_con_handle_t con_handle){ - if (con_handle != hci_connection.con_handle) return NULL; - return &hci_connection; + if (hci_connection.con_handle != con_handle){ + return NULL; + } + return &hci_connection; } + void hci_connections_get_iterator(btstack_linked_list_iterator_t *it){ // printf("hci_connections_get_iterator not implemented in mock backend\n"); btstack_linked_list_iterator_init(it, &connections); } -// int hci_send_cmd(const hci_cmd_t *cmd, ...){ -// // printf("hci_send_cmd opcode 0x%02x\n", cmd->opcode); -// return 0; -// } - -// int hci_can_send_packet_now_using_packet_buffer(uint8_t packet_type){ -// return 1; -// } - -// void hci_disconnect_security_block(hci_con_handle_t con_handle){ -// printf("hci_disconnect_security_block \n"); -// } - -// void hci_dump_log(const char * format, ...){ -// printf("hci_disconnect_security_block \n"); -// } void l2cap_run(void){ } @@ -259,6 +260,10 @@ void mock_call_att_server_packet_handler(uint8_t packet_type, uint16_t channel, (*att_server_packet_handler)(packet_type, channel, packet, size); } +void mock_call_att_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ + (*registered_hci_event_handler)(packet_type, channel, packet, size); +} + void att_dispatch_register_server(btstack_packet_handler_t packet_handler){ att_server_packet_handler = packet_handler; } @@ -279,3 +284,4 @@ void att_dispatch_server_request_can_send_now_event(hci_con_handle_t con_handle) att_server_packet_handler(HCI_EVENT_PACKET, 0, (uint8_t*)event, sizeof(event)); } } +