Bluetooth: audio: test: Unittests for broadcast reception start

Implement unit tests for the broadcast reception start procedure,
both with proper and with improper parameters.

Signed-off-by: Andries Kruithof <andries.kruithof@nordicsemi.no>
This commit is contained in:
Andries Kruithof 2024-02-08 14:31:17 +01:00 committed by Anas Nashif
parent b2d1e4505f
commit 7902457437
5 changed files with 385 additions and 4 deletions

View file

@ -13,9 +13,11 @@ target_include_directories(testbinary PRIVATE include)
target_sources(testbinary
PRIVATE
${ZEPHYR_BASE}/subsys/bluetooth/host/uuid.c
src/main.c
${ZEPHYR_BASE}/subsys/bluetooth/host/uuid.c
${ZEPHYR_BASE}/subsys/bluetooth/common/addr.c
src/main.c
src/test_common.c
src/test_vcp.c
src/test_micp.c
src/test_broadcast_reception.c
)

View file

@ -18,7 +18,7 @@ CONFIG_BT_CAP_COMMANDER=y
CONFIG_BT_BAP_BROADCAST_ASSISTANT=y
CONFIG_LOG=y
CONFIG_BT_CAP_COMMANDER_LOG_LEVEL_DBG=y
CONFIG_BT_BAP_BASS_MAX_SUBGROUPS=2
CONFIG_ASSERT=y
CONFIG_ASSERT_LEVEL=2
CONFIG_ASSERT_VERBOSE=y

View file

@ -0,0 +1,373 @@
/* test_broadcast_reception.c - unit test for broadcast reception */
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <zephyr/bluetooth/audio/cap.h>
#include <zephyr/bluetooth/audio/vcp.h>
#include <zephyr/fff.h>
#include "bluetooth.h"
#include "cap_commander.h"
#include "conn.h"
#include "expects_util.h"
#include "cap_mocks.h"
#include "test_common.h"
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bt_broadcast_reception_test, CONFIG_BT_CAP_COMMANDER_LOG_LEVEL);
#define FFF_GLOBALS
#define SID 0x0E
#define ADV_INTERVAL 10
#define BROADCAST_ID 0x55AA55
struct cap_commander_test_broadcast_reception_fixture {
struct bt_conn conns[CONFIG_BT_MAX_CONN];
struct bt_bap_bass_subgroup start_subgroups[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS];
struct bt_cap_commander_broadcast_reception_start_member_param
start_member_params[CONFIG_BT_MAX_CONN];
struct bt_cap_commander_broadcast_reception_start_param start_param;
};
static void test_start_param_init(void *f);
static void cap_commander_test_broadcast_reception_fixture_init(
struct cap_commander_test_broadcast_reception_fixture *fixture)
{
for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
test_conn_init(&fixture->conns[i]);
}
test_start_param_init(fixture);
}
static void *cap_commander_test_broadcast_reception_setup(void)
{
struct cap_commander_test_broadcast_reception_fixture *fixture;
fixture = malloc(sizeof(*fixture));
zassert_not_null(fixture);
return fixture;
}
static void cap_commander_test_broadcast_reception_before(void *f)
{
memset(f, 0, sizeof(struct cap_commander_test_broadcast_reception_fixture));
cap_commander_test_broadcast_reception_fixture_init(f);
}
static void cap_commander_test_broadcast_reception_after(void *f)
{
struct cap_commander_test_broadcast_reception_fixture *fixture = f;
bt_cap_commander_unregister_cb(&mock_cap_commander_cb);
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);
}
}
static void cap_commander_test_broadcast_reception_teardown(void *f)
{
free(f);
}
static void test_start_param_init(void *f)
{
struct cap_commander_test_broadcast_reception_fixture *fixture = f;
int err;
fixture->start_param.type = BT_CAP_SET_TYPE_AD_HOC;
fixture->start_param.param = fixture->start_member_params;
fixture->start_param.count = ARRAY_SIZE(fixture->start_member_params);
for (size_t i = 0; i < ARRAY_SIZE(fixture->start_subgroups); i++) {
fixture->start_subgroups[i].bis_sync = 1 << i;
fixture->start_subgroups[i].metadata_len = 0;
}
for (size_t i = 0U; i < ARRAY_SIZE(fixture->start_member_params); i++) {
fixture->start_member_params[i].member.member = &fixture->conns[i];
bt_addr_le_copy(&fixture->start_member_params[i].addr, BT_ADDR_LE_ANY);
fixture->start_member_params[i].adv_sid = SID;
fixture->start_member_params[i].pa_interval = ADV_INTERVAL;
fixture->start_member_params[i].broadcast_id = BROADCAST_ID;
memcpy(fixture->start_member_params[i].subgroups, &fixture->start_subgroups[0],
sizeof(struct bt_bap_bass_subgroup) * CONFIG_BT_BAP_BASS_MAX_SUBGROUPS);
fixture->start_member_params[i].num_subgroups = CONFIG_BT_BAP_BASS_MAX_SUBGROUPS;
}
for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
err = bt_cap_commander_discover(&fixture->conns[i]);
zassert_equal(0, err, "Unexpected return value %d", err);
}
for (size_t i = 0U; i < ARRAY_SIZE(fixture->start_member_params); i++) {
fixture->start_member_params[i].member.member = &fixture->conns[i];
}
}
ZTEST_SUITE(cap_commander_test_broadcast_reception, NULL,
cap_commander_test_broadcast_reception_setup,
cap_commander_test_broadcast_reception_before,
cap_commander_test_broadcast_reception_after,
cap_commander_test_broadcast_reception_teardown);
ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start)
{
int err;
err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
zassert_equal(0, err, "Unexpected return value %d", err);
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(0, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 1,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_one_subgroup)
{
int err;
err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
zassert_equal(0, err, "Unexpected return value %d", err);
/* We test with one subgroup, instead of CONFIG_BT_BAP_BASS_MAX_SUBGROUPS subgroups */
for (size_t i = 0U; i < CONFIG_BT_MAX_CONN; i++) {
fixture->start_param.param[i].num_subgroups = 1;
}
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(0, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 1,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_double)
{
int err;
err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
zassert_equal(0, err, "Unexpected return value %d", err);
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(0, err, "Unexpected return value %d", err);
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(0, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 2,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_param_null)
{
int err;
err = bt_cap_commander_broadcast_reception_start(NULL);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception,
test_commander_reception_start_inval_param_zero_count)
{
int err;
fixture->start_param.count = 0;
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception,
test_commander_reception_start_inval_param_high_count)
{
int err;
fixture->start_param.count = CONFIG_BT_MAX_CONN + 1;
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception,
test_commander_reception_start_inval_param_null_param)
{
int err;
fixture->start_param.type = BT_CAP_SET_TYPE_AD_HOC;
fixture->start_param.param = NULL;
fixture->start_param.count = ARRAY_SIZE(fixture->conns);
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_null_member)
{
int err;
fixture->start_param.param[0].member.member = NULL;
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_missing_cas)
{
int err;
fixture->start_param.type = BT_CAP_SET_TYPE_CSIP;
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_addr_type)
{
int err;
fixture->start_param.param[0].addr.type = BT_ADDR_LE_RANDOM + 1;
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_sid)
{
int err;
fixture->start_param.param[0].adv_sid = BT_GAP_SID_MAX + 1;
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception,
test_commander_reception_start_inval_pa_interval_low)
{
int err;
fixture->start_param.param[0].pa_interval = BT_GAP_PER_ADV_MIN_INTERVAL - 1;
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
/*
* Test for pa_interval_high omitted
* pa_interval is a uint16_t, BT_GAP_PER_ADV_MAX_INTERVAL is defined as 0xFFFF
* and therefor we can not test in the current implementation
*/
ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_broadcast_id)
{
int err;
fixture->start_param.param[0].broadcast_id = BT_AUDIO_BROADCAST_ID_MAX + 1;
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_no_subgroups)
{
int err;
fixture->start_param.param[0].num_subgroups = 0;
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_num_subgroups)
{
int err;
fixture->start_param.param[0].num_subgroups = CONFIG_BT_BAP_BASS_MAX_SUBGROUPS + 1;
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception,
test_commander_reception_start_inval_duplicate_bis_sync)
{
int err;
if (CONFIG_BT_BAP_BASS_MAX_SUBGROUPS == 1) {
ztest_test_skip();
}
fixture->start_param.param[0].subgroups[0].bis_sync =
fixture->start_param.param[0].subgroups[1].bis_sync;
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_start_inval_metadata_len)
{
int err;
fixture->start_param.param[0].subgroups[0].metadata_len =
CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE + 1;
err = bt_cap_commander_broadcast_reception_start(&fixture->start_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_reception_start", 0,
mock_cap_commander_broadcast_reception_start_cb_fake.call_count);
}

View file

@ -23,5 +23,6 @@ DECLARE_FAKE_VOID_FUNC(mock_cap_commander_volume_mute_changed_cb, struct bt_conn
DECLARE_FAKE_VOID_FUNC(mock_cap_commander_volume_offset_changed_cb, struct bt_conn *, int);
DECLARE_FAKE_VOID_FUNC(mock_cap_commander_microphone_mute_changed_cb, struct bt_conn *, int);
DECLARE_FAKE_VOID_FUNC(mock_cap_commander_microphone_gain_changed_cb, struct bt_conn *, int);
DECLARE_FAKE_VOID_FUNC(mock_cap_commander_broadcast_reception_start_cb, struct bt_conn *, int);
#endif /* MOCKS_CAP_COMMANDER_H_ */

View file

@ -15,7 +15,8 @@
FAKE(mock_cap_commander_volume_mute_changed_cb) \
FAKE(mock_cap_commander_volume_offset_changed_cb) \
FAKE(mock_cap_commander_microphone_mute_changed_cb) \
FAKE(mock_cap_commander_microphone_gain_changed_cb)
FAKE(mock_cap_commander_microphone_gain_changed_cb) \
FAKE(mock_cap_commander_broadcast_reception_start_cb)
DEFINE_FAKE_VOID_FUNC(mock_cap_commander_discovery_complete_cb, struct bt_conn *, int,
const struct bt_csip_set_coordinator_set_member *,
@ -26,6 +27,7 @@ DEFINE_FAKE_VOID_FUNC(mock_cap_commander_volume_mute_changed_cb, struct bt_conn
DEFINE_FAKE_VOID_FUNC(mock_cap_commander_volume_offset_changed_cb, struct bt_conn *, int);
DEFINE_FAKE_VOID_FUNC(mock_cap_commander_microphone_mute_changed_cb, struct bt_conn *, int);
DEFINE_FAKE_VOID_FUNC(mock_cap_commander_microphone_gain_changed_cb, struct bt_conn *, int);
DEFINE_FAKE_VOID_FUNC(mock_cap_commander_broadcast_reception_start_cb, struct bt_conn *, int);
const struct bt_cap_commander_cb mock_cap_commander_cb = {
.discovery_complete = mock_cap_commander_discovery_complete_cb,
@ -42,6 +44,9 @@ const struct bt_cap_commander_cb mock_cap_commander_cb = {
.microphone_gain_changed = mock_cap_commander_microphone_gain_changed_cb,
#endif /* CONFIG_BT_MICP_MIC_CTLR_AICS */
#endif /* CONFIG_BT_MICP_MIC_CTLR */
#if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT)
.broadcast_reception_start = mock_cap_commander_broadcast_reception_start_cb,
#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */
};
void mock_cap_commander_init(void)