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
fff_reset_rule_before(const struct ztest_unit_test * test,void * fixture)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 */
ZTEST(bt_data_parse,test_parsing_empty_buf)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 */
ZTEST(bt_data_parse,test_parsing_invalid_length)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 */
ZTEST(bt_data_parse,test_parsing_early_termination)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 */
ZTEST(bt_data_parse,test_parsing_stopped)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
bt_data_parse_func_custom_fake(struct bt_data * data,void * user_data)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 */
ZTEST(bt_data_parse,test_parsing_success)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 }
195