#include #include #include #include #include "CppUTest/TestHarness.h" #include "CppUTest/CommandLineTestRunner.h" #include "ble/att_db.h" #include "ble/att_db_util.h" #include "btstack_util.h" #include "bluetooth.h" #include "btstack_audio.h" #include "hal_audio.h" #include "hal_cpu.h" #include "hal_em9304_spi.h" #include "hal_flash_bank.h" #include "hal_flash_bank_memory.h" #include "hal_led.h" #include "hal_stdin.h" #include "hal_tick.h" #include "hal_time_ms.h" #include "hal_uart_dma.h" #include "btstack_run_loop.h" #include "btstack_run_loop_embedded.h" #include "btstack_memory.h" #include "btstack_debug.h" #include "l2cap_signaling.h" // quick mock // hal_cpu void hal_cpu_disable_irqs(void){} void hal_cpu_enable_irqs(void){} void hal_cpu_enable_irqs_and_sleep(void){} // hal_em9304_spi void hal_em9304_spi_init(void){} void hal_em9304_spi_deinit(void){} void hal_em9304_spi_set_ready_callback(void (*callback)(void)){} void hal_em9304_spi_set_transfer_done_callback(void (*callback)(void)){} void hal_em9304_spi_enable_ready_interrupt(void){} void hal_em9304_spi_disable_ready_interrupt(void){} int hal_em9304_spi_get_ready(){ return 0; } void hal_em9304_spi_set_chip_select(int enable){} int hal_em9304_spi_get_fullduplex_support(void){ return 0; } void hal_em9304_spi_transceive(const uint8_t * tx_data, uint8_t * rx_data, uint16_t len){} void hal_em9304_spi_transmit(const uint8_t * tx_data, uint16_t len){} void hal_em9304_spi_receive(uint8_t * rx_data, uint16_t len){} // hal_stdin_setup void hal_stdin_setup(void (*handler)(char c)){} // hal_uart_dma void hal_uart_dma_init(void){} void hal_uart_dma_set_block_received( void (*callback)(void)){} void hal_uart_dma_set_block_sent( void (*callback)(void)){} int hal_uart_dma_set_baud(uint32_t baud){ return 0; } int hal_uart_dma_set_flowcontrol(int flowcontrol){ return 0;} void hal_uart_dma_send_block(const uint8_t *buffer, uint16_t length){} void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t len){} void hal_uart_dma_set_csr_irq_handler( void (*csr_irq_handler)(void)){} void hal_uart_dma_set_sleep(uint8_t sleep){} int hal_uart_dma_get_supported_sleep_modes(void){ return 0; } // void hal_uart_dma_set_sleep_mode(btstack_uart_sleep_mode_t sleep_mode){} // hal_audio_sink void hal_audio_sink_init(uint8_t channels, uint32_t sample_rate,void (*buffer_played_callback)(uint8_t buffer_index)){} uint16_t hal_audio_sink_get_num_output_buffers(void){ return 0; } uint16_t hal_audio_sink_get_num_output_buffer_samples(void){ return 0; } int16_t * hal_audio_sink_get_output_buffer(uint8_t buffer_index){ return NULL; } void hal_audio_sink_start(void){} void hal_audio_sink_stop(void){} void hal_audio_sink_close(void){} void hal_audio_source_init(uint8_t channels, uint32_t sample_rate, void (*buffer_recorded_callback)(const int16_t * buffer, uint16_t num_samples)){} void hal_audio_source_start(void){} void hal_audio_source_stop(void){} void hal_audio_source_close(void){} #define HEARTBEAT_PERIOD_MS 1000 static btstack_timer_source_t timer_1; static btstack_timer_source_t timer_2; static btstack_data_source_t data_source; static bool data_source_called; static bool timer_called; static void heartbeat_timeout_handler(btstack_timer_source_t * ts){ UNUSED(ts); timer_called = true; } static void data_source_handler(btstack_data_source_t * ds, btstack_data_source_callback_type_t callback_type){ UNUSED(ds); UNUSED(callback_type); data_source_called = true; } TEST_GROUP(Embedded){ void setup(void){ // start with BTstack init - especially configure HCI Transport btstack_memory_init(); btstack_run_loop_init(btstack_run_loop_embedded_get_instance()); btstack_run_loop_set_timer_handler(&timer_1, heartbeat_timeout_handler); } void teardown(void){ btstack_run_loop_deinit(); btstack_memory_deinit(); } }; TEST(Embedded, Init){ btstack_run_loop_set_timer(&timer_1, HEARTBEAT_PERIOD_MS); btstack_run_loop_add_timer(&timer_1); btstack_run_loop_embedded_execute_once(); btstack_run_loop_embedded_trigger(); btstack_run_loop_embedded_execute_once(); btstack_run_loop_get_time_ms(); btstack_run_loop_timer_dump(); btstack_run_loop_remove_timer(&timer_1); (void) btstack_run_loop_get_timer_context(&timer_1); } TEST(Embedded, DataSource){ btstack_run_loop_set_data_source_handler(&data_source, &data_source_handler); btstack_run_loop_set_data_source_fd(&data_source, 0); btstack_run_loop_set_data_source_handle(&data_source, NULL); btstack_run_loop_enable_data_source_callbacks(&data_source, DATA_SOURCE_CALLBACK_POLL); btstack_run_loop_disable_data_source_callbacks(&data_source, DATA_SOURCE_CALLBACK_POLL); btstack_run_loop_add_data_source(&data_source); btstack_run_loop_remove_data_source(&data_source); } TEST_GROUP(RunLoopBase){ void setup(void){ btstack_memory_init(); btstack_run_loop_base_init(); data_source_called = false; timer_called = false; } void teardown(void){ btstack_memory_deinit(); } }; TEST(RunLoopBase, DataSource){ btstack_run_loop_set_data_source_handler(&data_source, &data_source_handler); btstack_run_loop_base_enable_data_source_callbacks(&data_source, DATA_SOURCE_CALLBACK_POLL); btstack_run_loop_base_add_data_source(&data_source); btstack_run_loop_base_disable_data_source_callbacks(&data_source, DATA_SOURCE_CALLBACK_POLL); btstack_run_loop_base_remove_data_source(&data_source); } TEST(RunLoopBase,Timer){ const uint32_t timeout_1 = 7; const uint32_t timeout_2 = 10; const uint32_t now_1 = 5; const uint32_t now_2 = 11; const uint32_t now_3 = 33; btstack_run_loop_set_timer_handler(&timer_1, heartbeat_timeout_handler); timer_1.timeout = timeout_1; btstack_run_loop_set_timer_handler(&timer_2, heartbeat_timeout_handler); timer_2.timeout = timeout_2; // test add/remove // add timer 2 btstack_run_loop_base_add_timer(&timer_2); CHECK(btstack_run_loop_base_timers != NULL); // remove timer btstack_run_loop_base_remove_timer(&timer_2); CHECK(btstack_run_loop_base_timers == NULL); // add timer 2 btstack_run_loop_base_add_timer(&timer_2); // add timer 1 btstack_run_loop_base_add_timer(&timer_1); // dump timers btstack_run_loop_base_dump_timer(); // process timers for now_1 btstack_run_loop_base_process_timers(now_1); CHECK(timer_called == false); CHECK(btstack_run_loop_base_timers != NULL); // get next timeout int next_timeout = btstack_run_loop_base_get_time_until_timeout(now_1); CHECK(next_timeout == (timeout_1 - now_1)); // get next timeout in future - timeout should be 0 = now next_timeout = btstack_run_loop_base_get_time_until_timeout(now_3); CHECK(next_timeout == 0); // process timers for now_2 btstack_run_loop_base_process_timers(now_2); CHECK(timer_called == true); CHECK(btstack_run_loop_base_timers == NULL); // get next timeout next_timeout = btstack_run_loop_base_get_time_until_timeout(now_2); CHECK(next_timeout == -1); } TEST(RunLoopBase, Overrun){ const uint32_t t1 = 0xfffffff0UL; // -16 const uint32_t t2 = 0xfffffff8UL; // -8 const uint32_t t3 = 50UL; int next_timeout; btstack_run_loop_set_timer_handler(&timer_1, heartbeat_timeout_handler); timer_1.timeout = t1 + 20; // overrun // add timer btstack_run_loop_base_add_timer(&timer_1); // verify timeout until correct next_timeout = btstack_run_loop_base_get_time_until_timeout(t1); CHECK(next_timeout == 20); // process timers for t2 btstack_run_loop_base_process_timers(t2); CHECK(timer_called == false); // process timers for t3 btstack_run_loop_base_process_timers(t3); CHECK(timer_called == true); } TEST_GROUP(BTstackUtil){ void setup(void){ } void teardown(void){ } }; TEST(BTstackUtil, btstack_next_cid_ignoring_zero){ CHECK_EQUAL(1, btstack_next_cid_ignoring_zero(0)); CHECK_EQUAL(5, btstack_next_cid_ignoring_zero(4)); CHECK_EQUAL(1, btstack_next_cid_ignoring_zero(0xFFFF)); } TEST(BTstackUtil, bd_addr_cmp){ bd_addr_t a = {0}; bd_addr_t b = {0}; CHECK_EQUAL(0, bd_addr_cmp(a, b)); bd_addr_t a1 = {0xBC, 0xEC, 0x5D, 0xE6, 0x15, 0x03}; bd_addr_t b1 = {0xBC, 0xEC, 0x5D, 0xE6, 0x15, 0x03}; CHECK_EQUAL(0, bd_addr_cmp(a1, b1)); bd_addr_t a3 = {0xBC, 0xEC, 0x5D, 0xE6, 0x15, 0x03}; bd_addr_t b3 = {0xCB, 0xEC, 0x5D, 0xE6, 0x15, 0x03}; } TEST(BTstackUtil, bd_addr_copy){ bd_addr_t a = {0xBC, 0xEC, 0x5D, 0xE6, 0x15, 0x03}; bd_addr_t b = {0}; CHECK(0 != bd_addr_cmp(a, b)); bd_addr_copy(a,b); CHECK_EQUAL(0, bd_addr_cmp(a, b)); } TEST(BTstackUtil, little_endian_read){ const uint8_t buffer[] = {0xBC, 0xEC, 0x5D, 0xE6, 0x15, 0x03}; uint32_t value; value = little_endian_read_16(buffer, 0); CHECK_EQUAL(0xECBC, value); value = little_endian_read_24(buffer, 0); CHECK_EQUAL(0x5DECBC, value); value = little_endian_read_32(buffer, 0); CHECK_EQUAL(0xE65DECBC, value); } TEST(BTstackUtil, little_endian_store){ uint8_t buffer[6]; uint32_t expected_value = 0xE65DECBC; uint32_t value; memset(buffer, 0, sizeof(buffer)); little_endian_store_16(buffer, 0, expected_value); value = little_endian_read_16(buffer, 0); CHECK_EQUAL(0xECBC, value); memset(buffer, 0, sizeof(buffer)); little_endian_store_24(buffer, 0, expected_value); value = little_endian_read_24(buffer, 0); CHECK_EQUAL(0x5DECBC, value); memset(buffer, 0, sizeof(buffer)); little_endian_store_32(buffer, 0, expected_value); value = little_endian_read_32(buffer, 0); CHECK_EQUAL(0xE65DECBC, value); } TEST(BTstackUtil, big_endian_read){ const uint8_t buffer[] = {0xBC, 0xEC, 0x5D, 0xE6, 0x15, 0x03}; uint32_t value; value = big_endian_read_16(buffer, 0); CHECK_EQUAL(0xBCEC, value); value = big_endian_read_24(buffer, 0); CHECK_EQUAL(0xBCEC5D, value); value = big_endian_read_32(buffer, 0); CHECK_EQUAL(0xBCEC5DE6, value); } TEST(BTstackUtil, big_endian_store){ uint8_t buffer[6]; uint32_t expected_value = 0xE65DECBC; uint32_t value; memset(buffer, 0, sizeof(buffer)); big_endian_store_16(buffer, 0, expected_value); value = big_endian_read_16(buffer, 0); CHECK_EQUAL(0xECBC, value); memset(buffer, 0, sizeof(buffer)); big_endian_store_24(buffer, 0, expected_value); value = big_endian_read_24(buffer, 0); CHECK_EQUAL(0x5DECBC, value); memset(buffer, 0, sizeof(buffer)); big_endian_store_32(buffer, 0, expected_value); value = big_endian_read_32(buffer, 0); CHECK_EQUAL(0xE65DECBC, value); } TEST(BTstackUtil, reverse_bytes){ uint8_t src[32]; uint8_t buffer[32]; uint32_t value; int i; for (i = 0; i < sizeof(src); i++){ src[i] = i + 1; } memset(buffer, 0, sizeof(buffer)); reverse_bytes(src, buffer, sizeof(buffer)); value = big_endian_read_32(buffer, 0); CHECK_EQUAL(0x201F1E1D, value); memset(buffer, 0, sizeof(buffer)); reverse_24(src, buffer); value = big_endian_read_32(buffer, 0); CHECK_EQUAL(0x03020100, value); memset(buffer, 0, sizeof(buffer)); reverse_48(src, buffer); value = big_endian_read_32(buffer, 0); CHECK_EQUAL(0x06050403, value); memset(buffer, 0, sizeof(buffer)); reverse_56(src, buffer); value = big_endian_read_32(buffer, 0); CHECK_EQUAL(0x07060504, value); memset(buffer, 0, sizeof(buffer)); reverse_64(src, buffer); value = big_endian_read_32(buffer, 0); CHECK_EQUAL(0x08070605, value); memset(buffer, 0, sizeof(buffer)); reverse_128(src, buffer); value = big_endian_read_32(buffer, 0); CHECK_EQUAL(0x100F0E0D, value); memset(buffer, 0, sizeof(buffer)); reverse_256(src, buffer); value = big_endian_read_32(buffer, 0); CHECK_EQUAL(0x201F1E1D, value); } TEST(BTstackUtil, reverse_bd_addr){ bd_addr_t src = {0xBC, 0xEC, 0x5D, 0xE6, 0x15, 0x03}; bd_addr_t dest = {0}; reverse_bd_addr(src, dest); uint32_t value = big_endian_read_32(dest, 0); CHECK_EQUAL(0x0315E65D, value); } TEST(BTstackUtil, btstack_min_max){ uint32_t a = 30; uint32_t b = 100; CHECK_EQUAL(a, btstack_min(a,b)); CHECK_EQUAL(a, btstack_min(b,a)); CHECK_EQUAL(b, btstack_max(a,b)); CHECK_EQUAL(b, btstack_max(b,a)); } TEST(BTstackUtil, char_for_nibble){ CHECK_EQUAL('A', char_for_nibble(10)); CHECK_EQUAL('?', char_for_nibble(20)); // CHECK_EQUAL('?', char_for_nibble(-5)); } TEST(BTstackUtil, nibble_for_char){ CHECK_EQUAL(0, nibble_for_char('0')); CHECK_EQUAL(5, nibble_for_char('5')); CHECK_EQUAL(9, nibble_for_char('9')); CHECK_EQUAL(10, nibble_for_char('a')); CHECK_EQUAL(12, nibble_for_char('c')); CHECK_EQUAL(15, nibble_for_char('f')); CHECK_EQUAL(10, nibble_for_char('A')); CHECK_EQUAL(12, nibble_for_char('C')); CHECK_EQUAL(15, nibble_for_char('F')); CHECK_EQUAL(-1, nibble_for_char('-')); } TEST(BTstackUtil, logging){ uint8_t data[6 * 16 + 5] = {0x54, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x69, 0x6e, 0x66, 0x6f}; #ifdef ENABLE_LOG_DEBUG log_debug_hexdump(data, sizeof(data)); #endif #ifdef ENABLE_LOG_INFO log_info_hexdump(data, sizeof(data)); sm_key_t key = {0x54, 0x65, 0x73, 0x74, 0x20, 0x6c, 0x6f, 0x67, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x01, 0x014, 0xFF}; log_info_key("test key", key); #endif } TEST(BTstackUtil, uuids){ uint32_t shortUUID = 0x44445555; uint8_t uuid[16]; uint8_t uuid128[] = {0x44, 0x44, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB}; memset(uuid, 0, sizeof(uuid)); uuid_add_bluetooth_prefix(uuid, shortUUID); MEMCMP_EQUAL(uuid128, uuid, sizeof(uuid)); CHECK_EQUAL(1, uuid_has_bluetooth_prefix(uuid128)); uuid128[5] = 0xff; CHECK(1 != uuid_has_bluetooth_prefix(uuid128)); char * uuid128_str = uuid128_to_str(uuid128); STRCMP_EQUAL("44445555-00FF-1000-8000-00805F9B34FB", uuid128_str); } TEST(BTstackUtil, bd_addr_utils){ const bd_addr_t addr = {0xBC, 0xEC, 0x5D, 0xE6, 0x15, 0x03}; char * device_addr_string = "BC:EC:5D:E6:15:03"; char * addr_str = bd_addr_to_str(addr); STRCMP_EQUAL(device_addr_string, addr_str); uint8_t device_name[50]; strcpy((char *)device_name, "Device name 00:00:00:00:00:00"); btstack_replace_bd_addr_placeholder(device_name, strlen((const char*) device_name), addr); STRCMP_EQUAL("Device name BC:EC:5D:E6:15:03", (const char *) device_name); bd_addr_t device_addr; CHECK_EQUAL(1, sscanf_bd_addr(device_addr_string, device_addr)); MEMCMP_EQUAL(addr, device_addr, sizeof(addr)); CHECK_EQUAL(1, sscanf_bd_addr("BC EC 5D E6 15 03", device_addr)); CHECK_EQUAL(1, sscanf_bd_addr("BC-EC-5D-E6-15-03", device_addr)); CHECK_EQUAL(0, sscanf_bd_addr("", device_addr)); CHECK_EQUAL(0, sscanf_bd_addr("GG-EC-5D-E6-15-03", device_addr)); CHECK_EQUAL(0, sscanf_bd_addr("8G-EC-5D-E6-15-03", device_addr)); CHECK_EQUAL(0, sscanf_bd_addr("BCxECx5DxE6:15:03", device_addr)); } TEST(BTstackUtil, atoi){ CHECK_EQUAL(102, btstack_atoi("102")); CHECK_EQUAL(0, btstack_atoi("-102")); CHECK_EQUAL(1, btstack_atoi("1st")); CHECK_EQUAL(1, btstack_atoi("1st2")); } TEST(BTstackUtil, string_len_for_uint32){ CHECK_EQUAL(1, string_len_for_uint32(9)); CHECK_EQUAL(2, string_len_for_uint32(19)); CHECK_EQUAL(3, string_len_for_uint32(109)); CHECK_EQUAL(4, string_len_for_uint32(1009)); CHECK_EQUAL(5, string_len_for_uint32(10009)); CHECK_EQUAL(6, string_len_for_uint32(100009)); CHECK_EQUAL(7, string_len_for_uint32(1000009)); CHECK_EQUAL(8, string_len_for_uint32(10000009)); CHECK_EQUAL(9, string_len_for_uint32(100000009)); CHECK_EQUAL(10, string_len_for_uint32(1000000000)); } TEST(BTstackUtil, count_set_bits_uint32){ CHECK_EQUAL(4, count_set_bits_uint32(0x0F)); } TEST(BTstackUtil, crc8){ uint8_t data[] = {1,2,3,4,5,6,7,8,9}; CHECK_EQUAL(84, btstack_crc8_calc(data, sizeof(data))); CHECK_EQUAL(0, btstack_crc8_check(data, sizeof(data), 84)); CHECK_EQUAL(1, btstack_crc8_check(data, sizeof(data), 74)); } TEST_GROUP(L2CAPSignaling){ void setup(void){ } void teardown(void){ } }; static uint16_t l2cap_send_le_signaling_packet(hci_con_handle_t handle, L2CAP_SIGNALING_COMMANDS cmd, int identifier, ...){ static uint8_t acl_buffer[100]; va_list argptr; va_start(argptr, identifier); uint16_t len = l2cap_create_signaling_le(acl_buffer, handle, cmd, identifier, argptr); va_end(argptr); return len; } TEST(L2CAPSignaling, l2cap_create_signaling_le_invalid_cmd){ uint16_t size = l2cap_send_le_signaling_packet((hci_con_handle_t) 0x01, (L2CAP_SIGNALING_COMMANDS)(CONNECTION_PARAMETER_UPDATE_REQUEST-1), 1); CHECK_EQUAL(0, size); } TEST(L2CAPSignaling, l2cap_create_signaling_le_invalid_cmd_0){ uint16_t size = l2cap_send_le_signaling_packet((hci_con_handle_t) 0x01, (L2CAP_SIGNALING_COMMANDS)0, 1); CHECK_EQUAL(0, size); } TEST(L2CAPSignaling, l2cap_create_signaling_le_invalid_cmd_FF){ uint16_t size = l2cap_send_le_signaling_packet((hci_con_handle_t) 0x01, (L2CAP_SIGNALING_COMMANDS)0xFF, 1); CHECK_EQUAL(0, size); } TEST(L2CAPSignaling, l2cap_create_signaling_le_invalid_cmd_M_format){ uint16_t size = l2cap_send_le_signaling_packet((hci_con_handle_t) 0x01, COMMAND_WITH_INVALID_FORMAT, 1); CHECK_EQUAL(12, size); } TEST(L2CAPSignaling, l2cap_create_signaling_le_valid_cmd_2_format){ uint16_t size = l2cap_send_le_signaling_packet((hci_con_handle_t) 0x01, INFORMATION_REQUEST, 1, 0); CHECK_EQUAL(14, size); } TEST(L2CAPSignaling, l2cap_create_signaling_le_valid_cmd_D_format){ uint16_t size = l2cap_send_le_signaling_packet((hci_con_handle_t) 0x01, ECHO_REQUEST, 1, 0, NULL); CHECK_EQUAL(12, size); } int main (int argc, const char * argv[]){ return CommandLineTestRunner::RunAllTests(argc, argv); }