Bluetooth: tests: Add tests for GATT
This adds initial test for GATT APIs that don't require a connection thus can be run without any extra setup. Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
parent
2dc2d9cf00
commit
4e6e2e3e85
8
tests/bluetooth/gatt/CMakeLists.txt
Normal file
8
tests/bluetooth/gatt/CMakeLists.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||
project(bluetooth_gatt)
|
||||
|
||||
FILE(GLOB app_sources src/*.c)
|
||||
target_sources(app PRIVATE ${app_sources})
|
10
tests/bluetooth/gatt/prj.conf
Normal file
10
tests/bluetooth/gatt/prj.conf
Normal file
|
@ -0,0 +1,10 @@
|
|||
CONFIG_TEST=y
|
||||
CONFIG_ZTEST=y
|
||||
|
||||
CONFIG_BT=y
|
||||
CONFIG_BT_CTLR=n
|
||||
CONFIG_BT_NO_DRIVER=y
|
||||
|
||||
CONFIG_BT_DEBUG_LOG=y
|
||||
CONFIG_BT_PERIPHERAL=y
|
||||
CONFIG_BT_GATT_DYNAMIC_DB=y
|
278
tests/bluetooth/gatt/src/main.c
Normal file
278
tests/bluetooth/gatt/src/main.c
Normal file
|
@ -0,0 +1,278 @@
|
|||
/* main.c - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <stddef.h>
|
||||
#include <ztest.h>
|
||||
|
||||
#include <bluetooth/buf.h>
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/gatt.h>
|
||||
|
||||
/* Custom Service Variables */
|
||||
static struct bt_uuid_128 test_uuid = BT_UUID_INIT_128(
|
||||
0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
|
||||
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
|
||||
static struct bt_uuid_128 test_chrc_uuid = BT_UUID_INIT_128(
|
||||
0xf2, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
|
||||
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
|
||||
|
||||
static u8_t test_value[] = { 'T', 'e', 's', 't', '\0' };
|
||||
|
||||
static struct bt_uuid_128 test1_uuid = BT_UUID_INIT_128(
|
||||
0xf4, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
|
||||
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
|
||||
|
||||
static const struct bt_uuid_128 test1_nfy_uuid = BT_UUID_INIT_128(
|
||||
0xf5, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
|
||||
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
|
||||
|
||||
static struct bt_gatt_ccc_cfg test1_ccc_cfg[BT_GATT_CCC_MAX] = {};
|
||||
static u8_t nfy_enabled;
|
||||
|
||||
static void test1_ccc_cfg_changed(const struct bt_gatt_attr *attr, u16_t value)
|
||||
{
|
||||
nfy_enabled = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0;
|
||||
}
|
||||
|
||||
static ssize_t read_test(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
void *buf, u16_t len, u16_t offset)
|
||||
{
|
||||
const char *value = attr->user_data;
|
||||
|
||||
return bt_gatt_attr_read(conn, attr, buf, len, offset, value,
|
||||
strlen(value));
|
||||
}
|
||||
|
||||
static ssize_t write_test(struct bt_conn *conn, const struct bt_gatt_attr *attr,
|
||||
const void *buf, u16_t len, u16_t offset,
|
||||
u8_t flags)
|
||||
{
|
||||
u8_t *value = attr->user_data;
|
||||
|
||||
if (offset + len > sizeof(test_value)) {
|
||||
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
|
||||
}
|
||||
|
||||
memcpy(value + offset, buf, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static struct bt_gatt_attr test_attrs[] = {
|
||||
/* Vendor Primary Service Declaration */
|
||||
BT_GATT_PRIMARY_SERVICE(&test_uuid),
|
||||
|
||||
BT_GATT_CHARACTERISTIC(&test_chrc_uuid.uuid,
|
||||
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE,
|
||||
BT_GATT_PERM_READ_AUTHEN |
|
||||
BT_GATT_PERM_WRITE_AUTHEN,
|
||||
read_test, write_test, test_value),
|
||||
};
|
||||
|
||||
static struct bt_gatt_service test_svc = BT_GATT_SERVICE(test_attrs);
|
||||
|
||||
static struct bt_gatt_attr test1_attrs[] = {
|
||||
/* Vendor Primary Service Declaration */
|
||||
BT_GATT_PRIMARY_SERVICE(&test1_uuid),
|
||||
|
||||
BT_GATT_CHARACTERISTIC(&test1_nfy_uuid.uuid,
|
||||
BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_NONE,
|
||||
NULL, NULL, &nfy_enabled),
|
||||
BT_GATT_CCC(test1_ccc_cfg, test1_ccc_cfg_changed),
|
||||
};
|
||||
|
||||
static struct bt_gatt_service test1_svc = BT_GATT_SERVICE(test1_attrs);
|
||||
|
||||
void test_gatt_register(void)
|
||||
{
|
||||
/* Attempt to register services */
|
||||
zassert_false(bt_gatt_service_register(&test_svc),
|
||||
"Test service registration failed");
|
||||
zassert_false(bt_gatt_service_register(&test1_svc),
|
||||
"Test service1 registration failed");
|
||||
|
||||
/* Attempt to register already registered services */
|
||||
zassert_true(bt_gatt_service_register(&test_svc),
|
||||
"Test service duplicate succeeded");
|
||||
zassert_true(bt_gatt_service_register(&test1_svc),
|
||||
"Test service1 duplicate succeeded");
|
||||
}
|
||||
|
||||
void test_gatt_unregister(void)
|
||||
{
|
||||
/* Attempt to unregister last */
|
||||
zassert_false(bt_gatt_service_unregister(&test1_svc),
|
||||
"Test service1 unregister failed");
|
||||
zassert_false(bt_gatt_service_register(&test1_svc),
|
||||
"Test service1 re-registration failed");
|
||||
|
||||
/* Attempt to unregister first/middle */
|
||||
zassert_false(bt_gatt_service_unregister(&test_svc),
|
||||
"Test service unregister failed");
|
||||
zassert_false(bt_gatt_service_register(&test_svc),
|
||||
"Test service re-registration failed");
|
||||
|
||||
/* Attempt to unregister all reverse order */
|
||||
zassert_false(bt_gatt_service_unregister(&test1_svc),
|
||||
"Test service1 unregister failed");
|
||||
zassert_false(bt_gatt_service_unregister(&test_svc),
|
||||
"Test service unregister failed");
|
||||
|
||||
zassert_false(bt_gatt_service_register(&test_svc),
|
||||
"Test service registration failed");
|
||||
zassert_false(bt_gatt_service_register(&test1_svc),
|
||||
"Test service1 registration failed");
|
||||
|
||||
/* Attempt to unregister all same order */
|
||||
zassert_false(bt_gatt_service_unregister(&test_svc),
|
||||
"Test service1 unregister failed");
|
||||
zassert_false(bt_gatt_service_unregister(&test1_svc),
|
||||
"Test service unregister failed");
|
||||
}
|
||||
|
||||
static u8_t count_attr(const struct bt_gatt_attr *attr, void *user_data)
|
||||
{
|
||||
u16_t *count = user_data;
|
||||
|
||||
(*count)++;
|
||||
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
static u8_t find_attr(const struct bt_gatt_attr *attr, void *user_data)
|
||||
{
|
||||
const struct bt_gatt_attr **tmp = user_data;
|
||||
|
||||
*tmp = attr;
|
||||
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
void test_gatt_foreach(void)
|
||||
{
|
||||
const struct bt_gatt_attr *attr;
|
||||
u16_t num = 0;
|
||||
|
||||
/* Attempt to register services */
|
||||
zassert_false(bt_gatt_service_register(&test_svc),
|
||||
"Test service registration failed");
|
||||
zassert_false(bt_gatt_service_register(&test1_svc),
|
||||
"Test service1 registration failed");
|
||||
|
||||
/* Iterate attributes */
|
||||
bt_gatt_foreach_attr(test_attrs[0].handle, 0xffff, count_attr, &num);
|
||||
zassert_equal(num, 7, "Number of attributes don't match");
|
||||
|
||||
/* Iterate 1 attribute */
|
||||
num = 0;
|
||||
bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff, NULL, NULL, 1,
|
||||
count_attr, &num);
|
||||
zassert_equal(num, 1, "Number of attributes don't match");
|
||||
|
||||
/* Find attribute by UUID */
|
||||
attr = NULL;
|
||||
bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff,
|
||||
&test_chrc_uuid.uuid, NULL, 0, find_attr,
|
||||
&attr);
|
||||
zassert_not_null(attr, "Attribute don't match");
|
||||
if (attr) {
|
||||
zassert_equal(attr->uuid, &test_chrc_uuid.uuid,
|
||||
"Attribute UUID don't match");
|
||||
}
|
||||
|
||||
/* Find attribute by DATA */
|
||||
attr = NULL;
|
||||
bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff, NULL,
|
||||
test_value, 0, find_attr, &attr);
|
||||
zassert_not_null(attr, "Attribute don't match");
|
||||
if (attr) {
|
||||
zassert_equal(attr->user_data, test_value,
|
||||
"Attribute value don't match");
|
||||
}
|
||||
|
||||
/* Find all characteristics */
|
||||
num = 0;
|
||||
bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff,
|
||||
BT_UUID_GATT_CHRC, NULL, 0, count_attr, &num);
|
||||
zassert_equal(num, 2, "Number of attributes don't match");
|
||||
|
||||
/* Find 1 characteristic */
|
||||
attr = NULL;
|
||||
bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff,
|
||||
BT_UUID_GATT_CHRC, NULL, 1, find_attr, &attr);
|
||||
zassert_not_null(attr, "Attribute don't match");
|
||||
|
||||
/* Find attribute by UUID and DATA */
|
||||
attr = NULL;
|
||||
bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff,
|
||||
&test1_nfy_uuid.uuid, &nfy_enabled, 1,
|
||||
find_attr, &attr);
|
||||
zassert_not_null(attr, "Attribute don't match");
|
||||
if (attr) {
|
||||
zassert_equal(attr->uuid, &test1_nfy_uuid.uuid,
|
||||
"Attribute UUID don't match");
|
||||
zassert_equal(attr->user_data, &nfy_enabled,
|
||||
"Attribute value don't match");
|
||||
}
|
||||
}
|
||||
|
||||
void test_gatt_read(void)
|
||||
{
|
||||
const struct bt_gatt_attr *attr;
|
||||
u8_t buf[256];
|
||||
ssize_t ret;
|
||||
|
||||
/* Find attribute by UUID */
|
||||
attr = NULL;
|
||||
bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff,
|
||||
&test_chrc_uuid.uuid, NULL, 0, find_attr,
|
||||
&attr);
|
||||
zassert_not_null(attr, "Attribute don't match");
|
||||
if (attr) {
|
||||
zassert_equal(attr->uuid, &test_chrc_uuid.uuid,
|
||||
"Attribute UUID don't match");
|
||||
}
|
||||
|
||||
ret = attr->read(NULL, attr, (void *)buf, sizeof(buf), 0);
|
||||
zassert_equal(ret, strlen(test_value),
|
||||
"Attribute read unexpected return");
|
||||
zassert_mem_equal(buf, test_value, ret,
|
||||
"Attribute read value don't match");
|
||||
}
|
||||
|
||||
void test_gatt_write(void)
|
||||
{
|
||||
const struct bt_gatt_attr *attr;
|
||||
char *value = " ";
|
||||
ssize_t ret;
|
||||
|
||||
/* Find attribute by UUID */
|
||||
attr = NULL;
|
||||
bt_gatt_foreach_attr_type(test_attrs[0].handle, 0xffff,
|
||||
&test_chrc_uuid.uuid, NULL, 0, find_attr,
|
||||
&attr);
|
||||
zassert_not_null(attr, "Attribute don't match");
|
||||
|
||||
ret = attr->write(NULL, attr, (void *)value, strlen(value), 0, 0);
|
||||
zassert_equal(ret, sizeof(value), "Attribute write unexpected return");
|
||||
zassert_mem_equal(value, test_value, ret,
|
||||
"Attribute write value don't match");
|
||||
}
|
||||
|
||||
/*test case main entry*/
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(test_gatt,
|
||||
ztest_unit_test(test_gatt_register),
|
||||
ztest_unit_test(test_gatt_unregister),
|
||||
ztest_unit_test(test_gatt_foreach),
|
||||
ztest_unit_test(test_gatt_read),
|
||||
ztest_unit_test(test_gatt_write));
|
||||
ztest_run_test_suite(test_gatt);
|
||||
}
|
4
tests/bluetooth/gatt/testcase.yaml
Normal file
4
tests/bluetooth/gatt/testcase.yaml
Normal file
|
@ -0,0 +1,4 @@
|
|||
tests:
|
||||
bluetooth.gatt:
|
||||
platform_whitelist: native_posix qemu_x86 qemu_cortex_m3
|
||||
tags: bluetooth gatt
|
Loading…
Reference in a new issue