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/