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