Skip to content

Commit

Permalink
tests: Bluetooth: CAP Commander Change Volume Offset unittests
Browse files Browse the repository at this point in the history
Adds unittests for the CAP COmmander Change Volume Offset
procedure.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
  • Loading branch information
Thalley authored and nashif committed Feb 1, 2024
1 parent 8459560 commit e0f3524
Show file tree
Hide file tree
Showing 10 changed files with 393 additions and 3 deletions.
2 changes: 2 additions & 0 deletions include/zephyr/bluetooth/audio/vocs.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <stdint.h>
#include <stdbool.h>

#include <zephyr/bluetooth/conn.h>

#ifdef __cplusplus
extern "C" {
#endif
Expand Down
2 changes: 2 additions & 0 deletions tests/bluetooth/audio/cap_commander/include/cap_mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ void mock_bt_csip_init(void);
void mock_bt_csip_cleanup(void);
void mock_bt_vcp_init(void);
void mock_bt_vcp_cleanup(void);
void mock_bt_vocs_init(void);
void mock_bt_vocs_cleanup(void);
2 changes: 2 additions & 0 deletions tests/bluetooth/audio/cap_commander/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ CONFIG_BT_AUDIO=y

# Requirements for CAP commander
CONFIG_BT_VCP_VOL_CTLR=y
CONFIG_BT_VOCS_CLIENT_MAX_INSTANCE_COUNT=1
CONFIG_BT_VCP_VOL_CTLR_MAX_VOCS_INST=1
CONFIG_BT_CSIP_SET_COORDINATOR=y

CONFIG_BT_CAP_COMMANDER=y
Expand Down
261 changes: 261 additions & 0 deletions tests/bluetooth/audio/cap_commander/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ static void mock_init_rule_before(const struct ztest_unit_test *test, void *fixt
mock_cap_commander_init();
mock_bt_csip_init();
mock_bt_vcp_init();
mock_bt_vocs_init();
}

static void mock_destroy_rule_after(const struct ztest_unit_test *test, void *fixture)
{
mock_cap_commander_cleanup();
mock_bt_csip_cleanup();
mock_bt_vcp_cleanup();
mock_bt_vocs_cleanup();
}

ZTEST_RULE(mock_rule, mock_init_rule_before, mock_destroy_rule_after);
Expand Down Expand Up @@ -393,3 +395,262 @@ ZTEST_F(cap_commander_test_suite, test_commander_change_volume_inval_param_inval
err = bt_cap_commander_change_volume(&param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
}

ZTEST_F(cap_commander_test_suite, test_commander_change_volume_offset)
{
struct bt_cap_commander_change_volume_offset_member_param
member_params[ARRAY_SIZE(fixture->conns)];
const struct bt_cap_commander_change_volume_offset_param param = {
.type = BT_CAP_SET_TYPE_AD_HOC,
.param = member_params,
.count = ARRAY_SIZE(member_params),
};
int err;

for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
member_params[i].member.member = &fixture->conns[i];
member_params[i].offset = 100 + 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++) {
struct bt_vcp_vol_ctlr *vol_ctlr; /* We don't care about this */

err = bt_cap_commander_discover(&fixture->conns[i]);
zassert_equal(0, err, "Unexpected return value %d", err);

err = bt_vcp_vol_ctlr_discover(&fixture->conns[i], &vol_ctlr);
zassert_equal(0, err, "Unexpected return value %d", err);
}

err = bt_cap_commander_change_volume_offset(&param);
zassert_equal(0, err, "Unexpected return value %d", err);

zexpect_call_count("bt_cap_commander_cb.volume_offset_changed", 1,
mock_cap_commander_volume_offset_changed_cb_fake.call_count);
}

ZTEST_F(cap_commander_test_suite, test_commander_change_volume_offset_double)
{
struct bt_cap_commander_change_volume_offset_member_param
member_params[ARRAY_SIZE(fixture->conns)];
const struct bt_cap_commander_change_volume_offset_param param = {
.type = BT_CAP_SET_TYPE_AD_HOC,
.param = member_params,
.count = ARRAY_SIZE(member_params),
};
int err;

for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
member_params[i].member.member = &fixture->conns[i];
member_params[i].offset = 100 + 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++) {
struct bt_vcp_vol_ctlr *vol_ctlr; /* We don't care about this */

err = bt_cap_commander_discover(&fixture->conns[i]);
zassert_equal(0, err, "Unexpected return value %d", err);

err = bt_vcp_vol_ctlr_discover(&fixture->conns[i], &vol_ctlr);
zassert_equal(0, err, "Unexpected return value %d", err);
}

err = bt_cap_commander_change_volume_offset(&param);
zassert_equal(0, err, "Unexpected return value %d", err);

zexpect_call_count("bt_cap_commander_cb.volume_offset_changed", 1,
mock_cap_commander_volume_offset_changed_cb_fake.call_count);

/* Verify that it still works as expected if we set the same value twice */
err = bt_cap_commander_change_volume_offset(&param);
zassert_equal(0, err, "Unexpected return value %d", err);

zexpect_call_count("bt_cap_commander_cb.volume_offset_changed", 2,
mock_cap_commander_volume_offset_changed_cb_fake.call_count);
}

ZTEST_F(cap_commander_test_suite, test_commander_change_volume_offset_inval_param_null)
{
int err;

err = bt_cap_commander_change_volume_offset(NULL);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
}

ZTEST_F(cap_commander_test_suite, test_commander_change_volume_offset_inval_param_null_param)
{
const struct bt_cap_commander_change_volume_offset_param param = {
.type = BT_CAP_SET_TYPE_AD_HOC,
.param = NULL,
.count = ARRAY_SIZE(fixture->conns),
};
int err;

err = bt_cap_commander_change_volume_offset(&param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
}

ZTEST_F(cap_commander_test_suite, test_commander_change_volume_offset_inval_param_null_member)
{
struct bt_cap_commander_change_volume_offset_member_param
member_params[ARRAY_SIZE(fixture->conns)];
const struct bt_cap_commander_change_volume_offset_param param = {
.type = BT_CAP_SET_TYPE_AD_HOC,
.param = member_params,
.count = ARRAY_SIZE(member_params),
};
int err;

for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
member_params[i].member.member = &fixture->conns[i];
member_params[i].offset = 100 + i;
}
member_params[ARRAY_SIZE(member_params) - 1].member.member = NULL;

err = bt_cap_commander_change_volume_offset(&param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
}

ZTEST_F(cap_commander_test_suite, test_commander_change_volume_offset_inval_missing_cas)
{
struct bt_cap_commander_change_volume_offset_member_param
member_params[ARRAY_SIZE(fixture->conns)];
const struct bt_cap_commander_change_volume_offset_param param = {
.type = BT_CAP_SET_TYPE_AD_HOC,
.param = member_params,
.count = ARRAY_SIZE(member_params),
};
int err;

for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
member_params[i].member.member = &fixture->conns[i];
member_params[i].offset = 100 + 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++) {
struct bt_vcp_vol_ctlr *vol_ctlr; /* We don't care about this */

err = bt_vcp_vol_ctlr_discover(&fixture->conns[i], &vol_ctlr);
zassert_equal(0, err, "Unexpected return value %d", err);
}

err = bt_cap_commander_change_volume_offset(&param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
}

ZTEST_F(cap_commander_test_suite, test_commander_change_volume_offset_inval_missing_vocs)
{
struct bt_cap_commander_change_volume_offset_member_param
member_params[ARRAY_SIZE(fixture->conns)];
const struct bt_cap_commander_change_volume_offset_param param = {
.type = BT_CAP_SET_TYPE_AD_HOC,
.param = member_params,
.count = ARRAY_SIZE(member_params),
};
int err;

for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
member_params[i].member.member = &fixture->conns[i];
member_params[i].offset = 100 + 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_change_volume_offset(&param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
}

ZTEST_F(cap_commander_test_suite, test_commander_change_volume_offset_inval_param_zero_count)
{
struct bt_cap_commander_change_volume_offset_member_param
member_params[ARRAY_SIZE(fixture->conns)];
const struct bt_cap_commander_change_volume_offset_param param = {
.type = BT_CAP_SET_TYPE_AD_HOC,
.param = member_params,
.count = 0U,
};
int err;

for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
member_params[i].member.member = &fixture->conns[i];
member_params[i].offset = 100 + i;
}

err = bt_cap_commander_change_volume_offset(&param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
}

ZTEST_F(cap_commander_test_suite, test_commander_change_volume_offset_inval_param_inval_count)
{
struct bt_cap_commander_change_volume_offset_member_param
member_params[ARRAY_SIZE(fixture->conns)];
const struct bt_cap_commander_change_volume_offset_param param = {
.type = BT_CAP_SET_TYPE_AD_HOC,
.param = member_params,
.count = CONFIG_BT_MAX_CONN + 1,
};
int err;

for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
member_params[i].member.member = &fixture->conns[i];
member_params[i].offset = 100 + i;
}

err = bt_cap_commander_change_volume_offset(&param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
}

ZTEST_F(cap_commander_test_suite, test_commander_change_volume_offset_inval_param_inval_offset_max)
{
struct bt_cap_commander_change_volume_offset_member_param
member_params[ARRAY_SIZE(fixture->conns)];
const struct bt_cap_commander_change_volume_offset_param param = {
.type = BT_CAP_SET_TYPE_AD_HOC,
.param = member_params,
.count = ARRAY_SIZE(member_params),
};
int err;

for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
member_params[i].member.member = &fixture->conns[i];
member_params[i].offset = BT_VOCS_MAX_OFFSET + 1;
}

err = bt_cap_commander_change_volume_offset(&param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
}

ZTEST_F(cap_commander_test_suite, test_commander_change_volume_offset_inval_param_inval_offset_min)
{
struct bt_cap_commander_change_volume_offset_member_param
member_params[ARRAY_SIZE(fixture->conns)];
const struct bt_cap_commander_change_volume_offset_param param = {
.type = BT_CAP_SET_TYPE_AD_HOC,
.param = member_params,
.count = ARRAY_SIZE(member_params),
};
int err;

for (size_t i = 0U; i < ARRAY_SIZE(member_params); i++) {
member_params[i].member.member = &fixture->conns[i];
member_params[i].offset = BT_VOCS_MIN_OFFSET - 1;
}

err = bt_cap_commander_change_volume_offset(&param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
}
1 change: 1 addition & 0 deletions tests/bluetooth/audio/cap_commander/uut/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ add_library(uut STATIC
${ZEPHYR_BASE}/subsys/net/buf_simple.c
csip.c
vcp.c
vocs.c
)

add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/audio/mocks mocks)
Expand Down
2 changes: 1 addition & 1 deletion tests/bluetooth/audio/cap_commander/uut/csip.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ int bt_csip_set_coordinator_discover(struct bt_conn *conn)

void mock_bt_csip_init(void)
{
csip_cb = NULL;
}

void mock_bt_csip_cleanup(void)
{
csip_cb = NULL;
}
42 changes: 41 additions & 1 deletion tests/bluetooth/audio/cap_commander/uut/vcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ static struct bt_vcp_vol_ctlr_cb *vcp_cb;

static struct bt_vcp_vol_ctlr {
struct bt_conn *conn;
struct bt_vocs *vocs[CONFIG_BT_VCP_VOL_CTLR_MAX_VOCS_INST];
struct bt_aics *aics[CONFIG_BT_VCP_VOL_CTLR_MAX_AICS_INST];
} vol_ctlrs[CONFIG_BT_MAX_CONN];

struct bt_vcp_vol_ctlr *bt_vcp_vol_ctlr_get_by_conn(const struct bt_conn *conn)
Expand Down Expand Up @@ -45,8 +47,17 @@ int bt_vcp_vol_ctlr_discover(struct bt_conn *conn, struct bt_vcp_vol_ctlr **vol_
{
for (size_t i = 0; i < ARRAY_SIZE(vol_ctlrs); i++) {
if (vol_ctlrs[i].conn == NULL) {
for (size_t j = 0U; j < ARRAY_SIZE(vol_ctlrs[i].vocs); j++) {
const int err = bt_vocs_discover(conn, vol_ctlrs[i].vocs[j], NULL);

if (err != 0) {
return err;
}
}

vol_ctlrs[i].conn = conn;
*vol_ctlr = &vol_ctlrs[i];

return 0;
}
}
Expand All @@ -58,14 +69,43 @@ int bt_vcp_vol_ctlr_cb_register(struct bt_vcp_vol_ctlr_cb *cb)
{
vcp_cb = cb;

if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR_VOCS)) {
for (size_t i = 0U; i < ARRAY_SIZE(vol_ctlrs); i++) {
for (size_t j = 0U; j < ARRAY_SIZE(vol_ctlrs[i].vocs); j++) {
bt_vocs_client_cb_register(vol_ctlrs[i].vocs[j], &cb->vocs_cb);
}
}
}

return 0;
}

int bt_vcp_vol_ctlr_included_get(struct bt_vcp_vol_ctlr *vol_ctlr, struct bt_vcp_included *included)
{
included->vocs_cnt = ARRAY_SIZE(vol_ctlr->vocs);
included->vocs = vol_ctlr->vocs;

included->aics_cnt = ARRAY_SIZE(vol_ctlr->aics);
included->aics = vol_ctlr->aics;

return 0;
}

void mock_bt_vcp_init(void)
{
memset(vol_ctlrs, 0, sizeof(vol_ctlrs));
if (IS_ENABLED(CONFIG_BT_VCP_VOL_CTLR_VOCS)) {
for (size_t i = 0U; i < ARRAY_SIZE(vol_ctlrs); i++) {
for (size_t j = 0U; j < ARRAY_SIZE(vol_ctlrs[i].vocs); j++) {
vol_ctlrs[i].vocs[j] = bt_vocs_client_free_instance_get();

__ASSERT(vol_ctlrs[i].vocs[j],
"Could not allocate VOCS client instance");
}
}
}
}

void mock_bt_vcp_cleanup(void)
{
memset(vol_ctlrs, 0, sizeof(vol_ctlrs));
}
Loading

0 comments on commit e0f3524

Please sign in to comment.