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