test: add gatt server to coverage

This commit is contained in:
Matthias Ringwald 2019-09-23 11:03:53 +02:00
parent 62faac7e54
commit f97394917c
6 changed files with 463 additions and 0 deletions

3
test/gatt_server/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
gatt_client_test
le_central
profile.h

49
test/gatt_server/Makefile Normal file
View File

@ -0,0 +1,49 @@
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 += -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 \
att_server.c \
att_db.c \
att_dispatch.c \
btstack_linked_list.c \
btstack_memory.c \
btstack_memory_pool.c \
btstack_util.c \
hci_cmd.c \
hci_dump.c \
le_device_db_memory.c \
mock.c \
btstack_tlv.c \
COMMON_OBJ = $(COMMON:.c=.o)
all: gatt_server_test
# compile .ble description
profile.h: profile.gatt
python ${BTSTACK_ROOT}/tool/compile_gatt.py $< $@
gatt_server_test: profile.h ${COMMON_OBJ} gatt_server_test.o
${CC} ${COMMON_OBJ} gatt_server_test.o ${CFLAGS} ${LDFLAGS} -o $@
test: all
./gatt_server_test
clean:
rm -f gatt_server_test
rm -f *.o
rm -rf *.dSYM
rm -f *.gcno *.gcda

View File

@ -0,0 +1,37 @@
//
// btstack_config.h for most tests
//
#ifndef __BTSTACK_CONFIG
#define __BTSTACK_CONFIG
// Port related features
#define HAVE_MALLOC
#define HAVE_POSIX_TIME
#define HAVE_POSIX_FILE_IO
#define HAVE_BTSTACK_STDIN
// BTstack features that can be enabled
#define ENABLE_BLE
#define ENABLE_CLASSIC
// #define ENABLE_LOG_DEBUG
#define ENABLE_LOG_ERROR
#define ENABLE_LOG_INFO
#define ENABLE_SDP_DES_DUMP
#define ENABLE_SDP_EXTRA_QUERIES
#define ENABLE_LE_SECURE_CONNECTIONS
#define ENABLE_LE_SIGNED_WRITE
#define ENABLE_LE_PERIPHERAL
#define ENABLE_LE_CENTRAL
#define ENABLE_SDP_EXTRA_QUERIES
#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
// BTstack configuration. buffers, sizes, ...
#define HCI_ACL_PAYLOAD_SIZE 52
#define HCI_INCOMING_PRE_BUFFER_SIZE 4
#define MAX_NR_LE_DEVICE_DB_ENTRIES 4
#define NVM_NUM_LINK_KEYS 2
#endif

View File

@ -0,0 +1,28 @@
// *****************************************************************************
//
// test rfcomm query tests
//
// *****************************************************************************
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CppUTest/TestHarness.h"
#include "CppUTest/CommandLineTestRunner.h"
#include "hci_cmd.h"
#include "btstack_memory.h"
#include "hci.h"
#include "hci_dump.h"
#include "ble/att_server.h"
#include "ble/att_db.h"
#include "profile.h"
int main (int argc, const char * argv[]){
return CommandLineTestRunner::RunAllTests(argc, argv);
}

216
test/gatt_server/mock.c Normal file
View File

@ -0,0 +1,216 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hci.h"
#include "hci_dump.h"
#include "l2cap.h"
#include "ble/att_db.h"
#include "ble/gatt_client.h"
#include "ble/sm.h"
static btstack_packet_handler_t att_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 gatt_client_handle = 0x40;
static hci_connection_t hci_connection;
uint16_t get_gatt_client_handle(void){
return gatt_client_handle;
}
void mock_simulate_command_complete(const hci_cmd_t *cmd){
uint8_t packet[] = {HCI_EVENT_COMMAND_COMPLETE, 4, 1, (uint8_t) (cmd->opcode & 0xff), (uint8_t) (cmd->opcode >> 8), 0};
registered_hci_event_handler(HCI_EVENT_PACKET, 0, (uint8_t *)&packet, sizeof(packet));
}
void mock_simulate_hci_state_working(void){
uint8_t packet[3] = {BTSTACK_EVENT_STATE, 0, HCI_STATE_WORKING};
registered_hci_event_handler(HCI_EVENT_PACKET, 0, (uint8_t *)&packet, 3);
}
void mock_simulate_connected(void){
uint8_t packet[] = {0x3E, 0x13, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x9B, 0x77, 0xD1, 0xF7, 0xB1, 0x34, 0x50, 0x00, 0x00, 0x00, 0xD0, 0x07, 0x05};
registered_hci_event_handler(HCI_EVENT_PACKET, 0, (uint8_t *)&packet, sizeof(packet));
}
void mock_simulate_scan_response(void){
uint8_t packet[] = {0xE2, 0x13, 0xE2, 0x01, 0x34, 0xB1, 0xF7, 0xD1, 0x77, 0x9B, 0xCC, 0x09, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
registered_hci_event_handler(HCI_EVENT_PACKET, 0, (uint8_t *)&packet, sizeof(packet));
}
void gap_start_scan(void){
}
void gap_stop_scan(void){
}
uint8_t gap_connect(bd_addr_t addr, bd_addr_type_t addr_type){
return 0;
}
void gap_set_scan_parameters(uint8_t scan_type, uint16_t scan_interval, uint16_t scan_window){
}
int gap_reconnect_security_setup_active(hci_con_handle_t con_handle){
UNUSED(con_handle);
return 0;
}
static void att_init_connection(att_connection_t * att_connection){
att_connection->mtu = 23;
att_connection->max_mtu = 23;
att_connection->encryption_key_size = 0;
att_connection->authenticated = 0;
att_connection->authorized = 0;
}
int hci_can_send_acl_le_packet_now(void){
return 1;
}
int l2cap_can_send_connectionless_packet_now(void){
return 1;
}
uint8_t *l2cap_get_outgoing_buffer(void){
// printf("l2cap_get_outgoing_buffer\n");
return (uint8_t *)&l2cap_stack_buffer; // 8 bytes
}
uint16_t l2cap_max_mtu(void){
// printf("l2cap_max_mtu\n");
return max_mtu;
}
uint16_t l2cap_max_le_mtu(void){
// printf("l2cap_max_mtu\n");
return max_mtu;
}
void l2cap_init(void){}
void l2cap_register_fixed_channel(btstack_packet_handler_t packet_handler, uint16_t channel_id) {
att_packet_handler = packet_handler;
}
void hci_add_event_handler(btstack_packet_callback_registration_t * callback_handler){
registered_hci_event_handler = callback_handler->callback;
}
int l2cap_reserve_packet_buffer(void){
return 1;
}
void l2cap_release_packet_buffer(void){
}
int l2cap_can_send_fixed_channel_packet_now(uint16_t handle, uint16_t channel_id){
return 1;
}
void l2cap_request_can_send_fix_channel_now_event(uint16_t handle, uint16_t channel_id){
uint8_t event[] = { L2CAP_EVENT_CAN_SEND_NOW, 2, 1, 0};
att_packet_handler(HCI_EVENT_PACKET, 0, (uint8_t*)event, sizeof(event));
}
int l2cap_send_prepared_connectionless(uint16_t handle, uint16_t cid, uint16_t len){
att_connection_t att_connection;
att_init_connection(&att_connection);
uint8_t response[max_mtu];
uint16_t response_len = att_handle_request(&att_connection, l2cap_get_outgoing_buffer(), len, &response[0]);
if (response_len){
att_packet_handler(ATT_DATA_PACKET, gatt_client_handle, &response[0], response_len);
}
return 0;
}
void sm_add_event_handler(btstack_packet_callback_registration_t * callback_handler){
}
int sm_cmac_ready(void){
return 1;
}
void sm_cmac_signed_write_start(const sm_key_t key, uint8_t opcode, uint16_t attribute_handle, uint16_t message_len, const uint8_t * message, uint32_t sign_counter, void (*done_callback)(uint8_t * hash)){
//sm_notify_client(SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED, sm_central_device_addr_type, sm_central_device_address, 0, sm_central_device_matched);
}
int sm_le_device_index(uint16_t handle ){
return -1;
}
irk_lookup_state_t sm_identity_resolving_state(hci_con_handle_t con_handle){
return IRK_LOOKUP_SUCCEEDED;
}
void sm_request_pairing(hci_con_handle_t con_handle){
}
void btstack_run_loop_set_timer(btstack_timer_source_t *a, uint32_t timeout_in_ms){
}
// Set callback that will be executed when timer expires.
void btstack_run_loop_set_timer_handler(btstack_timer_source_t *ts, void (*process)(btstack_timer_source_t *_ts)){
}
// Add/Remove timer source.
void btstack_run_loop_add_timer(btstack_timer_source_t *timer){
}
int btstack_run_loop_remove_timer(btstack_timer_source_t *timer){
return 1;
}
void * btstack_run_loop_get_timer_context(btstack_timer_source_t *ts){
return ts->context;
}
// todo:
hci_connection_t * hci_connection_for_bd_addr_and_type(bd_addr_t addr, bd_addr_type_t addr_type){
printf("hci_connection_for_bd_addr_and_type not implemented in mock backend\n");
return NULL;
}
hci_connection_t * hci_connection_for_handle(hci_con_handle_t con_handle){
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){
}
int gap_authenticated(hci_con_handle_t con_handle){
return 0;
}
authorization_state_t gap_authorization_state(hci_con_handle_t con_handle){
return AUTHORIZATION_UNKNOWN;
}
int gap_encryption_key_size(hci_con_handle_t con_handle){
return 0;
}
int gap_secure_connection(hci_con_handle_t con_handle){
return 0;
}
gap_connection_type_t gap_get_connection_type(hci_con_handle_t connection_handle){
return GAP_CONNECTION_INVALID;
}

View File

@ -0,0 +1,130 @@
PRIMARY_SERVICE, GAP_SERVICE
CHARACTERISTIC, GAP_DEVICE_NAME, READ | WRITE | DYNAMIC,
CHARACTERISTIC, GAP_APPEARANCE, READ | WRITE | DYNAMIC,
// GAP Peripheral Privacy Flag
CHARACTERISTIC, 2A02, READ | WRITE | DYNAMIC, 00
// GAP Reconnection Address - 6 bytes
CHARACTERISTIC, 2A03, READ | WRITE | DYNAMIC,
// GAP Peripheral Preferred Connection Parameters
CHARACTERISTIC, 2A04, READ | WRITE | DYNAMIC,
PRIMARY_SERVICE, GATT_SERVICE
CHARACTERISTIC, GATT_SERVICE_CHANGED, READ,
SECONDARY_SERVICE, 0000FF10-0000-1000-8000-00805F9B34FB
CHARACTERISTIC, FF10, READ | WRITE | DYNAMIC,
SECONDARY_SERVICE, 0000FF11-0000-1000-8000-00805F9B34FB
CHARACTERISTIC, FF11, READ | WRITE | DYNAMIC,
//
PRIMARY_SERVICE, FFFF
CHARACTERISTIC, FFFD, READ | WRITE | DYNAMIC,
CHARACTERISTIC, FFFE, READ | WRITE | DYNAMIC,
//
PRIMARY_SERVICE, FFFF
CHARACTERISTIC, FFFD, READ | WRITE | DYNAMIC,
CHARACTERISTIC, FFFE, READ | WRITE | DYNAMIC,
//
// SECONDARY_SERVICE, FFFA
// CHARACTERISTIC, FFFB, READ | WRITE | DYNAMIC,
//
// SECONDARY_SERVICE, FFF9
// INCLUDE_SERVICE, FFFA
//
// SECONDARY_SERVICE, FFF7
// INCLUDE_SERVICE, FFF9
// CHARACTERISTIC, FFF8, READ | WRITE | DYNAMIC,
//
SECONDARY_SERVICE, FFF4
// INCLUDE_SERVICE, FFF7
// INCLUDE_SERVICE, FFFC
// INCLUDE_SERVICE, FFFF
CHARACTERISTIC, FFF5, READ | WRITE | DYNAMIC,
CHARACTERISTIC, FFF6, READ | WRITE | DYNAMIC,
//
// PRIMARY_SERVICE, FFF0
// INCLUDE_SERVICE, FFF4
// CHARACTERISTIC, FFF1, READ | WRITE | DYNAMIC | AUTHORIZATION_REQUIRED | ENCRYPTION_KEY_SIZE_7 | AUTHENTICATION_REQUIRED,
// CHARACTERISTIC, FFF2, READ | WRITE | DYNAMIC,
// CHARACTERISTIC, FFF3, READ | INDICATE,
// CHARACTERISTIC, 00001234-0000-1000-8000-00805F9B34FB, READ | WRITE | DYNAMIC,
// Primary Service with 16-bit UUID, included service
PRIMARY_SERVICE, F000
INCLUDE_SERVICE, FFF4
// Characteristics 16 and 128 bit with different authoriztion/authentication/encryption requirements and read/write flags
// - no requirements
CHARACTERISTIC, F100, READ | WRITE | DYNAMIC | NOTIFY | INDICATE | RELIABLE_WRITE,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC,
CHARACTERISTIC, 0000F101-0000-1000-8000-00805F9B34FB, READ | WRITE | DYNAMIC | NOTIFY | INDICATE | RELIABLE_WRITE,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC,
// - neither read nor writable
CHARACTERISTIC, F102, DYNAMIC,
CHARACTERISTIC_USER_DESCRIPTION, DYNAMIC,
CHARACTERISTIC, 0000F103-0000-1000-8000-00805F9B34FB, DYNAMIC,
CHARACTERISTIC_USER_DESCRIPTION, DYNAMIC,
// - authorization required
CHARACTERISTIC, F104, READ | WRITE | DYNAMIC | AUTHORIZATION_REQUIRED,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC | AUTHORIZATION_REQUIRED,
CHARACTERISTIC, 0000F105-0000-1000-8000-00805F9B34FB, READ | WRITE | DYNAMIC | AUTHORIZATION_REQUIRED,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC | AUTHORIZATION_REQUIRED,
// - authenthication required
CHARACTERISTIC, F106, READ | WRITE | DYNAMIC | AUTHENTICATION_REQUIRED,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC | AUTHENTICATION_REQUIRED,
CHARACTERISTIC, 0000F107-0000-1000-8000-00805F9B34FB, READ | WRITE | DYNAMIC | AUTHENTICATION_REQUIRED,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC | AUTHENTICATION_REQUIRED,
// - encryptiont with 128 bit key required
CHARACTERISTIC, F108, READ | WRITE | DYNAMIC | ENCRYPTION_KEY_SIZE_16,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC | ENCRYPTION_KEY_SIZE_16,
CHARACTERISTIC, 0000F109-0000-1000-8000-00805F9B34FB, READ | WRITE | DYNAMIC | ENCRYPTION_KEY_SIZE_16,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC | ENCRYPTION_KEY_SIZE_16,
// - write only
CHARACTERISTIC, F10A, WRITE | DYNAMIC,
// - read/write, incl. server characteristic configuration, characteristic format (uint8_t, exponent = 0, unitless, Bluetooth SIG, and characteristic aggregate format
CHARACTERISTIC, F10B, READ | WRITE | DYNAMIC,
SERVER_CHARACTERISTIC_CONFIGURATION, READ | WRITE | DYNAMIC,
CHARACTERISTIC_FORMAT, 1, 04, 0, 2700, 1, 0000
CHARACTERISTIC_FORMAT, 2, 0c, 0, 2700, 1, 0000
CHARACTERISTIC_AGGREGATE_FORMAT, 1, 2
// - read/write/write without response
CHARACTERISTIC, F10D, READ | WRITE | WRITE_WITHOUT_RESPONSE | DYNAMIC,
// - read/write without response
CHARACTERISTIC, F10C, READ | WRITE_WITHOUT_RESPONSE | DYNAMIC,
// - read/authenticated signed writes
CHARACTERISTIC, F10E, READ | WRITE | AUTHENTICATED_SIGNED_WRITE | DYNAMIC,
// Primary Service with 128-bit UUID, included service
PRIMARY_SERVICE, 0000F001-0000-1000-8000-00805F9B34FB
INCLUDE_SERVICE, 0000FF10-0000-1000-8000-00805F9B34FB
INCLUDE_SERVICE, 0000FF11-0000-1000-8000-00805F9B34FB
// Characteristics 16 and 128 bit with different authoriztion/authentication/encryption requirements and read/write flags
// - no requirements
CHARACTERISTIC, F200, READ | WRITE | DYNAMIC | NOTIFY | INDICATE | RELIABLE_WRITE | WRITE_WITHOUT_RESPONSE,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC,
CHARACTERISTIC, 0000F201-0000-1000-8000-00805F9B34FB, READ | WRITE | DYNAMIC | NOTIFY | INDICATE | RELIABLE_WRITE,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC,
// - neither read nor writable
CHARACTERISTIC, F202, DYNAMIC,
CHARACTERISTIC_USER_DESCRIPTION, DYNAMIC,
CHARACTERISTIC, 0000F203-0000-1000-8000-00805F9B34FB, DYNAMIC,
CHARACTERISTIC_USER_DESCRIPTION, DYNAMIC,
// - authorization required
CHARACTERISTIC, F204, READ | WRITE | DYNAMIC | AUTHORIZATION_REQUIRED,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC | AUTHORIZATION_REQUIRED,
CHARACTERISTIC, 0000F205-0000-1000-8000-00805F9B34FB, READ | WRITE | DYNAMIC | AUTHORIZATION_REQUIRED,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC | AUTHORIZATION_REQUIRED,
// - authenthication required
CHARACTERISTIC, F206, READ | WRITE | DYNAMIC | AUTHENTICATION_REQUIRED,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC | AUTHENTICATION_REQUIRED,
CHARACTERISTIC, 0000F207-0000-1000-8000-00805F9B34FB, READ | WRITE | DYNAMIC | AUTHENTICATION_REQUIRED,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC | AUTHENTICATION_REQUIRED,
// - encryptiont with 128 bit key required
CHARACTERISTIC, F208, READ | WRITE | DYNAMIC | ENCRYPTION_KEY_SIZE_16,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC | ENCRYPTION_KEY_SIZE_16,
CHARACTERISTIC, 0000F209-0000-1000-8000-00805F9B34FB, READ | WRITE | DYNAMIC | ENCRYPTION_KEY_SIZE_16,
CHARACTERISTIC_USER_DESCRIPTION, READ | WRITE | DYNAMIC | ENCRYPTION_KEY_SIZE_16,