Skip to content

Commit 4279ceb

Browse files
Thalleycarlescufi
authored andcommitted
tests: Bluetooth: CAP: Ensure that unicast_start works in any state
The unicast_start procedure should take a stream in any state and put it in the streaming state. Adds tests with streams in various states. Signed-off-by: Emil Gydesen <[email protected]>
1 parent 316a551 commit 4279ceb

File tree

4 files changed

+211
-4
lines changed

4 files changed

+211
-4
lines changed

tests/bluetooth/audio/cap_initiator/include/test_common.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,16 @@
66
* SPDX-License-Identifier: Apache-2.0
77
*/
88

9+
#include <zephyr/bluetooth/audio/bap.h>
10+
#include <zephyr/bluetooth/audio/bap_lc3_preset.h>
11+
#include <zephyr/bluetooth/audio/cap.h>
12+
#include <zephyr/bluetooth/conn.h>
13+
914
void test_mocks_init(void);
1015
void test_mocks_cleanup(void);
1116

1217
void test_conn_init(struct bt_conn *conn);
18+
19+
void test_unicast_set_state(struct bt_cap_stream *cap_stream, struct bt_conn *conn,
20+
struct bt_bap_ep *ep, struct bt_bap_lc3_preset *preset,
21+
enum bt_bap_ep_state state);

tests/bluetooth/audio/cap_initiator/src/test_common.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66
* SPDX-License-Identifier: Apache-2.0
77
*/
88

9+
#include <zephyr/bluetooth/audio/bap.h>
10+
#include <zephyr/bluetooth/audio/bap_lc3_preset.h>
11+
#include <zephyr/bluetooth/audio/cap.h>
912
#include <zephyr/bluetooth/conn.h>
1013
#include <zephyr/bluetooth/hci_types.h>
1114

15+
#include "bap_endpoint.h"
1216
#include "cap_initiator.h"
1317
#include "conn.h"
1418
#include "test_common.h"
19+
#include "ztest_assert.h"
1520

1621
void test_mocks_init(void)
1722
{
@@ -33,3 +38,27 @@ void test_conn_init(struct bt_conn *conn)
3338
conn->info.security.enc_key_size = BT_ENC_KEY_SIZE_MAX;
3439
conn->info.security.flags = BT_SECURITY_FLAG_OOB | BT_SECURITY_FLAG_SC;
3540
}
41+
42+
void test_unicast_set_state(struct bt_cap_stream *cap_stream, struct bt_conn *conn,
43+
struct bt_bap_ep *ep, struct bt_bap_lc3_preset *preset,
44+
enum bt_bap_ep_state state)
45+
{
46+
struct bt_bap_stream *bap_stream = &cap_stream->bap_stream;
47+
48+
printk("Setting stream %p to state %d\n", bap_stream, state);
49+
50+
if (state == BT_BAP_EP_STATE_IDLE) {
51+
return;
52+
}
53+
54+
zassert_not_null(cap_stream);
55+
zassert_not_null(conn);
56+
zassert_not_null(ep);
57+
zassert_not_null(preset);
58+
59+
bap_stream->conn = conn;
60+
bap_stream->ep = ep;
61+
bap_stream->qos = &preset->qos;
62+
bap_stream->codec_cfg = &preset->codec_cfg;
63+
bap_stream->ep->status.state = state;
64+
}

tests/bluetooth/audio/cap_initiator/src/test_unicast_start.c

Lines changed: 120 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ static void cap_initiator_test_unicast_start_after(void *f)
9292
for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
9393
mock_bt_conn_disconnected(&fixture->conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN);
9494
}
95+
96+
/* In the case of a test failing, we cancel the procedure so that subsequent won't fail */
97+
bt_cap_initiator_unicast_audio_cancel();
9598
}
9699

97100
static void cap_initiator_test_unicast_start_teardown(void *f)
@@ -117,6 +120,7 @@ static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start)
117120
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
118121
stream_params[i].stream = &fixture->cap_streams[i];
119122
stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
123+
/* Distribute the streams equally among the connections */
120124
stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
121125
stream_params[i].ep = &fixture->eps[i];
122126
}
@@ -128,11 +132,11 @@ static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start)
128132
mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
129133

130134
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
131-
const enum bt_bap_ep_state state =
132-
fixture->cap_streams[i].bap_stream.ep->status.state;
135+
const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
136+
const enum bt_bap_ep_state state = bap_stream->ep->status.state;
133137

134-
zassert_equal(state, BT_BAP_EP_STATE_STREAMING, "[%zu] Unexpected state: %d", i,
135-
state);
138+
zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
139+
"[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
136140
}
137141
}
138142

@@ -384,3 +388,115 @@ static ZTEST_F(cap_initiator_test_unicast_start,
384388
zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
385389
mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
386390
}
391+
392+
static ZTEST_F(cap_initiator_test_unicast_start,
393+
test_initiator_unicast_start_state_codec_configured)
394+
{
395+
struct bt_cap_unicast_audio_start_stream_param
396+
stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
397+
const struct bt_cap_unicast_audio_start_param param = {
398+
.type = BT_CAP_SET_TYPE_AD_HOC,
399+
.count = ARRAY_SIZE(stream_params),
400+
.stream_params = stream_params,
401+
};
402+
int err;
403+
404+
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
405+
stream_params[i].stream = &fixture->cap_streams[i];
406+
stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
407+
stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
408+
stream_params[i].ep = &fixture->eps[i];
409+
410+
test_unicast_set_state(stream_params[i].stream, stream_params[i].member.member,
411+
stream_params[i].ep, &fixture->preset,
412+
BT_BAP_EP_STATE_CODEC_CONFIGURED);
413+
}
414+
415+
err = bt_cap_initiator_unicast_audio_start(&param);
416+
zassert_equal(err, 0, "Unexpected return value %d", err);
417+
418+
zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 1,
419+
mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
420+
421+
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
422+
const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
423+
const enum bt_bap_ep_state state = bap_stream->ep->status.state;
424+
425+
zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
426+
"[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
427+
}
428+
}
429+
430+
static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_state_qos_configured)
431+
{
432+
struct bt_cap_unicast_audio_start_stream_param
433+
stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
434+
const struct bt_cap_unicast_audio_start_param param = {
435+
.type = BT_CAP_SET_TYPE_AD_HOC,
436+
.count = ARRAY_SIZE(stream_params),
437+
.stream_params = stream_params,
438+
};
439+
int err;
440+
441+
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
442+
stream_params[i].stream = &fixture->cap_streams[i];
443+
stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
444+
stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
445+
stream_params[i].ep = &fixture->eps[i];
446+
447+
test_unicast_set_state(stream_params[i].stream, stream_params[i].member.member,
448+
stream_params[i].ep, &fixture->preset,
449+
BT_BAP_EP_STATE_QOS_CONFIGURED);
450+
}
451+
452+
err = bt_cap_initiator_unicast_audio_start(&param);
453+
zassert_equal(err, 0, "Unexpected return value %d", err);
454+
455+
zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 1,
456+
mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
457+
458+
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
459+
const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
460+
const enum bt_bap_ep_state state = bap_stream->ep->status.state;
461+
462+
zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
463+
"[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
464+
}
465+
}
466+
467+
static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_state_enabling)
468+
{
469+
struct bt_cap_unicast_audio_start_stream_param
470+
stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
471+
const struct bt_cap_unicast_audio_start_param param = {
472+
.type = BT_CAP_SET_TYPE_AD_HOC,
473+
.count = ARRAY_SIZE(stream_params),
474+
.stream_params = stream_params,
475+
};
476+
int err;
477+
478+
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
479+
stream_params[i].stream = &fixture->cap_streams[i];
480+
stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
481+
stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
482+
stream_params[i].ep = &fixture->eps[i];
483+
484+
test_unicast_set_state(stream_params[i].stream, stream_params[i].member.member,
485+
stream_params[i].ep, &fixture->preset,
486+
BT_BAP_EP_STATE_ENABLING);
487+
}
488+
489+
err = bt_cap_initiator_unicast_audio_start(&param);
490+
zassert_equal(err, 0, "Unexpected return value %d", err);
491+
492+
zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 1,
493+
mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
494+
495+
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
496+
const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
497+
const enum bt_bap_ep_state state = bap_stream->ep->status.state;
498+
499+
zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
500+
"[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
501+
}
502+
}

tests/bluetooth/audio/cap_initiator/uut/bap_unicast_client.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212

1313
#include <zephyr/bluetooth/audio/audio.h>
1414
#include <zephyr/bluetooth/audio/bap.h>
15+
#include <zephyr/sys/printk.h>
1516
#include <zephyr/sys/slist.h>
17+
#include <sys/errno.h>
1618

1719
#include "bap_endpoint.h"
1820
#include "ztest_assert.h"
@@ -29,6 +31,14 @@ int bt_bap_unicast_client_config(struct bt_bap_stream *stream,
2931
return -EINVAL;
3032
}
3133

34+
switch (stream->ep->status.state) {
35+
case BT_BAP_EP_STATE_IDLE:
36+
case BT_BAP_EP_STATE_CODEC_CONFIGURED:
37+
break;
38+
default:
39+
return -EINVAL;
40+
}
41+
3242
stream->ep->status.state = BT_BAP_EP_STATE_CODEC_CONFIGURED;
3343

3444
if (stream->ops != NULL && stream->ops->configured != NULL) {
@@ -48,6 +58,18 @@ int bt_bap_unicast_client_qos(struct bt_conn *conn, struct bt_bap_unicast_group
4858
return -EINVAL;
4959
}
5060

61+
SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
62+
if (stream->conn == conn) {
63+
switch (stream->ep->status.state) {
64+
case BT_BAP_EP_STATE_CODEC_CONFIGURED:
65+
case BT_BAP_EP_STATE_QOS_CONFIGURED:
66+
break;
67+
default:
68+
return -EINVAL;
69+
}
70+
}
71+
}
72+
5173
SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
5274
if (stream->conn == conn) {
5375
stream->ep->status.state = BT_BAP_EP_STATE_QOS_CONFIGURED;
@@ -68,6 +90,13 @@ int bt_bap_unicast_client_enable(struct bt_bap_stream *stream, const uint8_t met
6890
return -EINVAL;
6991
}
7092

93+
switch (stream->ep->status.state) {
94+
case BT_BAP_EP_STATE_QOS_CONFIGURED:
95+
break;
96+
default:
97+
return -EINVAL;
98+
}
99+
71100
stream->ep->status.state = BT_BAP_EP_STATE_ENABLING;
72101

73102
if (stream->ops != NULL && stream->ops->enabled != NULL) {
@@ -84,6 +113,14 @@ int bt_bap_unicast_client_metadata(struct bt_bap_stream *stream, const uint8_t m
84113
return -EINVAL;
85114
}
86115

116+
switch (stream->ep->status.state) {
117+
case BT_BAP_EP_STATE_ENABLING:
118+
case BT_BAP_EP_STATE_STREAMING:
119+
break;
120+
default:
121+
return -EINVAL;
122+
}
123+
87124
if (stream->ops != NULL && stream->ops->metadata_updated != NULL) {
88125
stream->ops->metadata_updated(stream);
89126
}
@@ -97,13 +134,22 @@ int bt_bap_unicast_client_connect(struct bt_bap_stream *stream)
97134
return -EINVAL;
98135
}
99136

137+
switch (stream->ep->status.state) {
138+
case BT_BAP_EP_STATE_QOS_CONFIGURED:
139+
case BT_BAP_EP_STATE_ENABLING:
140+
break;
141+
default:
142+
return -EINVAL;
143+
}
144+
100145
if (stream->ops != NULL && stream->ops->connected != NULL) {
101146
stream->ops->connected(stream);
102147
}
103148

104149
if (stream->ep != NULL && stream->ep->dir == BT_AUDIO_DIR_SINK) {
105150
/* Mocking that the unicast server automatically starts the stream */
106151
stream->ep->status.state = BT_BAP_EP_STATE_STREAMING;
152+
printk("A %s %p\n", __func__, stream);
107153

108154
if (stream->ops != NULL && stream->ops->started != NULL) {
109155
stream->ops->started(stream);
@@ -120,6 +166,13 @@ int bt_bap_unicast_client_start(struct bt_bap_stream *stream)
120166
return -EINVAL;
121167
}
122168

169+
switch (stream->ep->status.state) {
170+
case BT_BAP_EP_STATE_ENABLING:
171+
break;
172+
default:
173+
return -EINVAL;
174+
}
175+
123176
stream->ep->status.state = BT_BAP_EP_STATE_STREAMING;
124177

125178
if (stream->ops != NULL && stream->ops->started != NULL) {

0 commit comments

Comments
 (0)