Skip to content

Commit 253d080

Browse files
MariuszSkamracarlescufi
authored andcommitted
test: Bluetooth: host: Add unit tests for bt_data_parse
This adds unit tests for bt_data_parse. The sample data concept used in test is based on AD Structures of Advertising, Periodic Advertising, and Scan Response presented in Core specification. Signed-off-by: Mariusz Skamra <[email protected]>
1 parent 871db2d commit 253d080

File tree

4 files changed

+228
-0
lines changed

4 files changed

+228
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
project(bt_data_parse)
6+
7+
find_package(Zephyr COMPONENTS unittest HINTS $ENV{ZEPHYR_BASE})
8+
9+
add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/host host_mocks)
10+
11+
target_link_libraries(testbinary PRIVATE host_mocks)
12+
13+
target_sources(testbinary
14+
PRIVATE
15+
src/main.c
16+
17+
${ZEPHYR_BASE}/subsys/bluetooth/host/data.c
18+
${ZEPHYR_BASE}/subsys/net/buf_simple.c
19+
${ZEPHYR_BASE}/subsys/logging/log_minimal.c
20+
${ZEPHYR_BASE}/subsys/bluetooth/common/bt_str.c
21+
${ZEPHYR_BASE}/subsys/bluetooth/host/uuid.c
22+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CONFIG_ZTEST=y
2+
CONFIG_ZTEST_NEW_API=y
3+
CONFIG_ASSERT=y
4+
CONFIG_ASSERT_LEVEL=2
5+
CONFIG_ASSERT_VERBOSE=y
6+
CONFIG_ASSERT_ON_ERRORS=y
7+
CONFIG_NET_BUF=y
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
* Copyright (c) 2023 Codecoup
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/fff.h>
8+
#include <zephyr/kernel.h>
9+
#include <zephyr/bluetooth/bluetooth.h>
10+
11+
DEFINE_FFF_GLOBALS;
12+
13+
FAKE_VALUE_FUNC(bool, bt_data_parse_func, struct bt_data *, void *);
14+
15+
static void fff_reset_rule_before(const struct ztest_unit_test *test, void *fixture)
16+
{
17+
RESET_FAKE(bt_data_parse_func);
18+
}
19+
20+
ZTEST_RULE(fff_reset_rule, fff_reset_rule_before, NULL);
21+
22+
ZTEST_SUITE(bt_data_parse, NULL, NULL, NULL, NULL, NULL);
23+
24+
/*
25+
* Test empty data buffer
26+
*
27+
* Constraints:
28+
* - data.len set to 0
29+
*
30+
* Expected behaviour:
31+
* - Callback function is not called
32+
*/
33+
ZTEST(bt_data_parse, test_parsing_empty_buf)
34+
{
35+
struct net_buf_simple *buf = NET_BUF_SIMPLE(0);
36+
37+
bt_data_parse(buf, bt_data_parse_func, NULL);
38+
39+
zassert_equal(bt_data_parse_func_fake.call_count, 0);
40+
}
41+
42+
/*
43+
* Test AD Structure invalid length
44+
*
45+
* Constraints:
46+
* - AD Structure N length > number of bytes after
47+
*
48+
* Expected behaviour:
49+
* - Callback function is called N - 1 times
50+
*/
51+
ZTEST(bt_data_parse, test_parsing_invalid_length)
52+
{
53+
struct net_buf_simple buf;
54+
uint8_t data[] = {
55+
/* Significant part */
56+
0x02, 0x01, 0x00, /* AD Structure 1 */
57+
0x03, 0x02, 0x01, 0x00, /* AD Structure 2 */
58+
/* Invalid length 0xff */
59+
0xff, 0x03, 0x02, 0x01, /* AD Structure N */
60+
0x05, 0x04, 0x03, 0x02, 0x01, 0x00, /* AD Structure N + 1 */
61+
};
62+
63+
bt_data_parse_func_fake.return_val = true;
64+
65+
net_buf_simple_init_with_data(&buf, data, ARRAY_SIZE(data));
66+
67+
bt_data_parse(&buf, bt_data_parse_func, NULL);
68+
69+
zassert_equal(2, bt_data_parse_func_fake.call_count,
70+
"called %d", bt_data_parse_func_fake.call_count);
71+
}
72+
73+
/*
74+
* Test early termination of the significant part
75+
*
76+
* Constraints:
77+
* - The significant part contains a sequence of N AD structures
78+
* - The non-significant part extends the data with all-zero octets
79+
*
80+
* Expected behaviour:
81+
* - Callback function is called N times
82+
*/
83+
ZTEST(bt_data_parse, test_parsing_early_termination)
84+
{
85+
struct net_buf_simple buf;
86+
uint8_t data[] = {
87+
/* Significant part */
88+
0x02, 0x01, 0x00, /* AD Structure 1 */
89+
0x03, 0x02, 0x01, 0x00, /* AD Structure 2 */
90+
0x04, 0x03, 0x02, 0x01, 0x00, /* AD Structure 3 */
91+
/* Non-significant part */
92+
0x00, 0x00, 0x00, 0x00, 0x00
93+
};
94+
95+
bt_data_parse_func_fake.return_val = true;
96+
97+
net_buf_simple_init_with_data(&buf, data, ARRAY_SIZE(data));
98+
99+
bt_data_parse(&buf, bt_data_parse_func, NULL);
100+
101+
zassert_equal(3, bt_data_parse_func_fake.call_count,
102+
"called %d", bt_data_parse_func_fake.call_count);
103+
}
104+
105+
/*
106+
* Test parsing stopped
107+
*
108+
* Constraints:
109+
* - Data contains valid AD Structures
110+
* - Callback function returns false to stop parsing
111+
*
112+
* Expected behaviour:
113+
* - Once parsing is stopped, the callback is not called anymore
114+
*/
115+
ZTEST(bt_data_parse, test_parsing_stopped)
116+
{
117+
struct net_buf_simple buf;
118+
uint8_t data[] = {
119+
/* Significant part */
120+
0x02, 0x01, 0x00, /* AD Structure 1 */
121+
0x03, 0x02, 0x01, 0x00, /* AD Structure 2 */
122+
};
123+
124+
bt_data_parse_func_fake.return_val = false;
125+
126+
net_buf_simple_init_with_data(&buf, data, ARRAY_SIZE(data));
127+
128+
bt_data_parse(&buf, bt_data_parse_func, NULL);
129+
130+
zassert_equal(1, bt_data_parse_func_fake.call_count,
131+
"called %d", bt_data_parse_func_fake.call_count);
132+
}
133+
134+
struct custom_fake_user_data {
135+
const uint8_t *data;
136+
size_t len;
137+
};
138+
139+
static bool bt_data_parse_func_custom_fake(struct bt_data *data,
140+
void *user_data)
141+
{
142+
struct custom_fake_user_data *ud = user_data;
143+
144+
/* length check */
145+
zassert_true(ud->len-- > 0);
146+
zassert_equal(data->data_len, *ud->data - 1);
147+
ud->data++;
148+
149+
/* type check */
150+
zassert_true(ud->len-- > 0);
151+
zassert_equal(data->type, *ud->data);
152+
ud->data++;
153+
154+
/* value check */
155+
zassert_true(ud->len >= data->data_len);
156+
zassert_mem_equal(data->data, ud->data, data->data_len);
157+
ud->data += data->data_len;
158+
ud->len -= data->data_len;
159+
160+
return true;
161+
}
162+
163+
/*
164+
* Test parsing AD Data
165+
*
166+
* Constraints:
167+
* - Data contains valid AD Structures
168+
* - Callback function returns false to stop parsing
169+
*
170+
* Expected behaviour:
171+
* - Data passed to the callback match the expected data
172+
*/
173+
ZTEST(bt_data_parse, test_parsing_success)
174+
{
175+
struct net_buf_simple buf;
176+
uint8_t data[] = {
177+
/* Significant part */
178+
0x02, 0x01, 0x00, /* AD Structure 1 */
179+
0x03, 0x02, 0x01, 0x00, /* AD Structure 2 */
180+
};
181+
struct custom_fake_user_data user_data = {
182+
.data = data,
183+
.len = ARRAY_SIZE(data),
184+
};
185+
186+
bt_data_parse_func_fake.custom_fake = bt_data_parse_func_custom_fake;
187+
188+
net_buf_simple_init_with_data(&buf, data, ARRAY_SIZE(data));
189+
190+
bt_data_parse(&buf, bt_data_parse_func, &user_data);
191+
192+
zassert_equal(2, bt_data_parse_func_fake.call_count,
193+
"called %d", bt_data_parse_func_fake.call_count);
194+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
common:
2+
tags: bluetooth host
3+
tests:
4+
bluetooth.host.bt_data_parse:
5+
type: unit

0 commit comments

Comments
 (0)