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 <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
316a551ff1
commit
4279cebcbd
4 changed files with 211 additions and 4 deletions
|
@ -6,7 +6,16 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/bluetooth/audio/bap.h>
|
||||
#include <zephyr/bluetooth/audio/bap_lc3_preset.h>
|
||||
#include <zephyr/bluetooth/audio/cap.h>
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
|
||||
void test_mocks_init(void);
|
||||
void test_mocks_cleanup(void);
|
||||
|
||||
void test_conn_init(struct bt_conn *conn);
|
||||
|
||||
void test_unicast_set_state(struct bt_cap_stream *cap_stream, struct bt_conn *conn,
|
||||
struct bt_bap_ep *ep, struct bt_bap_lc3_preset *preset,
|
||||
enum bt_bap_ep_state state);
|
||||
|
|
|
@ -6,12 +6,17 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/bluetooth/audio/bap.h>
|
||||
#include <zephyr/bluetooth/audio/bap_lc3_preset.h>
|
||||
#include <zephyr/bluetooth/audio/cap.h>
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/bluetooth/hci_types.h>
|
||||
|
||||
#include "bap_endpoint.h"
|
||||
#include "cap_initiator.h"
|
||||
#include "conn.h"
|
||||
#include "test_common.h"
|
||||
#include "ztest_assert.h"
|
||||
|
||||
void test_mocks_init(void)
|
||||
{
|
||||
|
@ -33,3 +38,27 @@ void test_conn_init(struct bt_conn *conn)
|
|||
conn->info.security.enc_key_size = BT_ENC_KEY_SIZE_MAX;
|
||||
conn->info.security.flags = BT_SECURITY_FLAG_OOB | BT_SECURITY_FLAG_SC;
|
||||
}
|
||||
|
||||
void test_unicast_set_state(struct bt_cap_stream *cap_stream, struct bt_conn *conn,
|
||||
struct bt_bap_ep *ep, struct bt_bap_lc3_preset *preset,
|
||||
enum bt_bap_ep_state state)
|
||||
{
|
||||
struct bt_bap_stream *bap_stream = &cap_stream->bap_stream;
|
||||
|
||||
printk("Setting stream %p to state %d\n", bap_stream, state);
|
||||
|
||||
if (state == BT_BAP_EP_STATE_IDLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
zassert_not_null(cap_stream);
|
||||
zassert_not_null(conn);
|
||||
zassert_not_null(ep);
|
||||
zassert_not_null(preset);
|
||||
|
||||
bap_stream->conn = conn;
|
||||
bap_stream->ep = ep;
|
||||
bap_stream->qos = &preset->qos;
|
||||
bap_stream->codec_cfg = &preset->codec_cfg;
|
||||
bap_stream->ep->status.state = state;
|
||||
}
|
||||
|
|
|
@ -92,6 +92,9 @@ static void cap_initiator_test_unicast_start_after(void *f)
|
|||
for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
|
||||
mock_bt_conn_disconnected(&fixture->conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN);
|
||||
}
|
||||
|
||||
/* In the case of a test failing, we cancel the procedure so that subsequent won't fail */
|
||||
bt_cap_initiator_unicast_audio_cancel();
|
||||
}
|
||||
|
||||
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)
|
|||
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
|
||||
stream_params[i].stream = &fixture->cap_streams[i];
|
||||
stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
|
||||
/* Distribute the streams equally among the connections */
|
||||
stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
|
||||
stream_params[i].ep = &fixture->eps[i];
|
||||
}
|
||||
|
@ -128,11 +132,11 @@ static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start)
|
|||
mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
|
||||
const enum bt_bap_ep_state state =
|
||||
fixture->cap_streams[i].bap_stream.ep->status.state;
|
||||
const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
|
||||
const enum bt_bap_ep_state state = bap_stream->ep->status.state;
|
||||
|
||||
zassert_equal(state, BT_BAP_EP_STATE_STREAMING, "[%zu] Unexpected state: %d", i,
|
||||
state);
|
||||
zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
|
||||
"[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,3 +388,115 @@ static ZTEST_F(cap_initiator_test_unicast_start,
|
|||
zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 0,
|
||||
mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
|
||||
}
|
||||
|
||||
static ZTEST_F(cap_initiator_test_unicast_start,
|
||||
test_initiator_unicast_start_state_codec_configured)
|
||||
{
|
||||
struct bt_cap_unicast_audio_start_stream_param
|
||||
stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
|
||||
const struct bt_cap_unicast_audio_start_param param = {
|
||||
.type = BT_CAP_SET_TYPE_AD_HOC,
|
||||
.count = ARRAY_SIZE(stream_params),
|
||||
.stream_params = stream_params,
|
||||
};
|
||||
int err;
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
|
||||
stream_params[i].stream = &fixture->cap_streams[i];
|
||||
stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
|
||||
stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
|
||||
stream_params[i].ep = &fixture->eps[i];
|
||||
|
||||
test_unicast_set_state(stream_params[i].stream, stream_params[i].member.member,
|
||||
stream_params[i].ep, &fixture->preset,
|
||||
BT_BAP_EP_STATE_CODEC_CONFIGURED);
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_unicast_audio_start(¶m);
|
||||
zassert_equal(err, 0, "Unexpected return value %d", err);
|
||||
|
||||
zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 1,
|
||||
mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
|
||||
const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
|
||||
const enum bt_bap_ep_state state = bap_stream->ep->status.state;
|
||||
|
||||
zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
|
||||
"[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
|
||||
}
|
||||
}
|
||||
|
||||
static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_state_qos_configured)
|
||||
{
|
||||
struct bt_cap_unicast_audio_start_stream_param
|
||||
stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
|
||||
const struct bt_cap_unicast_audio_start_param param = {
|
||||
.type = BT_CAP_SET_TYPE_AD_HOC,
|
||||
.count = ARRAY_SIZE(stream_params),
|
||||
.stream_params = stream_params,
|
||||
};
|
||||
int err;
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
|
||||
stream_params[i].stream = &fixture->cap_streams[i];
|
||||
stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
|
||||
stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
|
||||
stream_params[i].ep = &fixture->eps[i];
|
||||
|
||||
test_unicast_set_state(stream_params[i].stream, stream_params[i].member.member,
|
||||
stream_params[i].ep, &fixture->preset,
|
||||
BT_BAP_EP_STATE_QOS_CONFIGURED);
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_unicast_audio_start(¶m);
|
||||
zassert_equal(err, 0, "Unexpected return value %d", err);
|
||||
|
||||
zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 1,
|
||||
mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
|
||||
const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
|
||||
const enum bt_bap_ep_state state = bap_stream->ep->status.state;
|
||||
|
||||
zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
|
||||
"[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
|
||||
}
|
||||
}
|
||||
|
||||
static ZTEST_F(cap_initiator_test_unicast_start, test_initiator_unicast_start_state_enabling)
|
||||
{
|
||||
struct bt_cap_unicast_audio_start_stream_param
|
||||
stream_params[CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT] = {0};
|
||||
const struct bt_cap_unicast_audio_start_param param = {
|
||||
.type = BT_CAP_SET_TYPE_AD_HOC,
|
||||
.count = ARRAY_SIZE(stream_params),
|
||||
.stream_params = stream_params,
|
||||
};
|
||||
int err;
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
|
||||
stream_params[i].stream = &fixture->cap_streams[i];
|
||||
stream_params[i].codec_cfg = &fixture->preset.codec_cfg;
|
||||
stream_params[i].member.member = &fixture->conns[i % ARRAY_SIZE(fixture->conns)];
|
||||
stream_params[i].ep = &fixture->eps[i];
|
||||
|
||||
test_unicast_set_state(stream_params[i].stream, stream_params[i].member.member,
|
||||
stream_params[i].ep, &fixture->preset,
|
||||
BT_BAP_EP_STATE_ENABLING);
|
||||
}
|
||||
|
||||
err = bt_cap_initiator_unicast_audio_start(¶m);
|
||||
zassert_equal(err, 0, "Unexpected return value %d", err);
|
||||
|
||||
zexpect_call_count("bt_cap_initiator_cb.unicast_start_complete_cb", 1,
|
||||
mock_cap_initiator_unicast_start_complete_cb_fake.call_count);
|
||||
|
||||
for (size_t i = 0U; i < ARRAY_SIZE(stream_params); i++) {
|
||||
const struct bt_bap_stream *bap_stream = &fixture->cap_streams[i].bap_stream;
|
||||
const enum bt_bap_ep_state state = bap_stream->ep->status.state;
|
||||
|
||||
zassert_equal(state, BT_BAP_EP_STATE_STREAMING,
|
||||
"[%zu]: Stream %p unexpected state: %d", i, bap_stream, state);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
|
||||
#include <zephyr/bluetooth/audio/audio.h>
|
||||
#include <zephyr/bluetooth/audio/bap.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
#include <zephyr/sys/slist.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include "bap_endpoint.h"
|
||||
#include "ztest_assert.h"
|
||||
|
@ -29,6 +31,14 @@ int bt_bap_unicast_client_config(struct bt_bap_stream *stream,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (stream->ep->status.state) {
|
||||
case BT_BAP_EP_STATE_IDLE:
|
||||
case BT_BAP_EP_STATE_CODEC_CONFIGURED:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
stream->ep->status.state = BT_BAP_EP_STATE_CODEC_CONFIGURED;
|
||||
|
||||
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
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
|
||||
if (stream->conn == conn) {
|
||||
switch (stream->ep->status.state) {
|
||||
case BT_BAP_EP_STATE_CODEC_CONFIGURED:
|
||||
case BT_BAP_EP_STATE_QOS_CONFIGURED:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SYS_SLIST_FOR_EACH_CONTAINER(&group->streams, stream, _node) {
|
||||
if (stream->conn == conn) {
|
||||
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
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (stream->ep->status.state) {
|
||||
case BT_BAP_EP_STATE_QOS_CONFIGURED:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
stream->ep->status.state = BT_BAP_EP_STATE_ENABLING;
|
||||
|
||||
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
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (stream->ep->status.state) {
|
||||
case BT_BAP_EP_STATE_ENABLING:
|
||||
case BT_BAP_EP_STATE_STREAMING:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (stream->ops != NULL && stream->ops->metadata_updated != NULL) {
|
||||
stream->ops->metadata_updated(stream);
|
||||
}
|
||||
|
@ -97,6 +134,14 @@ int bt_bap_unicast_client_connect(struct bt_bap_stream *stream)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (stream->ep->status.state) {
|
||||
case BT_BAP_EP_STATE_QOS_CONFIGURED:
|
||||
case BT_BAP_EP_STATE_ENABLING:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (stream->ops != NULL && stream->ops->connected != NULL) {
|
||||
stream->ops->connected(stream);
|
||||
}
|
||||
|
@ -104,6 +149,7 @@ int bt_bap_unicast_client_connect(struct bt_bap_stream *stream)
|
|||
if (stream->ep != NULL && stream->ep->dir == BT_AUDIO_DIR_SINK) {
|
||||
/* Mocking that the unicast server automatically starts the stream */
|
||||
stream->ep->status.state = BT_BAP_EP_STATE_STREAMING;
|
||||
printk("A %s %p\n", __func__, stream);
|
||||
|
||||
if (stream->ops != NULL && stream->ops->started != NULL) {
|
||||
stream->ops->started(stream);
|
||||
|
@ -120,6 +166,13 @@ int bt_bap_unicast_client_start(struct bt_bap_stream *stream)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (stream->ep->status.state) {
|
||||
case BT_BAP_EP_STATE_ENABLING:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
stream->ep->status.state = BT_BAP_EP_STATE_STREAMING;
|
||||
|
||||
if (stream->ops != NULL && stream->ops->started != NULL) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue