1 /* test_cancel.c - unit test for cancel command */
2 
3 /*
4  * Copyright (c) 2024 Nordic Semiconductor ASA
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 #include <errno.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include <zephyr/autoconf.h>
13 #include <zephyr/bluetooth/addr.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/sys/util.h>
19 #include <zephyr/sys/util_macro.h>
20 #include <zephyr/ztest_assert.h>
21 #include <zephyr/ztest_test.h>
22 
23 #include "cap_commander.h"
24 #include "conn.h"
25 #include "expects_util.h"
26 #include "cap_mocks.h"
27 #include "test_common.h"
28 #include "bap_broadcast_assistant.h"
29 
30 #define FFF_GLOBALS
31 
32 struct cap_commander_test_cancel_fixture {
33 	struct bt_conn conns[CONFIG_BT_MAX_CONN];
34 
35 	struct bt_bap_bass_subgroup subgroups[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS];
36 	struct bt_cap_commander_broadcast_reception_start_member_param
37 		start_member_params[CONFIG_BT_MAX_CONN];
38 	struct bt_cap_commander_broadcast_reception_start_param start_param;
39 };
40 
test_start_param_init(void * f)41 static void test_start_param_init(void *f)
42 {
43 	struct cap_commander_test_cancel_fixture *fixture = f;
44 	int err;
45 
46 	fixture->start_param.type = BT_CAP_SET_TYPE_AD_HOC;
47 	fixture->start_param.param = fixture->start_member_params;
48 
49 	fixture->start_param.count = ARRAY_SIZE(fixture->start_member_params);
50 
51 	for (size_t i = 0; i < ARRAY_SIZE(fixture->subgroups); i++) {
52 		fixture->subgroups[i].bis_sync = BIT(i);
53 		fixture->subgroups[i].metadata_len = 0;
54 	}
55 
56 	for (size_t i = 0U; i < ARRAY_SIZE(fixture->start_member_params); i++) {
57 		fixture->start_member_params[i].member.member = &fixture->conns[i];
58 		bt_addr_le_copy(&fixture->start_member_params[i].addr, BT_ADDR_LE_ANY);
59 		fixture->start_member_params[i].adv_sid = 0;
60 		fixture->start_member_params[i].pa_interval = 10;
61 		fixture->start_member_params[i].broadcast_id = 0;
62 		memcpy(fixture->start_member_params[i].subgroups, &fixture->subgroups[0],
63 		       sizeof(struct bt_bap_bass_subgroup) * CONFIG_BT_BAP_BASS_MAX_SUBGROUPS);
64 		fixture->start_member_params[i].num_subgroups = CONFIG_BT_BAP_BASS_MAX_SUBGROUPS;
65 	}
66 
67 	for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
68 		err = bt_cap_commander_discover(&fixture->conns[i]);
69 		zassert_equal(0, err, "Unexpected return value %d", err);
70 	}
71 }
72 
73 static void
cap_commander_test_cancel_fixture_init(struct cap_commander_test_cancel_fixture * fixture)74 cap_commander_test_cancel_fixture_init(struct cap_commander_test_cancel_fixture *fixture)
75 {
76 	for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
77 		test_conn_init(&fixture->conns[i]);
78 	}
79 
80 	test_start_param_init(fixture);
81 }
82 
cap_commander_test_cancel_setup(void)83 static void *cap_commander_test_cancel_setup(void)
84 {
85 	struct cap_commander_test_cancel_fixture *fixture;
86 
87 	fixture = malloc(sizeof(*fixture));
88 	zassert_not_null(fixture);
89 
90 	return fixture;
91 }
92 
cap_commander_test_cancel_before(void * f)93 static void cap_commander_test_cancel_before(void *f)
94 {
95 	struct cap_commander_test_cancel_fixture *fixture = f;
96 
97 	memset(f, 0, sizeof(struct cap_commander_test_cancel_fixture));
98 	cap_commander_test_cancel_fixture_init(fixture);
99 }
100 
cap_commander_test_cancel_after(void * f)101 static void cap_commander_test_cancel_after(void *f)
102 {
103 	struct cap_commander_test_cancel_fixture *fixture = f;
104 
105 	bt_cap_commander_unregister_cb(&mock_cap_commander_cb);
106 
107 	for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
108 		mock_bt_conn_disconnected(&fixture->conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN);
109 	}
110 }
111 
cap_commander_test_cancel_teardown(void * f)112 static void cap_commander_test_cancel_teardown(void *f)
113 {
114 	free(f);
115 }
116 
test_cancel(void)117 static void test_cancel(void)
118 {
119 	int err;
120 
121 	err = bt_cap_commander_cancel();
122 	zassert_equal(0, err, "Unexpected return value %d", err);
123 
124 	zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 1,
125 			   mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
126 	zassert_equal(-ECANCELED,
127 		      mock_cap_commander_broadcast_reception_start_cb_fake.arg1_history[0]);
128 }
129 
130 ZTEST_SUITE(cap_commander_test_cancel, NULL, cap_commander_test_cancel_setup,
131 	    cap_commander_test_cancel_before, cap_commander_test_cancel_after,
132 	    cap_commander_test_cancel_teardown);
133 
ZTEST_F(cap_commander_test_cancel,test_commander_cancel)134 ZTEST_F(cap_commander_test_cancel, test_commander_cancel)
135 {
136 	int err;
137 
138 	if (CONFIG_BT_MAX_CONN == 1) {
139 		ztest_test_skip();
140 	}
141 
142 	err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
143 	zassert_equal(0, err, "Unexpected return value %d", err);
144 
145 	/* Do not run the add_src callback, so that the broadcast reception start procedure does not
146 	 * run until completion
147 	 */
148 	set_skip_add_src(1);
149 
150 	/* initiate a CAP procedure; for this test we use broadcast reception start*/
151 	err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
152 	zassert_equal(0, err, "Could not start CAP procedure: %d", err);
153 
154 	test_cancel();
155 }
156 
ZTEST_F(cap_commander_test_cancel,test_commander_cancel_double)157 ZTEST_F(cap_commander_test_cancel, test_commander_cancel_double)
158 {
159 	int err;
160 
161 	if (CONFIG_BT_MAX_CONN == 1) {
162 		ztest_test_skip();
163 	}
164 
165 	err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
166 	zassert_equal(0, err, "Unexpected return value %d", err);
167 
168 	set_skip_add_src(1);
169 	err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
170 	zassert_equal(0, err, "Could not start CAP procedure: %d", err);
171 
172 	test_cancel();
173 
174 	err = bt_cap_commander_cancel();
175 	zassert_equal(-EALREADY, err, "Unexpected return value %d", err);
176 }
177 
ZTEST_F(cap_commander_test_cancel,test_commander_cancel_no_proc_in_progress)178 ZTEST_F(cap_commander_test_cancel, test_commander_cancel_no_proc_in_progress)
179 {
180 	int err;
181 
182 	err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
183 	zassert_equal(0, err, "Unexpected return value %d", err);
184 
185 	err = bt_cap_commander_cancel();
186 	zassert_equal(-EALREADY, err, "Unexpected return value %d", err);
187 }
188