Skip to content

Commit c9a9f0a

Browse files
Andries Kruithofkartben
authored andcommitted
Bluetooth: Audio: Add tests for the CAP cancel command
This adds unittests and babblesim tests for the CAP cancel command Signed-off-by: Andries Kruithof <[email protected]>
1 parent 1115cd5 commit c9a9f0a

File tree

7 files changed

+365
-4
lines changed

7 files changed

+365
-4
lines changed

tests/bluetooth/audio/cap_commander/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ target_sources(testbinary
2020
src/test_micp.c
2121
src/test_broadcast_reception.c
2222
src/test_distribute_broadcast_code.c
23+
src/test_cancel.c
2324
)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright (c) 2023 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef UUT_BAP_BROADCAST_ASSISTANT_H_
8+
#define UUT_BAP_BROADCAST_ASSISTANT_H_
9+
10+
void set_skip_add_src(unsigned int nr_to_skip);
11+
12+
#endif /* UUT_BAP_BROADCAST_ASSISTANT_H_ */

tests/bluetooth/audio/cap_commander/src/test_broadcast_reception.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ static void test_start_param_init(void *f)
129129
fixture->start_param.count = ARRAY_SIZE(fixture->start_member_params);
130130

131131
for (size_t i = 0; i < ARRAY_SIZE(fixture->subgroups); i++) {
132-
fixture->subgroups[i].bis_sync = 1 << i;
132+
fixture->subgroups[i].bis_sync = BIT(i);
133133
fixture->subgroups[i].metadata_len = 0;
134134
}
135135

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

tests/bluetooth/audio/cap_commander/uut/bap_broadcast_assistant.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,25 @@
77
#include "zephyr/bluetooth/audio/bap.h"
88
#include "test_common.h"
99

10+
#include "bap_broadcast_assistant.h"
11+
1012
static sys_slist_t broadcast_assistant_cbs = SYS_SLIST_STATIC_INIT(&broadcast_assistant_cbs);
1113

14+
/* when > 0 immediately return from the add_src callback the specified number of times
15+
* This allows us to test the CAP cancel command by not successfully sending all the
16+
* requests, so that we can cancel before the CAP commander implementation is done
17+
* with the procedure.
18+
* This is based on the fact that we are not actually sending any requests on air, and
19+
* that we are using this function as a synchronous function, rather than an asynchronous
20+
* function.
21+
*/
22+
static unsigned int add_src_skip;
23+
24+
void set_skip_add_src(unsigned int setting)
25+
{
26+
add_src_skip = setting;
27+
}
28+
1229
struct bap_broadcast_assistant_recv_state_info {
1330
uint8_t src_id;
1431
/** Cached PAST available */
@@ -83,6 +100,12 @@ int bt_bap_broadcast_assistant_add_src(struct bt_conn *conn,
83100
struct bt_bap_scan_delegator_recv_state state;
84101
struct bt_bap_broadcast_assistant_cb *listener, *next;
85102

103+
if (add_src_skip != 0) {
104+
add_src_skip--;
105+
106+
return 0;
107+
}
108+
86109
/* Note that proper parameter checking is done in the caller */
87110
zassert_not_null(conn, "conn is NULL");
88111
zassert_not_null(param, "param is NULL");

0 commit comments

Comments
 (0)