1 /* test_micp.c - unit test for microphone settings */
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/bluetooth/audio/micp.h>
13 #include <zephyr/fff.h>
14 
15 #include "bluetooth.h"
16 #include "cap_commander.h"
17 #include "conn.h"
18 #include "expects_util.h"
19 #include "cap_mocks.h"
20 #include "test_common.h"
21 
22 #define FFF_GLOBALS
23 
24 struct cap_commander_test_micp_fixture {
25 	struct bt_conn conns[CONFIG_BT_MAX_CONN];
26 };
27 
cap_commander_test_micp_fixture_init(struct cap_commander_test_micp_fixture * fixture)28 static void cap_commander_test_micp_fixture_init(struct cap_commander_test_micp_fixture *fixture)
29 {
30 	for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
31 		test_conn_init(&fixture->conns[i]);
32 	}
33 }
34 
cap_commander_test_micp_setup(void)35 static void *cap_commander_test_micp_setup(void)
36 {
37 	struct cap_commander_test_micp_fixture *fixture;
38 
39 	fixture = malloc(sizeof(*fixture));
40 	zassert_not_null(fixture);
41 
42 	return fixture;
43 }
44 
cap_commander_test_micp_before(void * f)45 static void cap_commander_test_micp_before(void *f)
46 {
47 	memset(f, 0, sizeof(struct cap_commander_test_micp_fixture));
48 	cap_commander_test_micp_fixture_init(f);
49 }
50 
cap_commander_test_micp_after(void * f)51 static void cap_commander_test_micp_after(void *f)
52 {
53 	struct cap_commander_test_micp_fixture *fixture = f;
54 
55 	bt_cap_commander_unregister_cb(&mock_cap_commander_cb);
56 
57 	for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
58 		mock_bt_conn_disconnected(&fixture->conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN);
59 	}
60 }
61 
cap_commander_test_micp_teardown(void * f)62 static void cap_commander_test_micp_teardown(void *f)
63 {
64 	free(f);
65 }
66 
67 ZTEST_SUITE(cap_commander_test_micp, NULL, cap_commander_test_micp_setup,
68 	    cap_commander_test_micp_before, cap_commander_test_micp_after,
69 	    cap_commander_test_micp_teardown);
70 
71 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_gain_setting)72 ZTEST_F(cap_commander_test_micp, test_commander_change_microphone_gain_setting)
73 {
74 	struct bt_cap_commander_change_microphone_gain_setting_member_param
75 		member_params[ARRAY_SIZE(fixture->conns)];
76 	const struct bt_cap_commander_change_microphone_gain_setting_param param = {
77 		.type = BT_CAP_SET_TYPE_AD_HOC,
78 		.param = member_params,
79 		.count = ARRAY_SIZE(member_params),
80 	};
81 	int err;
82 
83 	for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
84 		member_params[i].member.member = &fixture->conns[i];
85 		member_params[i].gain = 10 + i;
86 	}
87 
88 	err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
89 	zassert_equal(0, err, "Unexpected return value %d", err);
90 
91 	for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
92 		struct bt_micp_mic_ctlr *mic_ctlr; /* We don't care about this */
93 
94 		err = bt_micp_mic_ctlr_discover(&fixture->conns[i], &mic_ctlr);
95 		zassert_equal(0, err, "Unexpected return value %d", err);
96 	}
97 
98 	err = bt_cap_commander_change_microphone_gain_setting(&param);
99 	zassert_equal(0, err, "Unexpected return value %d", err);
100 
101 	zexpect_call_count("bt_cap_commander_cb.microphone_gain_setting_changed", 1,
102 			   mock_cap_commander_microphone_gain_changed_cb_fake.call_count);
103 }
104 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_gain_setting_double)105 ZTEST_F(cap_commander_test_micp, test_commander_change_microphone_gain_setting_double)
106 {
107 	struct bt_cap_commander_change_microphone_gain_setting_member_param
108 		member_params[ARRAY_SIZE(fixture->conns)];
109 	const struct bt_cap_commander_change_microphone_gain_setting_param param = {
110 		.type = BT_CAP_SET_TYPE_AD_HOC,
111 		.param = member_params,
112 		.count = ARRAY_SIZE(member_params),
113 	};
114 	int err;
115 
116 	for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
117 		member_params[i].member.member = &fixture->conns[i];
118 		member_params[i].gain = 10 + i;
119 	}
120 
121 	err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
122 	zassert_equal(0, err, "Unexpected return value %d", err);
123 
124 	for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
125 		struct bt_micp_mic_ctlr *mic_ctlr; /* We don't care about this */
126 
127 		err = bt_micp_mic_ctlr_discover(&fixture->conns[i], &mic_ctlr);
128 		zassert_equal(0, err, "Unexpected return value %d", err);
129 	}
130 
131 	err = bt_cap_commander_change_microphone_gain_setting(&param);
132 	zassert_equal(0, err, "Unexpected return value %d", err);
133 
134 	zexpect_call_count("bt_cap_commander_cb.microphone_gain_setting_changed", 1,
135 			   mock_cap_commander_microphone_gain_changed_cb_fake.call_count);
136 
137 	/* Test that it still works as expected if we set the same value twice */
138 	err = bt_cap_commander_change_microphone_gain_setting(&param);
139 	zassert_equal(0, err, "Unexpected return value %d", err);
140 
141 	zexpect_call_count("bt_cap_commander_cb.microphone_gain_setting_changed", 2,
142 			   mock_cap_commander_microphone_gain_changed_cb_fake.call_count);
143 }
144 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_gain_setting_inval_param_null)145 ZTEST_F(cap_commander_test_micp, test_commander_change_microphone_gain_setting_inval_param_null)
146 {
147 	int err;
148 
149 	err = bt_cap_commander_change_microphone_gain_setting(NULL);
150 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
151 }
152 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_gain_setting_inval_param_null_param)153 ZTEST_F(cap_commander_test_micp,
154 	test_commander_change_microphone_gain_setting_inval_param_null_param)
155 {
156 	const struct bt_cap_commander_change_microphone_gain_setting_param param = {
157 		.type = BT_CAP_SET_TYPE_AD_HOC,
158 		.param = NULL,
159 		.count = ARRAY_SIZE(fixture->conns),
160 	};
161 	int err;
162 
163 	err = bt_cap_commander_change_microphone_gain_setting(&param);
164 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
165 }
166 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_gain_setting_inval_param_null_member)167 ZTEST_F(cap_commander_test_micp,
168 	test_commander_change_microphone_gain_setting_inval_param_null_member)
169 {
170 	struct bt_cap_commander_change_microphone_gain_setting_member_param
171 		member_params[ARRAY_SIZE(fixture->conns)];
172 	const struct bt_cap_commander_change_microphone_gain_setting_param param = {
173 		.type = BT_CAP_SET_TYPE_AD_HOC,
174 		.param = member_params,
175 		.count = ARRAY_SIZE(member_params),
176 	};
177 	int err;
178 
179 	for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
180 		member_params[i].member.member = &fixture->conns[i];
181 		member_params[i].gain = 10 + i;
182 	}
183 	member_params[ARRAY_SIZE(member_params) - 1].member.member = NULL;
184 
185 	err = bt_cap_commander_change_microphone_gain_setting(&param);
186 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
187 }
188 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_gain_setting_inval_missing_cas)189 ZTEST_F(cap_commander_test_micp, test_commander_change_microphone_gain_setting_inval_missing_cas)
190 {
191 	struct bt_cap_commander_change_microphone_gain_setting_member_param
192 		member_params[ARRAY_SIZE(fixture->conns)];
193 	const struct bt_cap_commander_change_microphone_gain_setting_param param = {
194 		.type = BT_CAP_SET_TYPE_CSIP,
195 		.param = member_params,
196 		.count = ARRAY_SIZE(member_params),
197 	};
198 	int err;
199 
200 	for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
201 		member_params[i].member.member = &fixture->conns[i];
202 		member_params[i].gain = 10 + i;
203 	}
204 
205 	err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
206 	zassert_equal(0, err, "Unexpected return value %d", err);
207 
208 	for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
209 		struct bt_micp_mic_ctlr *mic_ctlr; /* We don't care about this */
210 
211 		err = bt_micp_mic_ctlr_discover(&fixture->conns[i], &mic_ctlr);
212 		zassert_equal(0, err, "Unexpected return value %d", err);
213 	}
214 
215 	err = bt_cap_commander_change_microphone_gain_setting(&param);
216 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
217 }
218 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_gain_setting_inval_missing_aics)219 ZTEST_F(cap_commander_test_micp, test_commander_change_microphone_gain_setting_inval_missing_aics)
220 {
221 	struct bt_cap_commander_change_microphone_gain_setting_member_param
222 		member_params[ARRAY_SIZE(fixture->conns)];
223 	const struct bt_cap_commander_change_microphone_gain_setting_param param = {
224 		.type = BT_CAP_SET_TYPE_AD_HOC,
225 		.param = member_params,
226 		.count = ARRAY_SIZE(member_params),
227 	};
228 	int err;
229 
230 	for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
231 		member_params[i].member.member = &fixture->conns[i];
232 		member_params[i].gain = 10 + i;
233 	}
234 
235 	err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
236 	zassert_equal(0, err, "Unexpected return value %d", err);
237 
238 	err = bt_cap_commander_change_microphone_gain_setting(&param);
239 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
240 }
241 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_gain_setting_inval_param_zero_count)242 ZTEST_F(cap_commander_test_micp,
243 	test_commander_change_microphone_gain_setting_inval_param_zero_count)
244 {
245 	struct bt_cap_commander_change_microphone_gain_setting_member_param
246 		member_params[ARRAY_SIZE(fixture->conns)];
247 	const struct bt_cap_commander_change_microphone_gain_setting_param param = {
248 		.type = BT_CAP_SET_TYPE_AD_HOC,
249 		.param = member_params,
250 		.count = 0U,
251 	};
252 	int err;
253 
254 	for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
255 		member_params[i].member.member = &fixture->conns[i];
256 		member_params[i].gain = 10 + i;
257 	}
258 
259 	err = bt_cap_commander_change_microphone_gain_setting(&param);
260 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
261 }
262 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_gain_setting_inval_param_inval_count)263 ZTEST_F(cap_commander_test_micp,
264 	test_commander_change_microphone_gain_setting_inval_param_inval_count)
265 {
266 	struct bt_cap_commander_change_microphone_gain_setting_member_param
267 		member_params[ARRAY_SIZE(fixture->conns)];
268 	const struct bt_cap_commander_change_microphone_gain_setting_param param = {
269 		.type = BT_CAP_SET_TYPE_AD_HOC,
270 		.param = member_params,
271 		.count = CONFIG_BT_MAX_CONN + 1,
272 	};
273 	int err;
274 
275 	for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
276 		member_params[i].member.member = &fixture->conns[i];
277 		member_params[i].gain = 10 + i;
278 	}
279 
280 	err = bt_cap_commander_change_microphone_gain_setting(&param);
281 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
282 }
283 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_mute_state)284 ZTEST_F(cap_commander_test_micp, test_commander_change_microphone_mute_state)
285 {
286 	union bt_cap_set_member members[ARRAY_SIZE(fixture->conns)];
287 	const struct bt_cap_commander_change_microphone_mute_state_param param = {
288 		.type = BT_CAP_SET_TYPE_AD_HOC,
289 		.members = members,
290 		.count = ARRAY_SIZE(fixture->conns),
291 		.mute = true,
292 	};
293 	int err;
294 
295 	for (size_t i = 0U; i < ARRAY_SIZE(members); i++) {
296 		members[i].member = &fixture->conns[i];
297 	}
298 
299 	err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
300 	zassert_equal(0, err, "Unexpected return value %d", err);
301 
302 	for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
303 		struct bt_micp_mic_ctlr *mic_ctlr; /* We don't care about this */
304 
305 		err = bt_micp_mic_ctlr_discover(&fixture->conns[i], &mic_ctlr);
306 		zassert_equal(0, err, "Unexpected return value %d", err);
307 	}
308 
309 	err = bt_cap_commander_change_microphone_mute_state(&param);
310 	zassert_equal(0, err, "Unexpected return value %d", err);
311 
312 	zexpect_call_count("bt_cap_commander_cb.microphone_mute_changed", 1,
313 			   mock_cap_commander_microphone_mute_changed_cb_fake.call_count);
314 }
315 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_mute_state_double)316 ZTEST_F(cap_commander_test_micp, test_commander_change_microphone_mute_state_double)
317 {
318 	union bt_cap_set_member members[ARRAY_SIZE(fixture->conns)];
319 	const struct bt_cap_commander_change_microphone_mute_state_param param = {
320 		.type = BT_CAP_SET_TYPE_AD_HOC,
321 		.members = members,
322 		.count = ARRAY_SIZE(fixture->conns),
323 		.mute = true,
324 	};
325 	int err;
326 
327 	for (size_t i = 0U; i < ARRAY_SIZE(members); i++) {
328 		members[i].member = &fixture->conns[i];
329 	}
330 
331 	err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
332 	zassert_equal(0, err, "Unexpected return value %d", err);
333 
334 	for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
335 		struct bt_micp_mic_ctlr *mic_ctlr; /* We don't care about this */
336 
337 		err = bt_micp_mic_ctlr_discover(&fixture->conns[i], &mic_ctlr);
338 		zassert_equal(0, err, "Unexpected return value %d", err);
339 	}
340 
341 	err = bt_cap_commander_change_microphone_mute_state(&param);
342 	zassert_equal(0, err, "Unexpected return value %d", err);
343 
344 	zexpect_call_count("bt_cap_commander_cb.microphone_mute_changed", 1,
345 			   mock_cap_commander_microphone_mute_changed_cb_fake.call_count);
346 
347 	/* Test that it still works as expected if we set the same value twice */
348 	err = bt_cap_commander_change_microphone_mute_state(&param);
349 	zassert_equal(0, err, "Unexpected return value %d", err);
350 
351 	zexpect_call_count("bt_cap_commander_cb.microphone_mute_changed", 2,
352 			   mock_cap_commander_microphone_mute_changed_cb_fake.call_count);
353 }
354 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_mute_state_inval_param_null)355 ZTEST_F(cap_commander_test_micp, test_commander_change_microphone_mute_state_inval_param_null)
356 {
357 	int err;
358 
359 	err = bt_cap_commander_change_microphone_mute_state(NULL);
360 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
361 }
362 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_mute_state_inval_param_null_members)363 ZTEST_F(cap_commander_test_micp,
364 	test_commander_change_microphone_mute_state_inval_param_null_members)
365 {
366 	const struct bt_cap_commander_change_microphone_mute_state_param param = {
367 		.type = BT_CAP_SET_TYPE_AD_HOC,
368 		.members = NULL,
369 		.count = ARRAY_SIZE(fixture->conns),
370 		.mute = true,
371 	};
372 	int err;
373 
374 	err = bt_cap_commander_change_microphone_mute_state(&param);
375 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
376 }
377 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_mute_state_inval_param_null_member)378 ZTEST_F(cap_commander_test_micp,
379 	test_commander_change_microphone_mute_state_inval_param_null_member)
380 {
381 	union bt_cap_set_member members[ARRAY_SIZE(fixture->conns)];
382 	const struct bt_cap_commander_change_microphone_mute_state_param param = {
383 		.type = BT_CAP_SET_TYPE_AD_HOC,
384 		.members = members,
385 		.count = ARRAY_SIZE(fixture->conns),
386 		.mute = true,
387 	};
388 	int err;
389 
390 	for (size_t i = 0U; i < ARRAY_SIZE(members) - 1; i++) {
391 		members[i].member = &fixture->conns[i];
392 	}
393 	members[ARRAY_SIZE(members) - 1].member = NULL;
394 
395 	err = bt_cap_commander_change_microphone_mute_state(&param);
396 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
397 }
398 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_mute_state_inval_missing_cas)399 ZTEST_F(cap_commander_test_micp, test_commander_change_microphone_mute_state_inval_missing_cas)
400 {
401 	union bt_cap_set_member members[ARRAY_SIZE(fixture->conns)];
402 	const struct bt_cap_commander_change_microphone_mute_state_param param = {
403 		.type = BT_CAP_SET_TYPE_CSIP,
404 		.members = members,
405 		.count = ARRAY_SIZE(fixture->conns),
406 		.mute = true,
407 	};
408 	int err;
409 
410 	for (size_t i = 0U; i < ARRAY_SIZE(members); i++) {
411 		members[i].member = &fixture->conns[i];
412 	}
413 
414 	err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
415 	zassert_equal(0, err, "Unexpected return value %d", err);
416 
417 	for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
418 		struct bt_micp_mic_ctlr *mic_ctlr; /* We don't care about this */
419 
420 		err = bt_micp_mic_ctlr_discover(&fixture->conns[i], &mic_ctlr);
421 		zassert_equal(0, err, "Unexpected return value %d", err);
422 	}
423 
424 	err = bt_cap_commander_change_microphone_mute_state(&param);
425 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
426 }
427 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_mute_state_inval_missing_vcs)428 ZTEST_F(cap_commander_test_micp, test_commander_change_microphone_mute_state_inval_missing_vcs)
429 {
430 	union bt_cap_set_member members[ARRAY_SIZE(fixture->conns)];
431 	const struct bt_cap_commander_change_microphone_mute_state_param param = {
432 		.type = BT_CAP_SET_TYPE_AD_HOC,
433 		.members = members,
434 		.count = ARRAY_SIZE(fixture->conns),
435 		.mute = true,
436 	};
437 	int err;
438 
439 	for (size_t i = 0U; i < ARRAY_SIZE(members); i++) {
440 		members[i].member = &fixture->conns[i];
441 	}
442 
443 	err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
444 	zassert_equal(0, err, "Unexpected return value %d", err);
445 
446 	err = bt_cap_commander_change_microphone_mute_state(&param);
447 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
448 }
449 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_mute_state_inval_param_zero_count)450 ZTEST_F(cap_commander_test_micp, test_commander_change_microphone_mute_state_inval_param_zero_count)
451 {
452 	union bt_cap_set_member members[ARRAY_SIZE(fixture->conns)];
453 	const struct bt_cap_commander_change_microphone_mute_state_param param = {
454 		.type = BT_CAP_SET_TYPE_AD_HOC,
455 		.members = members,
456 		.count = 0U,
457 		.mute = true,
458 	};
459 	int err;
460 
461 	for (size_t i = 0U; i < ARRAY_SIZE(members); i++) {
462 		members[i].member = &fixture->conns[i];
463 	}
464 
465 	err = bt_cap_commander_change_microphone_mute_state(&param);
466 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
467 }
468 
ZTEST_F(cap_commander_test_micp,test_commander_change_microphone_mute_state_inval_param_inval_count)469 ZTEST_F(cap_commander_test_micp,
470 	test_commander_change_microphone_mute_state_inval_param_inval_count)
471 {
472 	union bt_cap_set_member members[ARRAY_SIZE(fixture->conns)];
473 	const struct bt_cap_commander_change_microphone_mute_state_param param = {
474 		.type = BT_CAP_SET_TYPE_AD_HOC,
475 		.members = members,
476 		.count = CONFIG_BT_MAX_CONN + 1,
477 		.mute = true,
478 	};
479 	int err;
480 
481 	for (size_t i = 0U; i < ARRAY_SIZE(members); i++) {
482 		members[i].member = &fixture->conns[i];
483 	}
484 
485 	err = bt_cap_commander_change_microphone_mute_state(&param);
486 	zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
487 }
488