From 94deb4c10abf700c68e2b7ca02994a8cbbc1c512 Mon Sep 17 00:00:00 2001 From: Andries Kruithof Date: Thu, 8 Feb 2024 14:31:17 +0100 Subject: [PATCH] Bluetooth: audio: test: Unit tests for the broadcast reception start command Implement unit tests for the broadcast reception start, both with proper and with improper parameters. Add framework for the broadcast reception stop command Signed-off-by: Andries Kruithof --- .../audio/cap_commander/CMakeLists.txt | 6 +- .../src/test_broadcast_reception.c | 311 ++++++++++++++++++ .../audio/cap_commander/uut/CMakeLists.txt | 1 + .../audio/mocks/include/cap_commander.h | 1 + .../bluetooth/audio/mocks/src/cap_commander.c | 4 + 5 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 tests/bluetooth/audio/cap_commander/src/test_broadcast_reception.c diff --git a/tests/bluetooth/audio/cap_commander/CMakeLists.txt b/tests/bluetooth/audio/cap_commander/CMakeLists.txt index 2dde0298e4bcb03..a3a71abb585799b 100644 --- a/tests/bluetooth/audio/cap_commander/CMakeLists.txt +++ b/tests/bluetooth/audio/cap_commander/CMakeLists.txt @@ -13,8 +13,10 @@ 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_volume.c + src/test_broadcast_reception.c ) diff --git a/tests/bluetooth/audio/cap_commander/src/test_broadcast_reception.c b/tests/bluetooth/audio/cap_commander/src/test_broadcast_reception.c new file mode 100644 index 000000000000000..8b1a2b304049e83 --- /dev/null +++ b/tests/bluetooth/audio/cap_commander/src/test_broadcast_reception.c @@ -0,0 +1,311 @@ +/* test_change_volume.c - unit test for volume settings */ + +/* + * Copyright (c) 2023-2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +#include "bluetooth.h" +#include "cap_commander.h" +#include "conn.h" +#include "expects_util.h" +#include "cap_mocks.h" +#include "test_common.h" + +#define FFF_GLOBALS + + +#define ADDRESS 0x123456 +#define SID 0x55 +#define ADV_INTERVAL 10 +#define BROADCAST_ID 0x80DEBEEF +#define NR_SUBGROUPS 1 + +struct cap_commander_test_broadcast_reception_fixture { + struct bt_conn conns[CONFIG_BT_MAX_CONN]; +}; + +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]); + } +} + +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 struct bt_bap_bass_subgroup start_subgroups[NR_SUBGROUPS]; +static struct bt_cap_commander_broadcast_reception_start_member_param + start_member_params[CONFIG_BT_MAX_CONN]; +static struct bt_cap_commander_broadcast_reception_start_param start_param; + +static void init_start_param(void *f) +{ + struct cap_commander_test_broadcast_reception_fixture *fixture = f; + + start_param.type = BT_CAP_SET_TYPE_AD_HOC; + start_param.param = start_member_params; + + start_param.count = ARRAY_SIZE(start_member_params); + + 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); + } + + for (size_t i = 0U; i < ARRAY_SIZE(start_member_params); i++) { + start_member_params[i].member.member = &fixture->conns[i]; + bt_addr_le_copy(&start_member_params[i].addr, BT_ADDR_LE_ANY); + start_member_params[i].adv_sid = SID; + start_member_params[i].pa_interval = ADV_INTERVAL; + start_member_params[i].broadcast_id = BROADCAST_ID; + start_member_params[i].subgroups = &start_subgroups[0]; + start_member_params[i].num_subgroups = NR_SUBGROUPS; + } + + for (size_t i = 0; i < ARRAY_SIZE(start_subgroups); i++) { + start_subgroups[i].bis_sync = 0; + start_subgroups[i].metadata_len = 0; + } +} + + +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; + + init_start_param(fixture); + + err = bt_cap_commander_register_cb(&mock_cap_commander_cb); + zassert_equal(0, err, "Unexpected return value %d", err); + + 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(start_member_params); i++) { + start_member_params[i].member.member = &fixture->conns[i]; + } + + err = bt_cap_commander_broadcast_reception_start(&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; + + init_start_param(fixture); + + err = bt_cap_commander_register_cb(&mock_cap_commander_cb); + zassert_equal(0, err, "Unexpected return value %d", err); + + 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(start_member_params); i++) { + start_member_params[i].member.member = &fixture->conns[i]; + } + + + err = bt_cap_commander_broadcast_reception_start(&start_param); + zassert_equal(0, err, "Unexpected return value %d", err); + + err = bt_cap_commander_broadcast_reception_start(&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_register_cb(&mock_cap_commander_cb); + zassert_equal(0, err, "Unexpected return value %d", err); + + err = bt_cap_commander_broadcast_reception_start(NULL); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); +} + +ZTEST_F(cap_commander_test_broadcast_reception, + test_commander_reception_start_inval_param_null_param) +{ + + int err; + + err = bt_cap_commander_register_cb(&mock_cap_commander_cb); + zassert_equal(0, err, "Unexpected return value %d", err); + + start_param.type = BT_CAP_SET_TYPE_AD_HOC; + start_param.param = NULL; + start_param.count = ARRAY_SIZE(fixture->conns); + + err = bt_cap_commander_broadcast_reception_start(&start_param); + zassert_equal(-EINVAL, err, "Unexpected return value %d", err); +} + + +ZTEST_F(cap_commander_test_broadcast_reception, + test_commander_reception_start_inval_param_zero_count) +{ + int err; + + init_start_param(fixture); + + err = bt_cap_commander_register_cb(&mock_cap_commander_cb); + zassert_equal(0, err, "Unexpected return value %d", err); + + start_param.count = 0; + + 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); + } + + err = bt_cap_commander_broadcast_reception_start(&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_inval_count) +{ + int err; + + init_start_param(fixture); + + err = bt_cap_commander_register_cb(&mock_cap_commander_cb); + zassert_equal(0, err, "Unexpected return value %d", err); + + start_param.count = CONFIG_BT_MAX_CONN + 1; + + 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); + } + + err = bt_cap_commander_broadcast_reception_start(&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); +} + +#ifdef NOT_DEFINEDYET +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_stop) +{ + union bt_cap_set_member members[ARRAY_SIZE(fixture->conns)]; + const struct bt_cap_commander_broadcast_reception_stop_param param = { + .type = BT_CAP_SET_TYPE_AD_HOC, + .members = members, + .count = ARRAY_SIZE(member_params), + }; + int err; + + for (size_t i = 0; i < ARRAY_SIZE(members); i++) { + members[i].member = &fixture->conns[i]; + } + + err = bt_cap_commander_register_cb(&mock_cap_commander_cb); + zassert_equal(0, err, "Unexpected return value %d", err); + + 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); + } + + err = bt_cap_commander_broadcast_reception_stop(¶m); + zassert_equal(0, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_stop", 1, + mock_cap_commander_broadcast_reception_stop_fake.call_count); +} + +ZTEST_F(cap_commander_test_broadcast_reception, test_commander_reception_stop_double) +{ + union bt_cap_set_member members[ARRAY_SIZE(fixture->conns)]; + const struct bt_cap_commander_broadcast_reception_stop_param param = { + .type = BT_CAP_SET_TYPE_AD_HOC, + .members = members, + .count = ARRAY_SIZE(member_params), + }; + int err; + + for (size_t i = 0; i < ARRAY_SIZE(members); i++) { + members[i].member = &fixture->conns[i]; + } + + err = bt_cap_commander_register_cb(&mock_cap_commander_cb); + zassert_equal(0, err, "Unexpected return value %d", err); + + 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); + } + + err = bt_cap_commander_broadcast_reception_stop(¶m); + zassert_equal(0, err, "Unexpected return value %d", err); + + err = bt_cap_commander_broadcast_reception_stop(¶m); + zassert_equal(0, err, "Unexpected return value %d", err); + + zexpect_call_count("bt_cap_commander_cb.broadcast_reception_stop", 2, + mock_cap_commander_broadcast_reception_stop_fake.call_count); +} + +#endif + + diff --git a/tests/bluetooth/audio/cap_commander/uut/CMakeLists.txt b/tests/bluetooth/audio/cap_commander/uut/CMakeLists.txt index 1213c9573673a0d..a3ba33e37622de8 100644 --- a/tests/bluetooth/audio/cap_commander/uut/CMakeLists.txt +++ b/tests/bluetooth/audio/cap_commander/uut/CMakeLists.txt @@ -15,6 +15,7 @@ add_library(uut STATIC csip.c vcp.c vocs.c + bap_broadcast_assistant.c ) add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/audio/mocks mocks) diff --git a/tests/bluetooth/audio/mocks/include/cap_commander.h b/tests/bluetooth/audio/mocks/include/cap_commander.h index 8ccd2caf7ba5bf6..127835a41057766 100644 --- a/tests/bluetooth/audio/mocks/include/cap_commander.h +++ b/tests/bluetooth/audio/mocks/include/cap_commander.h @@ -20,5 +20,6 @@ DECLARE_FAKE_VOID_FUNC(mock_cap_commander_discovery_complete_cb, struct bt_conn DECLARE_FAKE_VOID_FUNC(mock_cap_commander_volume_changed_cb, struct bt_conn *, int); DECLARE_FAKE_VOID_FUNC(mock_cap_commander_volume_mute_changed_cb, struct bt_conn *, int); DECLARE_FAKE_VOID_FUNC(mock_cap_commander_volume_offset_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_ */ diff --git a/tests/bluetooth/audio/mocks/src/cap_commander.c b/tests/bluetooth/audio/mocks/src/cap_commander.c index abf9245273cb5bd..92561b59d4224fc 100644 --- a/tests/bluetooth/audio/mocks/src/cap_commander.c +++ b/tests/bluetooth/audio/mocks/src/cap_commander.c @@ -14,6 +14,7 @@ FAKE(mock_cap_commander_volume_changed_cb) \ FAKE(mock_cap_commander_volume_mute_changed_cb) \ FAKE(mock_cap_commander_volume_offset_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_csis_inst *); @@ -21,6 +22,8 @@ DEFINE_FAKE_VOID_FUNC(mock_cap_commander_discovery_complete_cb, struct bt_conn * DEFINE_FAKE_VOID_FUNC(mock_cap_commander_volume_changed_cb, struct bt_conn *, int); DEFINE_FAKE_VOID_FUNC(mock_cap_commander_volume_mute_changed_cb, struct bt_conn *, int); DEFINE_FAKE_VOID_FUNC(mock_cap_commander_volume_offset_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, @@ -31,6 +34,7 @@ const struct bt_cap_commander_cb mock_cap_commander_cb = { .volume_offset_changed = mock_cap_commander_volume_offset_changed_cb, #endif /* CONFIG_BT_VCP_VOL_CTLR */ #endif /* CONFIG_BT_VCP_VOL_CTLR */ + .broadcast_reception_start = mock_cap_commander_broadcast_reception_start_cb, }; void mock_cap_commander_init(void)