1 /* test_unicast_start.c - unit test for unicast start procedure */
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 <stddef.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include <zephyr/autoconf.h>
15 #include <zephyr/bluetooth/audio/audio.h>
16 #include <zephyr/bluetooth/audio/bap.h>
17 #include <zephyr/bluetooth/audio/bap_lc3_preset.h>
18 #include <zephyr/bluetooth/audio/cap.h>
19 #include <zephyr/bluetooth/hci_types.h>
20 #include <zephyr/fff.h>
21 #include <zephyr/sys/slist.h>
22 #include <zephyr/sys/util.h>
23 #include <sys/errno.h>
24 
25 #include "bap_endpoint.h"
26 #include "cap_initiator.h"
27 #include "conn.h"
28 #include "expects_util.h"
29 #include "test_common.h"
30 #include "ztest_assert.h"
31 #include "ztest_test.h"
32 
33 struct cap_initiator_test_unicast_start_fixture {
34 	struct bt_cap_stream cap_streams[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT];
35 	struct bt_bap_ep eps[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT];
36 	struct bt_bap_unicast_group unicast_group;
37 	struct bt_conn conns[CONFIG_BT_MAX_CONN];
38 	struct bt_bap_lc3_preset preset;
39 };
40 
cap_initiator_test_unicast_start_fixture_init(struct cap_initiator_test_unicast_start_fixture * fixture)41 static void cap_initiator_test_unicast_start_fixture_init(
42 	struct cap_initiator_test_unicast_start_fixture *fixture)
43 {
44 	fixture->preset = (struct bt_bap_lc3_preset)BT_BAP_LC3_UNICAST_PRESET_16_2_1(
45 		BT_AUDIO_LOCATION_MONO_AUDIO, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
46 
47 	for (size_t i = 0U; i < ARRAY_SIZE(fixture->conns); i++) {
48 		test_conn_init(&fixture->conns[i]);
49 	}
50 
51 	for (size_t i = 0U; i < ARRAY_SIZE(fixture->cap_streams); i++) {
52 		struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
53 
54 		sys_slist_append(&fixture->unicast_group.streams, &bap_stream->_node);
55 		bap_stream->group = &fixture->unicast_group;
56 	}
57 
58 	for (size_t i = 0U; i < ARRAY_SIZE(fixture->eps); i++) {
59 		fixture->eps[i].dir = (i & 1) + 1; /* Makes it either 1 or 2 (sink or source)*/
60 	}
61 }
62 
cap_initiator_test_unicast_start_setup(void)63 static void *cap_initiator_test_unicast_start_setup(void)
64 {
65 	struct cap_initiator_test_unicast_start_fixture *fixture;
66 
67 	fixture = malloc(sizeof(*fixture));
68 	zassert_not_null(fixture);
69 
70 	return fixture;
71 }
72 
cap_initiator_test_unicast_start_before(void * f)73 static void cap_initiator_test_unicast_start_before(void *f)
74 {
75 	int err;
76 
77 	memset(f, 0, sizeof(struct cap_initiator_test_unicast_start_fixture));
78 	cap_initiator_test_unicast_start_fixture_init(f);
79 
80 	err = bt_cap_initiator_register_cb(&mock_cap_initiator_cb);
81 	zassert_equal(0, err, "Unexpected return value %d", err);
82 }
83 
cap_initiator_test_unicast_start_after(void * f)84 static void cap_initiator_test_unicast_start_after(void *f)
85 {
86 	struct cap_initiator_test_unicast_start_fixture *fixture = f;
87 
88 	bt_cap_initiator_unregister_cb(&mock_cap_initiator_cb);
89 
90 	for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
91 		mock_bt_conn_disconnected(&fixture->conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN);
92 	}
93 
94 	/* In the case of a test failing, we cancel the procedure so that subsequent won't fail */
95 	bt_cap_initiator_unicast_audio_cancel();
96 }
97 
cap_initiator_test_unicast_start_teardown(void * f)98 static void cap_initiator_test_unicast_start_teardown(void *f)
99 {
100 	free(f);
101 }
102 
103 ZTEST_SUITE(cap_initiator_test_unicast_start, NULL, cap_initiator_test_unicast_start_setup,
104 	    cap_initiator_test_unicast_start_before, cap_initiator_test_unicast_start_after,
105 	    cap_initiator_test_unicast_start_teardown);
106 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start)107 static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start)
108 {
109 	struct bt_cap_unicast_audio_start_stream_param
110 		stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
111 	const struct bt_cap_unicast_audio_start_param param = {
112 		.type = BT_CAP_SET_TYPE_AD_HOC,
113 		.count = ARRAY_SIZE(stream_params),
114 		.stream_params = stream_params,
115 	};
116 	int err;
117 
118 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
119 		stream_params[i].stream = &fixture->cap_streams[i];
120 		stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
121 		/* Distribute the streams equally among the connections */
122 		stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
123 		stream_params[i].ep = &fixture->eps[i];
124 	}
125 
126 	err = bt_cap_initiator_unicast_audio_start(&param);
127 	zassert_equal(err, 0, "Unexpected return value %d", err);
128 
129 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 1,
130 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
131 
132 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
133 		const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
134 		const enum bt_bap_ep_state state = bap_stream->ep->status.state;
135 
136 		zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
137 			      "[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
138 	}
139 }
140 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_inval_param_null)141 static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_inval_param_null)
142 {
143 	int err;
144 
145 	err = bt_cap_initiator_unicast_audio_start(NULL);
146 	zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
147 
148 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
149 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
150 }
151 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_inval_param_null_param)152 static ZTEST_F(cap_initiator_test_unicast_start,
153 	       test_initiator_unicast_start_inval_param_null_param)
154 {
155 	const struct bt_cap_unicast_audio_start_param param = {
156 		.type = BT_CAP_SET_TYPE_AD_HOC,
157 		.count = CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT,
158 		.stream_params = NULL,
159 	};
160 	int err;
161 
162 	err = bt_cap_initiator_unicast_audio_start(&param);
163 	zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
164 
165 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
166 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
167 }
168 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_inval_param_null_member)169 static ZTEST_F(cap_initiator_test_unicast_start,
170 	       test_initiator_unicast_start_inval_param_null_member)
171 {
172 	struct bt_cap_unicast_audio_start_stream_param
173 		stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
174 	const struct bt_cap_unicast_audio_start_param param = {
175 		.type = BT_CAP_SET_TYPE_AD_HOC,
176 		.count = ARRAY_SIZE(stream_params),
177 		.stream_params = stream_params,
178 	};
179 	int err;
180 
181 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
182 		stream_params[i].stream = &fixture->cap_streams[i];
183 		stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
184 		stream_params[i].ep = &fixture->eps[i];
185 	}
186 
187 	err = bt_cap_initiator_unicast_audio_start(&param);
188 	zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
189 
190 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
191 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
192 }
193 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_inval_missing_cas)194 static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_inval_missing_cas)
195 {
196 	struct bt_cap_unicast_audio_start_stream_param
197 		stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
198 	const struct bt_cap_unicast_audio_start_param param = {
199 		.type = BT_CAP_SET_TYPE_CSIP, /* CSIP requires CAS */
200 		.count = ARRAY_SIZE(stream_params),
201 		.stream_params = stream_params,
202 	};
203 	int err;
204 
205 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
206 		stream_params[i].stream = &fixture->cap_streams[i];
207 		stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
208 		stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
209 		stream_params[i].ep = &fixture->eps[i];
210 	}
211 
212 	err = bt_cap_initiator_unicast_audio_start(&param);
213 	zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
214 
215 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
216 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
217 }
218 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_inval_param_zero_count)219 static ZTEST_F(cap_initiator_test_unicast_start,
220 	       test_initiator_unicast_start_inval_param_zero_count)
221 {
222 	struct bt_cap_unicast_audio_start_stream_param
223 		stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
224 	const struct bt_cap_unicast_audio_start_param param = {
225 		.type = BT_CAP_SET_TYPE_AD_HOC,
226 		.count = 0U,
227 		.stream_params = stream_params,
228 	};
229 	int err;
230 
231 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
232 		stream_params[i].stream = &fixture->cap_streams[i];
233 		stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
234 		stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
235 		stream_params[i].ep = &fixture->eps[i];
236 	}
237 
238 	err = bt_cap_initiator_unicast_audio_start(&param);
239 	zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
240 
241 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
242 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
243 }
244 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_inval_param_inval_count)245 static ZTEST_F(cap_initiator_test_unicast_start,
246 	       test_initiator_unicast_start_inval_param_inval_count)
247 {
248 	struct bt_cap_unicast_audio_start_stream_param
249 		stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
250 	const struct bt_cap_unicast_audio_start_param param = {
251 		.type = BT_CAP_SET_TYPE_AD_HOC,
252 		.count = CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT + 1U,
253 		.stream_params = stream_params,
254 	};
255 	int err;
256 
257 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
258 		stream_params[i].stream = &fixture->cap_streams[i];
259 		stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
260 		stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
261 		stream_params[i].ep = &fixture->eps[i];
262 	}
263 
264 	err = bt_cap_initiator_unicast_audio_start(&param);
265 	zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
266 
267 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
268 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
269 }
270 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_inval_param_inval_stream_param_null_stream)271 static ZTEST_F(cap_initiator_test_unicast_start,
272 	       test_initiator_unicast_start_inval_param_inval_stream_param_null_stream)
273 {
274 	struct bt_cap_unicast_audio_start_stream_param stream_param = {0};
275 	const struct bt_cap_unicast_audio_start_param param = {
276 		.type = BT_CAP_SET_TYPE_AD_HOC,
277 		.count = 1,
278 		.stream_params = &stream_param,
279 	};
280 	int err;
281 
282 	stream_param.stream = NULL;
283 	stream_param.codec_cfg = &fixture->preset.codec_cfg;
284 	stream_param.member.member = &fixture->conns[0];
285 	stream_param.ep = &fixture->eps[0];
286 
287 	err = bt_cap_initiator_unicast_audio_start(&param);
288 	zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
289 
290 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
291 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
292 }
293 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_inval_param_inval_stream_param_null_codec_cfg)294 static ZTEST_F(cap_initiator_test_unicast_start,
295 	       test_initiator_unicast_start_inval_param_inval_stream_param_null_codec_cfg)
296 {
297 	struct bt_cap_unicast_audio_start_stream_param stream_param = {0};
298 	const struct bt_cap_unicast_audio_start_param param = {
299 		.type = BT_CAP_SET_TYPE_AD_HOC,
300 		.count = 1,
301 		.stream_params = &stream_param,
302 	};
303 	int err;
304 
305 	stream_param.stream = &fixture->cap_streams[0];
306 	stream_param.codec_cfg = NULL;
307 	stream_param.member.member = &fixture->conns[0];
308 	stream_param.ep = &fixture->eps[0];
309 
310 	err = bt_cap_initiator_unicast_audio_start(&param);
311 	zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
312 
313 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
314 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
315 }
316 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_inval_param_inval_stream_param_null_member)317 static ZTEST_F(cap_initiator_test_unicast_start,
318 	       test_initiator_unicast_start_inval_param_inval_stream_param_null_member)
319 {
320 	struct bt_cap_unicast_audio_start_stream_param stream_param = {0};
321 	const struct bt_cap_unicast_audio_start_param param = {
322 		.type = BT_CAP_SET_TYPE_AD_HOC,
323 		.count = 1,
324 		.stream_params = &stream_param,
325 	};
326 	int err;
327 
328 	stream_param.stream = &fixture->cap_streams[0];
329 	stream_param.codec_cfg = &fixture->preset.codec_cfg;
330 	stream_param.member.member = NULL;
331 	stream_param.ep = &fixture->eps[0];
332 
333 	err = bt_cap_initiator_unicast_audio_start(&param);
334 	zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
335 
336 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
337 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
338 }
339 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_inval_param_inval_stream_param_null_ep)340 static ZTEST_F(cap_initiator_test_unicast_start,
341 	       test_initiator_unicast_start_inval_param_inval_stream_param_null_ep)
342 {
343 	struct bt_cap_unicast_audio_start_stream_param stream_param = {0};
344 	const struct bt_cap_unicast_audio_start_param param = {
345 		.type = BT_CAP_SET_TYPE_AD_HOC,
346 		.count = 1,
347 		.stream_params = &stream_param,
348 	};
349 	int err;
350 
351 	stream_param.stream = &fixture->cap_streams[0];
352 	stream_param.codec_cfg = &fixture->preset.codec_cfg;
353 	stream_param.member.member = &fixture->conns[0];
354 	stream_param.ep = NULL;
355 
356 	err = bt_cap_initiator_unicast_audio_start(&param);
357 	zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
358 
359 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
360 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
361 }
362 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_inval_param_inval_stream_param_invalid_meta)363 static ZTEST_F(cap_initiator_test_unicast_start,
364 	       test_initiator_unicast_start_inval_param_inval_stream_param_invalid_meta)
365 {
366 	struct bt_cap_unicast_audio_start_stream_param stream_param = {0};
367 	const struct bt_cap_unicast_audio_start_param param = {
368 		.type = BT_CAP_SET_TYPE_AD_HOC,
369 		.count = 1,
370 		.stream_params = &stream_param,
371 	};
372 	int err;
373 
374 	stream_param.stream = &fixture->cap_streams[0];
375 	stream_param.codec_cfg = &fixture->preset.codec_cfg;
376 	stream_param.member.member = &fixture->conns[0];
377 	stream_param.ep = &fixture->eps[0];
378 
379 	/* CAP requires stream context - Let's remove it */
380 	memset(stream_param.codec_cfg->meta, 0, sizeof(stream_param.codec_cfg->meta));
381 	stream_param.codec_cfg->meta_len = 0U;
382 
383 	err = bt_cap_initiator_unicast_audio_start(&param);
384 	zassert_equal(err, -EINVAL, "Unexpected return value %d", err);
385 
386 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
387 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
388 }
389 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_state_codec_configured)390 static ZTEST_F(cap_initiator_test_unicast_start,
391 	       test_initiator_unicast_start_state_codec_configured)
392 {
393 	struct bt_cap_unicast_audio_start_stream_param
394 		stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
395 	const struct bt_cap_unicast_audio_start_param param = {
396 		.type = BT_CAP_SET_TYPE_AD_HOC,
397 		.count = ARRAY_SIZE(stream_params),
398 		.stream_params = stream_params,
399 	};
400 	int err;
401 
402 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
403 		stream_params[i].stream = &fixture->cap_streams[i];
404 		stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
405 		stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
406 		stream_params[i].ep = &fixture->eps[i];
407 
408 		test_unicast_set_state(stream_params[i].stream, stream_params[i].member.member,
409 				       stream_params[i].ep, &fixture->preset,
410 				       BT_BAP_EP_STATE_CODEC_CONFIGURED);
411 	}
412 
413 	err = bt_cap_initiator_unicast_audio_start(&param);
414 	zassert_equal(err, 0, "Unexpected return value %d", err);
415 
416 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 1,
417 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
418 
419 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
420 		const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
421 		const enum bt_bap_ep_state state = bap_stream->ep->status.state;
422 
423 		zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
424 			      "[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
425 	}
426 }
427 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_state_qos_configured)428 static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_state_qos_configured)
429 {
430 	struct bt_cap_unicast_audio_start_stream_param
431 		stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
432 	const struct bt_cap_unicast_audio_start_param param = {
433 		.type = BT_CAP_SET_TYPE_AD_HOC,
434 		.count = ARRAY_SIZE(stream_params),
435 		.stream_params = stream_params,
436 	};
437 	int err;
438 
439 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
440 		stream_params[i].stream = &fixture->cap_streams[i];
441 		stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
442 		stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
443 		stream_params[i].ep = &fixture->eps[i];
444 
445 		test_unicast_set_state(stream_params[i].stream, stream_params[i].member.member,
446 				       stream_params[i].ep, &fixture->preset,
447 				       BT_BAP_EP_STATE_QOS_CONFIGURED);
448 	}
449 
450 	err = bt_cap_initiator_unicast_audio_start(&param);
451 	zassert_equal(err, 0, "Unexpected return value %d", err);
452 
453 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 1,
454 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
455 
456 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
457 		const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
458 		const enum bt_bap_ep_state state = bap_stream->ep->status.state;
459 
460 		zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
461 			      "[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
462 	}
463 }
464 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_state_enabling)465 static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_state_enabling)
466 {
467 	struct bt_cap_unicast_audio_start_stream_param
468 		stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
469 	const struct bt_cap_unicast_audio_start_param param = {
470 		.type = BT_CAP_SET_TYPE_AD_HOC,
471 		.count = ARRAY_SIZE(stream_params),
472 		.stream_params = stream_params,
473 	};
474 	int err;
475 
476 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
477 		stream_params[i].stream = &fixture->cap_streams[i];
478 		stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
479 		stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
480 		stream_params[i].ep = &fixture->eps[i];
481 
482 		test_unicast_set_state(stream_params[i].stream, stream_params[i].member.member,
483 				       stream_params[i].ep, &fixture->preset,
484 				       BT_BAP_EP_STATE_ENABLING);
485 	}
486 
487 	err = bt_cap_initiator_unicast_audio_start(&param);
488 	zassert_equal(err, 0, "Unexpected return value %d", err);
489 
490 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 1,
491 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
492 
493 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
494 		const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
495 		const enum bt_bap_ep_state state = bap_stream->ep->status.state;
496 
497 		zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
498 			      "[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
499 	}
500 }
501 
ZTEST_F(cap_initiator_test_unicast_start,test_initiator_unicast_start_state_streaming)502 static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_state_streaming)
503 {
504 	struct bt_cap_unicast_audio_start_stream_param
505 		stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
506 	const struct bt_cap_unicast_audio_start_param param = {
507 		.type = BT_CAP_SET_TYPE_AD_HOC,
508 		.count = ARRAY_SIZE(stream_params),
509 		.stream_params = stream_params,
510 	};
511 	int err;
512 
513 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
514 		stream_params[i].stream = &fixture->cap_streams[i];
515 		stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
516 		stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
517 		stream_params[i].ep = &fixture->eps[i];
518 
519 		test_unicast_set_state(stream_params[i].stream, stream_params[i].member.member,
520 				       stream_params[i].ep, &fixture->preset,
521 				       BT_BAP_EP_STATE_STREAMING);
522 	}
523 
524 	err = bt_cap_initiator_unicast_audio_start(&param);
525 	zassert_equal(err, -EALREADY, "Unexpected return value %d", err);
526 
527 	zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
528 			   mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
529 
530 	for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
531 		const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
532 		const enum bt_bap_ep_state state = bap_stream->ep->status.state;
533 
534 		zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
535 			      "[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
536 	}
537 }
538