1 /* test_distribute_broadcast_code.c - unit test for distribute broadcast code */
2
3 /*
4 * Copyright (c) 2024 Nordic Semiconductor ASA
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <errno.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #include <zephyr/autoconf.h>
14 #include <zephyr/bluetooth/audio/bap.h>
15 #include <zephyr/bluetooth/audio/cap.h>
16 #include <zephyr/bluetooth/hci_types.h>
17 #include <zephyr/fff.h>
18 #include <zephyr/ztest_assert.h>
19 #include <zephyr/ztest_test.h>
20
21 #include "cap_commander.h"
22 #include "conn.h"
23 #include "expects_util.h"
24 #include "cap_mocks.h"
25 #include "test_common.h"
26
27 #include <zephyr/logging/log.h>
28 #include <zephyr/sys/util.h>
29
30 LOG_MODULE_REGISTER(bt_distribute_broadcast_code, CONFIG_BT_CAP_COMMANDER_LOG_LEVEL);
31
32 #define FFF_GLOBALS
33
34 struct cap_commander_test_distribute_broadcast_code_fixture {
35 struct bt_conn conns[CONFIG_BT_MAX_CONN];
36
37 struct bt_bap_bass_subgroup subgroups[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS];
38 struct bt_cap_commander_broadcast_reception_start_member_param
39 start_member_params[CONFIG_BT_MAX_CONN];
40 struct bt_cap_commander_broadcast_reception_start_param start_param;
41 struct bt_cap_commander_distribute_broadcast_code_member_param
42 broadcast_code_member_params[CONFIG_BT_MAX_CONN];
43 struct bt_cap_commander_distribute_broadcast_code_param distribute_broadcast_code_param;
44 struct bt_bap_broadcast_assistant_cb broadcast_assistant_cb;
45 };
46
cap_commander_test_distribute_broadcast_code_fixture_init(struct cap_commander_test_distribute_broadcast_code_fixture * fixture)47 static void cap_commander_test_distribute_broadcast_code_fixture_init(
48 struct cap_commander_test_distribute_broadcast_code_fixture *fixture)
49 {
50 for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
51 test_conn_init(&fixture->conns[i]);
52 fixture->conns[i].index = i;
53 }
54
55 fixture->distribute_broadcast_code_param.type = BT_CAP_SET_TYPE_AD_HOC;
56 fixture->distribute_broadcast_code_param.param = fixture->broadcast_code_member_params;
57 fixture->distribute_broadcast_code_param.count =
58 ARRAY_SIZE(fixture->broadcast_code_member_params);
59 memcpy(fixture->distribute_broadcast_code_param.broadcast_code, BROADCAST_CODE,
60 sizeof(BROADCAST_CODE));
61 for (size_t i = 0; i < ARRAY_SIZE(fixture->broadcast_code_member_params); i++) {
62 fixture->broadcast_code_member_params[i].member.member = &fixture->conns[i];
63 fixture->broadcast_code_member_params[i].src_id = RANDOM_SRC_ID;
64 }
65 }
66
cap_commander_test_distribute_broadcast_code_setup(void)67 static void *cap_commander_test_distribute_broadcast_code_setup(void)
68 {
69 struct cap_commander_test_distribute_broadcast_code_fixture *fixture;
70
71 fixture = malloc(sizeof(*fixture));
72 zassert_not_null(fixture);
73
74 return fixture;
75 }
76
cap_commander_test_distribute_broadcast_code_before(void * f)77 static void cap_commander_test_distribute_broadcast_code_before(void *f)
78 {
79 int err;
80 struct cap_commander_test_distribute_broadcast_code_fixture *fixture = f;
81
82 memset(f, 0, sizeof(struct cap_commander_test_distribute_broadcast_code_fixture));
83 cap_commander_test_distribute_broadcast_code_fixture_init(fixture);
84
85 for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
86 err = bt_cap_commander_discover(&fixture->conns[i]);
87 zassert_equal(0, err, "Unexpected return value %d", err);
88 }
89 }
90
cap_commander_test_distribute_broadcast_code_after(void * f)91 static void cap_commander_test_distribute_broadcast_code_after(void *f)
92 {
93 struct cap_commander_test_distribute_broadcast_code_fixture *fixture = f;
94
95 bt_cap_commander_unregister_cb(&mock_cap_commander_cb);
96 bt_bap_broadcast_assistant_unregister_cb(&fixture->broadcast_assistant_cb);
97
98 /* We need to cleanup since the CAP commander remembers state */
99 bt_cap_commander_cancel();
100
101 for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
102 mock_bt_conn_disconnected(&fixture->conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN);
103 }
104 }
105
cap_commander_test_distribute_broadcast_code_teardown(void * f)106 static void cap_commander_test_distribute_broadcast_code_teardown(void *f)
107 {
108 free(f);
109 }
110
test_distribute_broadcast_code(struct bt_cap_commander_distribute_broadcast_code_param * distribute_broadcast_code_param)111 static void test_distribute_broadcast_code(
112 struct bt_cap_commander_distribute_broadcast_code_param *distribute_broadcast_code_param)
113 {
114 int err;
115
116 err = bt_cap_commander_distribute_broadcast_code(distribute_broadcast_code_param);
117 zassert_equal(0, err, "Unexpected return value %d", err);
118
119 zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 1,
120 mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
121 zassert_equal_ptr(NULL,
122 mock_cap_commander_distribute_broadcast_code_cb_fake.arg0_history[0]);
123 zassert_equal(0, mock_cap_commander_distribute_broadcast_code_cb_fake.arg1_history[0]);
124 }
125
126 ZTEST_SUITE(cap_commander_test_distribute_broadcast_code, NULL,
127 cap_commander_test_distribute_broadcast_code_setup,
128 cap_commander_test_distribute_broadcast_code_before,
129 cap_commander_test_distribute_broadcast_code_after,
130 cap_commander_test_distribute_broadcast_code_teardown);
131
ZTEST_F(cap_commander_test_distribute_broadcast_code,test_commander_distribute_broadcast_code)132 ZTEST_F(cap_commander_test_distribute_broadcast_code, test_commander_distribute_broadcast_code)
133 {
134 int err;
135
136 err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
137 zassert_equal(0, err, "Unexpected return value %d", err);
138
139 test_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
140 }
141
ZTEST_F(cap_commander_test_distribute_broadcast_code,test_commander_reception_distribute_broadcast_code_double)142 ZTEST_F(cap_commander_test_distribute_broadcast_code,
143 test_commander_reception_distribute_broadcast_code_double)
144 {
145 int err;
146
147 err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
148 zassert_equal(0, err, "Unexpected return value %d", err);
149
150 test_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
151
152 /*
153 * We can not use test_distribute_broadcast_code because of the check on how often the
154 * callback function is called
155 */
156 err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
157 zassert_equal(0, err, "Unexpected return value %d", err);
158
159 zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 2,
160 mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
161 zassert_equal_ptr(NULL,
162 mock_cap_commander_distribute_broadcast_code_cb_fake.arg0_history[1]);
163 zassert_equal(0, mock_cap_commander_distribute_broadcast_code_cb_fake.arg1_history[1]);
164 }
165
ZTEST_F(cap_commander_test_distribute_broadcast_code,test_commander_reception_distribute_broadcast_code_param_null)166 ZTEST_F(cap_commander_test_distribute_broadcast_code,
167 test_commander_reception_distribute_broadcast_code_param_null)
168 {
169 int err;
170
171 err = bt_cap_commander_distribute_broadcast_code(NULL);
172 zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
173
174 zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 0,
175 mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
176 }
177
ZTEST_F(cap_commander_test_distribute_broadcast_code,test_commander_distribute_broadcast_code_param_zero_count)178 ZTEST_F(cap_commander_test_distribute_broadcast_code,
179 test_commander_distribute_broadcast_code_param_zero_count)
180 {
181 int err;
182
183 fixture->distribute_broadcast_code_param.count = 0;
184
185 err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
186 zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
187
188 zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 0,
189 mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
190 }
191
ZTEST_F(cap_commander_test_distribute_broadcast_code,test_commander_distribute_broadcast_code_param_high_count)192 ZTEST_F(cap_commander_test_distribute_broadcast_code,
193 test_commander_distribute_broadcast_code_param_high_count)
194 {
195 int err;
196
197 fixture->distribute_broadcast_code_param.count = CONFIG_BT_MAX_CONN + 1;
198
199 err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
200 zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
201
202 zexpect_call_count("bt_cap_commander_cb.broadcast_distribute_broadcast_code", 0,
203 mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
204 }
205
ZTEST_F(cap_commander_test_distribute_broadcast_code,test_commander_distribute_broadcast_code_inval_param_null_param)206 ZTEST_F(cap_commander_test_distribute_broadcast_code,
207 test_commander_distribute_broadcast_code_inval_param_null_param)
208 {
209 int err;
210
211 fixture->distribute_broadcast_code_param.type = BT_CAP_SET_TYPE_AD_HOC;
212 fixture->distribute_broadcast_code_param.param = NULL;
213 fixture->distribute_broadcast_code_param.count = ARRAY_SIZE(fixture->conns);
214
215 err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
216 zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
217
218 zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 0,
219 mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
220 }
221
ZTEST_F(cap_commander_test_distribute_broadcast_code,test_commander_distribute_broadcast_code_inval_null_member)222 ZTEST_F(cap_commander_test_distribute_broadcast_code,
223 test_commander_distribute_broadcast_code_inval_null_member)
224 {
225 int err;
226
227 fixture->distribute_broadcast_code_param.param[0].member.member = NULL;
228
229 err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
230 zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
231
232 zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 0,
233 mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
234 }
235
ZTEST_F(cap_commander_test_distribute_broadcast_code,test_commander_distribute_broadcast_code_inval_missing_cas)236 ZTEST_F(cap_commander_test_distribute_broadcast_code,
237 test_commander_distribute_broadcast_code_inval_missing_cas)
238 {
239 int err;
240
241 fixture->distribute_broadcast_code_param.type = BT_CAP_SET_TYPE_CSIP;
242
243 err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
244 zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
245
246 zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 0,
247 mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
248 }
249
ZTEST_F(cap_commander_test_distribute_broadcast_code,test_commander_distribute_broadcast_code_double_conn)250 ZTEST_F(cap_commander_test_distribute_broadcast_code,
251 test_commander_distribute_broadcast_code_double_conn)
252 {
253 int err;
254
255 if (CONFIG_BT_MAX_CONN == 1) {
256 ztest_test_skip();
257 }
258
259 for (size_t i = 0; i < ARRAY_SIZE(fixture->broadcast_code_member_params); i++) {
260 fixture->broadcast_code_member_params[i].member.member = &fixture->conns[0];
261 }
262
263 err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
264 zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
265
266 zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 0,
267 mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
268 }
269