tests bsim: Add tests for unicast client/server samples
Add a test based on the unicase client/server samples
which runs them together and after waiting for a predefined
amount of time, checks how many audio packets has the
client received, and if over a threshold, passes the test.
Signed-off-by: Alberto Escolar Piedras <alberto.escolar.piedras@nordicsemi.no>
diff --git a/samples/bluetooth/unicast_audio_client/src/main.c b/samples/bluetooth/unicast_audio_client/src/main.c
index 1dc411f..3953bee 100644
--- a/samples/bluetooth/unicast_audio_client/src/main.c
+++ b/samples/bluetooth/unicast_audio_client/src/main.c
@@ -19,6 +19,8 @@
static void start_scan(void);
+uint64_t unicast_audio_recv_ctr; /* This value is exposed to test code */
+
static struct bt_bap_unicast_client_cb unicast_client_cbs;
static struct bt_conn *default_conn;
static struct k_work_delayable audio_send_work;
@@ -564,7 +566,9 @@
struct net_buf *buf)
{
if (info->flags & BT_ISO_FLAGS_VALID) {
- printk("Incoming audio on stream %p len %u\n", stream, buf->len);
+ unicast_audio_recv_ctr++;
+ printk("Incoming audio on stream %p len %u (%"PRIu64")\n", stream, buf->len,
+ unicast_audio_recv_ctr);
}
}
diff --git a/tests/bsim/bluetooth/audio_samples/compile.sh b/tests/bsim/bluetooth/audio_samples/compile.sh
new file mode 100755
index 0000000..e41f4f9
--- /dev/null
+++ b/tests/bsim/bluetooth/audio_samples/compile.sh
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+# Copyright 2023 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+# Compile all the applications needed by the bsim tests in these subfolders
+
+#set -x #uncomment this line for debugging
+set -ue
+
+: "${BSIM_COMPONENTS_PATH:?BSIM_COMPONENTS_PATH must be defined}"
+: "${ZEPHYR_BASE:?ZEPHYR_BASE must be set to point to the zephyr root\
+ directory}"
+
+WORK_DIR="${WORK_DIR:-${ZEPHYR_BASE}/bsim_out}"
+
+BOARD_ROOT="${BOARD_ROOT:-${ZEPHYR_BASE}}"
+
+mkdir -p ${WORK_DIR}
+
+source ${ZEPHYR_BASE}/tests/bsim/compile.source
+
+if [ "${BOARD}" == "nrf5340bsim_nrf5340_cpuapp" ]; then
+ app=samples/bluetooth/unicast_audio_server sysbuild=1 compile
+else
+ app=samples/bluetooth/unicast_audio_server conf_overlay=overlay-bt_ll_sw_split.conf \
+ exe_name=bs_${BOARD}_${app}_prj_conf sysbuild=1 compile
+fi
+
+if [ "${BOARD}" == "nrf5340bsim_nrf5340_cpuapp" ]; then
+ app=tests/bsim/bluetooth/audio_samples/unicast_audio_client sysbuild=1 compile
+else
+ app=tests/bsim/bluetooth/audio_samples/unicast_audio_client \
+ conf_overlay=${ZEPHYR_BASE}/samples/bluetooth/unicast_audio_client/overlay-bt_ll_sw_split.conf \
+ exe_name=bs_${BOARD}_${app}_prj_conf sysbuild=1 compile
+fi
+
+wait_for_background_jobs
diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/CMakeLists.txt b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/CMakeLists.txt
new file mode 100644
index 0000000..1afb502
--- /dev/null
+++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/CMakeLists.txt
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: Apache-2.0
+
+cmake_minimum_required(VERSION 3.20.0)
+
+find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
+project(unicast_audio_client_self_tets)
+
+set(unicast_client_path ${ZEPHYR_BASE}/samples/bluetooth/unicast_audio_client)
+
+target_sources(app PRIVATE
+ ${unicast_client_path}/src/main.c
+)
+
+target_sources(app PRIVATE
+ src/unicast_client_sample_test.c
+ src/test_main.c
+)
+
+zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth)
+
+zephyr_include_directories(
+ ${BSIM_COMPONENTS_PATH}/libUtilv1/src/
+ ${BSIM_COMPONENTS_PATH}/libPhyComv1/src/
+ )
diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/Kconfig.sysbuild b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/Kconfig.sysbuild
new file mode 100644
index 0000000..4e7f669
--- /dev/null
+++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/Kconfig.sysbuild
@@ -0,0 +1,10 @@
+# Copyright (c) 2023 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+source "${ZEPHYR_BASE}/samples/bluetooth/unicast_audio_client/Kconfig.sysbuild"
+
+config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX
+ int
+ # Let's pass the test arguments to the application MCU test
+ # otherwise by default they would have gone to the net core.
+ default 0 if $(BOARD) = "nrf5340bsim_nrf5340_cpuapp"
diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf52_bsim.conf b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf52_bsim.conf
new file mode 100644
index 0000000..664b1b5
--- /dev/null
+++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf52_bsim.conf
@@ -0,0 +1,7 @@
+# This file content is just a copy of the equivalent one in the unicast client sample
+
+# For LC3 the following configs are needed
+CONFIG_FPU=y
+CONFIG_LIBLC3=y
+# LC3 lib requires floating point support in the c-lib.
+CONFIG_REQUIRES_FULL_LIBC=y
diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpuapp.conf b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpuapp.conf
new file mode 100644
index 0000000..b716697
--- /dev/null
+++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpuapp.conf
@@ -0,0 +1,14 @@
+# This file content is just a copy of the equivalent one in the unicast client sample
+
+# For LC3 the following configs are needed
+CONFIG_FPU=y
+CONFIG_LIBLC3=y
+# LC3 lib requires floating point support in the c-lib.
+CONFIG_REQUIRES_FULL_LIBC=y
+
+CONFIG_BT_BUF_EVT_RX_SIZE=255
+CONFIG_BT_BUF_ACL_RX_SIZE=255
+CONFIG_BT_BUF_ACL_TX_SIZE=251
+CONFIG_BT_BUF_CMD_TX_SIZE=255
+
+CONFIG_BT_TINYCRYPT_ECC=y
diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpunet.conf b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpunet.conf
new file mode 100644
index 0000000..664b1b5
--- /dev/null
+++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpunet.conf
@@ -0,0 +1,7 @@
+# This file content is just a copy of the equivalent one in the unicast client sample
+
+# For LC3 the following configs are needed
+CONFIG_FPU=y
+CONFIG_LIBLC3=y
+# LC3 lib requires floating point support in the c-lib.
+CONFIG_REQUIRES_FULL_LIBC=y
diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/prj.conf b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/prj.conf
new file mode 100644
index 0000000..c7385ae
--- /dev/null
+++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/prj.conf
@@ -0,0 +1,16 @@
+# This file content is just a copy of the unicast client sample prj.conf
+
+CONFIG_BT=y
+CONFIG_LOG=y
+CONFIG_BT_CENTRAL=y
+CONFIG_BT_AUDIO=y
+CONFIG_BT_BAP_UNICAST_CLIENT=y
+CONFIG_BT_ISO_TX_BUF_COUNT=4
+# Support an ISO channel per ASE
+CONFIG_BT_ISO_MAX_CHAN=4
+CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT=4
+CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT=2
+CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT=2
+CONFIG_BT_KEYS_OVERWRITE_OLDEST=y
+
+CONFIG_BT_EXT_ADV=y
diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/src/test_main.c b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/src/test_main.c
new file mode 100644
index 0000000..dbba210
--- /dev/null
+++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/src/test_main.c
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2023 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "bstests.h"
+
+extern struct bst_test_list *test_unicast_client_sample_install(struct bst_test_list *tests);
+
+bst_test_install_t test_installers[] = {
+ test_unicast_client_sample_install,
+ NULL
+};
diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/src/unicast_client_sample_test.c b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/src/unicast_client_sample_test.c
new file mode 100644
index 0000000..729e426
--- /dev/null
+++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/src/unicast_client_sample_test.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2023 Nordic Semiconductor ASA
+ * Copyright (c) 2017-2019 Oticon A/S
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "bs_types.h"
+#include "bs_tracing.h"
+#include "bs_utils.h"
+#include "time_machine.h"
+#include "bstests.h"
+
+#define WAIT_TIME 10 /* Seconds */
+
+#define PASS_THRESHOLD 100 /* Audio packets */
+
+extern enum bst_result_t bst_result;
+
+#define FAIL(...) \
+ do { \
+ bst_result = Failed; \
+ bs_trace_error_time_line(__VA_ARGS__); \
+ } while (0)
+
+#define PASS(...) \
+ do { \
+ bst_result = Passed; \
+ bs_trace_info_time(1, __VA_ARGS__); \
+ } while (0)
+
+static void test_unicast_client_sample_init(void)
+{
+ /* We set an absolute deadline in 30 seconds */
+ bst_ticker_set_next_tick_absolute(WAIT_TIME*1e6);
+ bst_result = In_progress;
+}
+
+static void test_unicast_client_sample_tick(bs_time_t HW_device_time)
+{
+ /*
+ * If in WAIT_TIME seconds we did not get enough packets through
+ * we consider the test failed
+ */
+
+ extern uint64_t unicast_audio_recv_ctr;
+
+ bs_trace_info_time(2, "%"PRIu64" packets received, expected >= %i\n",
+ unicast_audio_recv_ctr, PASS_THRESHOLD);
+
+ if (unicast_audio_recv_ctr >= PASS_THRESHOLD) {
+ PASS("unicast_client PASSED\n");
+ bs_trace_exit("Done, disconnecting from simulation\n");
+ } else {
+ FAIL("unicast_client FAILED (Did not pass after %i seconds)\n",
+ WAIT_TIME);
+ }
+}
+
+static const struct bst_test_instance test_sample[] = {
+ {
+ .test_id = "unicast_client",
+ .test_descr = "Test based on the unicast client sample. "
+ "It expects to be connected to a compatible unicast server, "
+ "waits for " STR(WAIT_TIME) " seconds, and checks how "
+ "many audio packets have been received correctly",
+ .test_post_init_f = test_unicast_client_sample_init,
+ .test_tick_f = test_unicast_client_sample_tick,
+ },
+ BSTEST_END_MARKER
+};
+
+struct bst_test_list *test_unicast_client_sample_install(struct bst_test_list *tests)
+{
+ tests = bst_add_tests(tests, test_sample);
+ return tests;
+}
diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/sysbuild.cmake b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/sysbuild.cmake
new file mode 100644
index 0000000..9686cde
--- /dev/null
+++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/sysbuild.cmake
@@ -0,0 +1,13 @@
+# Copyright (c) 2023 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+include(${ZEPHYR_BASE}/samples/bluetooth/unicast_audio_client/sysbuild.cmake)
+
+if (NOT ("${SB_CONFIG_NATIVE_SIMULATOR_PRIMARY_MCU_INDEX}" STREQUAL ""))
+ set_property(TARGET ${NET_APP} APPEND_STRING PROPERTY CONFIG
+ "CONFIG_NATIVE_SIMULATOR_PRIMARY_MCU_INDEX=${SB_CONFIG_NATIVE_SIMULATOR_PRIMARY_MCU_INDEX}\n"
+ )
+ set_property(TARGET ${DEFAULT_IMAGE} APPEND_STRING PROPERTY CONFIG
+ "CONFIG_NATIVE_SIMULATOR_PRIMARY_MCU_INDEX=${SB_CONFIG_NATIVE_SIMULATOR_PRIMARY_MCU_INDEX}\n"
+ )
+endif()
diff --git a/tests/bsim/bluetooth/audio_samples/unicast_audio_client/tests_scripts/unicast_client.sh b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/tests_scripts/unicast_client.sh
new file mode 100755
index 0000000..cc92cda
--- /dev/null
+++ b/tests/bsim/bluetooth/audio_samples/unicast_audio_client/tests_scripts/unicast_client.sh
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+# Copyright 2023 Nordic Semiconductor ASA
+# SPDX-License-Identifier: Apache-2.0
+
+# Simple selfchecking test for the unicast client/server samples,
+# It relies on the bs_tests hooks to register a test timer callback, which after a deadline
+# will check how many audio packets the unicast client has received, and if over a threshold
+# it considers the test passed
+
+simulation_id="unicast_samples_test"
+verbosity_level=2
+
+source ${ZEPHYR_BASE}/tests/bsim/sh_common.source
+
+EXECUTE_TIMEOUT=100
+
+cd ${BSIM_OUT_PATH}/bin
+
+Execute ./bs_${BOARD}_samples_bluetooth_unicast_audio_server_prj_conf \
+ -v=${verbosity_level} -s=${simulation_id} -d=0 -RealEncryption=1
+
+Execute ./bs_${BOARD}_tests_bsim_bluetooth_audio_samples_unicast_audio_client_prj_conf \
+ -v=${verbosity_level} -s=${simulation_id} -d=1 -RealEncryption=1 \
+ -testid=unicast_client
+
+Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \
+ -D=2 -sim_length=20e6 $@
+
+wait_for_background_jobs #Wait for all programs in background and return != 0 if any fails
diff --git a/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh b/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh
index ddb8349..4f17554 100755
--- a/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh
+++ b/tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh
@@ -22,4 +22,6 @@
app=tests/bsim/bluetooth/ll/conn conf_file=prj_split_privacy.conf sysbuild=1 compile
app=tests/bsim/bluetooth/ll/bis sysbuild=1 compile
+run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/audio_samples/compile.sh
+
wait_for_background_jobs
diff --git a/tests/bsim/bluetooth/compile.sh b/tests/bsim/bluetooth/compile.sh
index 016437a..b6b709f 100755
--- a/tests/bsim/bluetooth/compile.sh
+++ b/tests/bsim/bluetooth/compile.sh
@@ -24,6 +24,7 @@
# On the other hand the audio compile script, only builds one image. So we parallelize it with
# the rest to save a couple of seconds.
run_in_background ${ZEPHYR_BASE}/tests/bsim/bluetooth/audio/compile.sh
+${ZEPHYR_BASE}/tests/bsim/bluetooth/audio_samples/compile.sh
${ZEPHYR_BASE}/tests/bsim/bluetooth/host/compile.sh
${ZEPHYR_BASE}/tests/bsim/bluetooth/ll/compile.sh
${ZEPHYR_BASE}/tests/bsim/bluetooth/mesh/compile.sh
diff --git a/tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpuapp.txt b/tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpuapp.txt
index 147b551..27a1fc4 100644
--- a/tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpuapp.txt
+++ b/tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpuapp.txt
@@ -2,3 +2,4 @@
# This file is used in CI to select which tests are run
tests/bsim/bluetooth/ll/conn/tests_scripts/basic_conn_encrypted_split_privacy.sh
tests/bsim/bluetooth/ll/bis/tests_scripts/broadcast_iso.sh
+tests/bsim/bluetooth/audio_samples/