tests: Bluetooth: Add common helpers for bsim
This code can be found (kinda) duplicated all over `tests/bsim/bluetooth`. Put it in a common place. Refactoring the current tests will be done in a future commit. Signed-off-by: Jonathan Rico <jonathan.rico@nordicsemi.no>
This commit is contained in:
parent
936598ddf1
commit
389192a94d
19
tests/bsim/babblekit/CMakeLists.txt
Normal file
19
tests/bsim/babblekit/CMakeLists.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Helpers that can be used on bsim targets but don't have other
|
||||
# dependencies (e.g. on Bluetooth, etc).
|
||||
add_library(babblekit)
|
||||
|
||||
target_link_libraries(babblekit PUBLIC
|
||||
kernel
|
||||
zephyr_interface
|
||||
)
|
||||
|
||||
target_include_directories(babblekit PUBLIC
|
||||
include
|
||||
)
|
||||
|
||||
target_sources(babblekit PRIVATE
|
||||
src/sync.c
|
||||
)
|
55
tests/bsim/babblekit/include/babblekit/flags.h
Normal file
55
tests/bsim/babblekit/include/babblekit/flags.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* Provides a way to set/clear and block on binary flags.
|
||||
*
|
||||
* These flags are often used to wait until the test has gotten in a particular
|
||||
* state, e.g. a connection is established or a message has been successfully
|
||||
* sent.
|
||||
*
|
||||
* These macros can only be called from Zephyr threads. They can't be called
|
||||
* from e.g. a bs_tests callback.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/sys/atomic.h>
|
||||
|
||||
/* Declare a flag that has been defined in another file */
|
||||
#define DECLARE_FLAG(flag) extern atomic_t flag
|
||||
|
||||
/* Define a new binary flag.
|
||||
* Declare them static if defining flags with the same name in multiple files.
|
||||
*
|
||||
* @param flag Name of the flag
|
||||
*/
|
||||
#define DEFINE_FLAG(flag) atomic_t flag = (atomic_t) false
|
||||
|
||||
#define SET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) true)
|
||||
#define UNSET_FLAG(flag) (void)atomic_set(&flag, (atomic_t) false)
|
||||
|
||||
#define IS_FLAG_SET(flag) (atomic_get(&flag) != false)
|
||||
|
||||
/* Block until `flag` is equal to `val` */
|
||||
#define WAIT_FOR_VAL(var, val) \
|
||||
while (atomic_get(&var) != val) { \
|
||||
(void)k_sleep(K_MSEC(1)); \
|
||||
}
|
||||
|
||||
/* Block until `flag` is true */
|
||||
#define WAIT_FOR_FLAG(flag) \
|
||||
while (!(bool)atomic_get(&flag)) { \
|
||||
(void)k_sleep(K_MSEC(1)); \
|
||||
}
|
||||
|
||||
/* Block until `flag` is false */
|
||||
#define WAIT_FOR_FLAG_UNSET(flag) \
|
||||
while ((bool)atomic_get(&flag)) { \
|
||||
(void)k_sleep(K_MSEC(1)); \
|
||||
}
|
||||
|
||||
/* Block until `flag` is true and set it to false */
|
||||
#define TAKE_FLAG(flag) \
|
||||
while (!(bool)atomic_cas(&flag, true, false)) { \
|
||||
(void)k_sleep(K_MSEC(1)); \
|
||||
}
|
43
tests/bsim/babblekit/include/babblekit/sync.h
Normal file
43
tests/bsim/babblekit/include/babblekit/sync.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* This file provides a synchronization mechanism between devices, for the
|
||||
* simple use-case when there are only two devices in the simulation.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* @brief Initialize the sync library
|
||||
*
|
||||
* This initializes a simple synchronization library based on bsim backchannels.
|
||||
*
|
||||
* Calling `bk_sync_wait()` on device A will make it block until
|
||||
* `bk_sync_send()` is called on device B.
|
||||
*
|
||||
* @note Only works between two devices in a simulation, with IDs 0 and 1.
|
||||
*
|
||||
* @retval 0 Sync channel operational
|
||||
* @retval -1 Failed to open sync channel
|
||||
*
|
||||
*/
|
||||
int bk_sync_init(void);
|
||||
|
||||
/*
|
||||
* @brief Send a synchronization packet
|
||||
*
|
||||
* @note Only works between two devices in a simulation, with IDs 0 and 1.
|
||||
*
|
||||
*/
|
||||
void bk_sync_send(void);
|
||||
|
||||
/*
|
||||
* @brief Wait for a synchronization packet
|
||||
*
|
||||
* This blocks until the other device has called `bk_sync_send()`.
|
||||
*
|
||||
* @note Only works between two devices in a simulation, with IDs 0 and 1.
|
||||
*
|
||||
*/
|
||||
void bk_sync_wait(void);
|
112
tests/bsim/babblekit/include/babblekit/testcase.h
Normal file
112
tests/bsim/babblekit/include/babblekit/testcase.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "bs_tracing.h"
|
||||
#include "bs_types.h"
|
||||
#include "bstests.h"
|
||||
|
||||
extern enum bst_result_t bst_result;
|
||||
|
||||
/*
|
||||
* @brief Mark the test as in progress
|
||||
*
|
||||
* Call this at the start of the test entry point.
|
||||
*
|
||||
* @param ... format-string and arguments to print to console
|
||||
*
|
||||
*/
|
||||
#define TEST_START(msg, ...) \
|
||||
do { \
|
||||
bst_result = In_progress; \
|
||||
bs_trace_info_time(2, "Test start: " msg "\n", ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* @brief Fail the test and exit
|
||||
*
|
||||
* Printf-like function that also terminates the device with an error code.
|
||||
*
|
||||
* @param ... format-string and arguments to print to console
|
||||
*
|
||||
*/
|
||||
#define TEST_FAIL(msg, ...) \
|
||||
do { \
|
||||
bst_result = Failed; \
|
||||
bs_trace_error_time_line(msg "\n", ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* @brief Mark the currently-running test as "Passed"
|
||||
*
|
||||
* Mark the test as "passed". The execution continues after that point.
|
||||
*
|
||||
* @note Use this if you use backchannels (testlib/bsim/sync.h).
|
||||
*
|
||||
* After calling this, the executable will eventually return 0 when it exits.
|
||||
* Unless `TEST_FAIL` is called (e.g. in a callback).
|
||||
*
|
||||
* @param ... format-string and arguments to print to console
|
||||
*
|
||||
*/
|
||||
#define TEST_PASS(msg, ...) \
|
||||
do { \
|
||||
bst_result = Passed; \
|
||||
bs_trace_info_time(2, "Test end: " msg "\n", ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* @brief Mark test case as passed and end execution
|
||||
*
|
||||
* Mark the role / test-case as "Passed" and return 0.
|
||||
*
|
||||
* @note DO NOT use this if you use backchannels (testlib/bsim/sync.h).
|
||||
*
|
||||
* @note This macro only ends execution for the current executable, not all
|
||||
* executables in a simulation.
|
||||
*
|
||||
* @param ... format-string and arguments to print to console
|
||||
*
|
||||
*/
|
||||
#define TEST_PASS_AND_EXIT(msg, ...) \
|
||||
do { \
|
||||
bst_result = Passed; \
|
||||
bs_trace_info_time(2, "Test end: " msg "\n", ##__VA_ARGS__); \
|
||||
bs_trace_silent_exit(0); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* @brief Assert `expr` is true
|
||||
*
|
||||
* Assert that `expr` is true. If assertion is false, print a printf-like
|
||||
* message to the console and fail the test. I.e. return non-zero.
|
||||
*
|
||||
* @note This is different than `sys/__assert.h`.
|
||||
*
|
||||
* @param message String to print to console
|
||||
*
|
||||
*/
|
||||
#define TEST_ASSERT(expr, ...) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
TEST_FAIL(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* @brief Print a value. Lower-level than `printk` or `LOG_xx`.
|
||||
*
|
||||
* Print a message to console.
|
||||
*
|
||||
* This can be safely called at any time in the execution of the device.
|
||||
* Use it to print when the logging subsystem is not available, e.g. early
|
||||
* startup or shutdown.
|
||||
*
|
||||
* @param ... format-string and arguments to print to console
|
||||
*
|
||||
*/
|
||||
#define TEST_PRINT(msg, ...) \
|
||||
bs_trace_print(BS_TRACE_INFO, __FILE__, __LINE__, 0, BS_TRACE_AUTOTIME, 0, \
|
||||
msg "\n", ##__VA_ARGS__)
|
67
tests/bsim/babblekit/src/sync.c
Normal file
67
tests/bsim/babblekit/src/sync.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include "argparse.h"
|
||||
#include "bs_types.h"
|
||||
#include "bs_tracing.h"
|
||||
#include "time_machine.h"
|
||||
#include "bs_pc_backchannel.h"
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(sync, CONFIG_LOG_DEFAULT_LEVEL);
|
||||
|
||||
#define CHANNEL_ID 0
|
||||
#define MSG_SIZE 1
|
||||
|
||||
int bk_sync_init(void)
|
||||
{
|
||||
uint device_number = get_device_nbr();
|
||||
uint peer_number = device_number ^ 1;
|
||||
uint device_numbers[] = { peer_number };
|
||||
uint channel_numbers[] = { CHANNEL_ID };
|
||||
uint *ch;
|
||||
|
||||
ch = bs_open_back_channel(device_number, device_numbers, channel_numbers,
|
||||
ARRAY_SIZE(channel_numbers));
|
||||
if (!ch) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_DBG("Sync initialized");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bk_sync_send(void)
|
||||
{
|
||||
uint8_t sync_msg[MSG_SIZE] = { get_device_nbr() };
|
||||
|
||||
LOG_DBG("Sending sync");
|
||||
bs_bc_send_msg(CHANNEL_ID, sync_msg, ARRAY_SIZE(sync_msg));
|
||||
}
|
||||
|
||||
void bk_sync_wait(void)
|
||||
{
|
||||
uint8_t sync_msg[MSG_SIZE];
|
||||
|
||||
LOG_DBG("Waiting for sync");
|
||||
|
||||
while (true) {
|
||||
if (bs_bc_is_msg_received(CHANNEL_ID) > 0) {
|
||||
bs_bc_receive_msg(CHANNEL_ID, sync_msg, ARRAY_SIZE(sync_msg));
|
||||
if (sync_msg[0] != get_device_nbr()) {
|
||||
/* Received a message from another device, exit */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
k_sleep(K_MSEC(1));
|
||||
}
|
||||
|
||||
LOG_DBG("Sync received");
|
||||
}
|
Loading…
Reference in a new issue