From 1470db0ca8ab4772a606fa66265361030a4953d3 Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 2 Apr 2020 16:22:07 +0200 Subject: [PATCH] test/gap: unit test for gap le scanning --- src/hci.c | 4 ++ src/hci.h | 3 + test/Makefile | 1 + test/gap/Makefile | 48 ++++++++++++++ test/gap/test_le_scan.c | 139 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 195 insertions(+) create mode 100644 test/gap/Makefile create mode 100644 test/gap/test_le_scan.c diff --git a/src/hci.c b/src/hci.c index 2fa460c9a..72c607cdd 100644 --- a/src/hci.c +++ b/src/hci.c @@ -5405,4 +5405,8 @@ void hci_free_connections_fuzz(void){ btstack_memory_hci_connection_free(con); } } +void hci_simulate_working_fuzz(void){ + hci_init_done(); + hci_stack->num_cmd_packets = 255; +} #endif diff --git a/src/hci.h b/src/hci.h index 11e06350a..d3eaeeff7 100644 --- a/src/hci.h +++ b/src/hci.h @@ -1251,6 +1251,9 @@ void hci_setup_test_connections_fuzz(void); // free all connections, used for fuzzing void hci_free_connections_fuzz(void); +// simulate stack bootup +void hci_simulate_working_fuzz(void); + #if defined __cplusplus } #endif diff --git a/test/Makefile b/test/Makefile index 684886c71..d2a6a4868 100644 --- a/test/Makefile +++ b/test/Makefile @@ -14,6 +14,7 @@ SUBDIRS = \ flash_tlv \ gatt_client \ gatt_server \ + gap \ hfp \ hid_parser \ linked_list \ diff --git a/test/gap/Makefile b/test/gap/Makefile new file mode 100644 index 000000000..6c0cb4dba --- /dev/null +++ b/test/gap/Makefile @@ -0,0 +1,48 @@ +CC = g++ + +# Requirements: cpputest.github.io + +BTSTACK_ROOT = ../.. + +CFLAGS = -DUNIT_TEST -x c++ -g -Wall -Wnarrowing -Wconversion-null -I. -I../ -I${BTSTACK_ROOT}/src +CFLAGS += -fsanitize=address +CFLAGS += -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION +CFLAGS += -fprofile-arcs -ftest-coverage +LDFLAGS += -lCppUTest -lCppUTestExt + +VPATH += ${BTSTACK_ROOT}/src +VPATH += ${BTSTACK_ROOT}/src/ble +VPATH += ${BTSTACK_ROOT}/platform/posix + +COMMON = \ + ad_parser.c \ + btstack_linked_list.c \ + btstack_memory.c \ + btstack_memory_pool.c \ + btstack_util.c \ + btstack_run_loop.c \ + hci.c \ + hci_cmd.c \ + hci_dump.c \ + le_device_db_memory.c \ + +COMMON_OBJ = $(COMMON:.c=.o) + +all: test_le_scan + +# compile .ble description +profile.h: profile.gatt + python ${BTSTACK_ROOT}/tool/compile_gatt.py $< $@ + +test_le_scan: ${COMMON_OBJ} test_le_scan.o + ${CC} ${COMMON_OBJ} test_le_scan.o ${CFLAGS} ${LDFLAGS} -o $@ + +test: all + ./test_le_scan + +clean: + rm -f test_le_scan + rm -f *.o + rm -rf *.dSYM + rm -f *.gcno *.gcda + diff --git a/test/gap/test_le_scan.c b/test/gap/test_le_scan.c new file mode 100644 index 000000000..78721baab --- /dev/null +++ b/test/gap/test_le_scan.c @@ -0,0 +1,139 @@ +#include +#include +#include +#include + +#include "CppUTest/TestHarness.h" +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTestExt/MockSupport.h" + +#include "hci_cmd.h" + +#include "btstack_memory.h" +#include "hci.h" +#include "ble/gatt_client.h" +#include "btstack_event.h" +#include "hci_dump.h" +#include "btstack_debug.h" + +typedef struct { + uint8_t type; + uint16_t size; + uint8_t buffer[258]; +} hci_packet_t; + +#define MAX_HCI_PACKETS 10 +static uint16_t transport_count_packets; +static hci_packet_t transport_packets[MAX_HCI_PACKETS]; + +static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size); + +static const uint8_t packet_sent_event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0}; + +static int hci_transport_test_set_baudrate(uint32_t baudrate){ + return 0; +} + +static int hci_transport_test_can_send_now(uint8_t packet_type){ + return 1; +} + +static int hci_transport_test_send_packet(uint8_t packet_type, uint8_t * packet, int size){ + btstack_assert(transport_count_packets < MAX_HCI_PACKETS); + memcpy(transport_packets[transport_count_packets].buffer, packet, size); + transport_packets[transport_count_packets].type = packet_type; + transport_packets[transport_count_packets].size = size; + transport_count_packets++; + // notify upper stack that it can send again + packet_handler(HCI_EVENT_PACKET, (uint8_t *) &packet_sent_event[0], sizeof(packet_sent_event)); + return 0; +} + +static void hci_transport_test_init(const void * transport_config){ +} + +static int hci_transport_test_open(void){ + return 0; +} + +static int hci_transport_test_close(void){ + return 0; +} + +static void hci_transport_test_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ + packet_handler = handler; +} + +static const hci_transport_t hci_transport_test = { + /* const char * name; */ "TEST", + /* void (*init) (const void *transport_config); */ &hci_transport_test_init, + /* int (*open)(void); */ &hci_transport_test_open, + /* int (*close)(void); */ &hci_transport_test_close, + /* void (*register_packet_handler)(void (*handler)(...); */ &hci_transport_test_register_packet_handler, + /* int (*can_send_packet_now)(uint8_t packet_type); */ &hci_transport_test_can_send_now, + /* int (*send_packet)(...); */ &hci_transport_test_send_packet, + /* int (*set_baudrate)(uint32_t baudrate); */ &hci_transport_test_set_baudrate, + /* void (*reset_link)(void); */ NULL, + /* void (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL, +}; + +static uint16_t next_hci_packet; + +void CHECK_EQUAL_ARRAY(const uint8_t * expected, uint8_t * actual, int size){ + for (int i=0; iopcode, actual_opcode); +} + +TEST_GROUP(GAP_LE){ + void setup(void){ + transport_count_packets = 0; + next_hci_packet = 0; + hci_init(&hci_transport_test, NULL); + hci_simulate_working_fuzz(); + // register for HCI events + mock().expectOneCall("hci_can_send_packet_now_using_packet_buffer").andReturnValue(1); + } + void teardown(void){ + mock().clear(); + } +}; + +TEST(GAP_LE, ScanStart){ + log_info("TEST(GAP_LE, ScanStart)"); + gap_start_scan(); + CHECK_EQUAL(1, transport_count_packets); + CHECK_HCI_COMMAND(&hci_le_set_scan_enable); +} +TEST(GAP_LE, ScanStartStop){ + log_info("TEST(GAP_LE, ScanStartStop)"); + gap_start_scan(); + gap_stop_scan(); + CHECK_EQUAL(2, transport_count_packets); + CHECK_HCI_COMMAND(&hci_le_set_scan_enable); + CHECK_HCI_COMMAND(&hci_le_set_scan_enable); +} + +TEST(GAP_LE, ScanStartParam){ + log_info("TEST(GAP_LE, ScanStartParam)"); + gap_start_scan(); + gap_set_scan_parameters(0, 10, 10); + CHECK_EQUAL(4, transport_count_packets); + CHECK_HCI_COMMAND(&hci_le_set_scan_enable); + CHECK_HCI_COMMAND(&hci_le_set_scan_enable); + CHECK_HCI_COMMAND(&hci_le_set_scan_parameters); + CHECK_HCI_COMMAND(&hci_le_set_scan_enable); +} + +int main (int argc, const char * argv[]){ + const char * log_path = "/tmp/test_scan.pklg"; + printf("Log: %s\n", log_path); + hci_dump_open(log_path, HCI_DUMP_PACKETLOGGER); + return CommandLineTestRunner::RunAllTests(argc, argv); +}