Skip to content

Commit

Permalink
tests: Bluetooth: add sleep in notify cb testcase
Browse files Browse the repository at this point in the history
Validates that nothing nefarious happens if the application decides to
wait an arbitrary amount of time in notification callbacks.

Also validates that a disconnection during said waiting works as
expected.

E.g. in #48505, the user was trying to send data synchronously over UART
_inside_ the notification callback. Then the device was disconnected
whilst still waiting.

This kind of pattern is not recommended, but the stack should still
function correctly, stalling the "BT RX" thread shouldn't result in
state corruption or resource leakage.

Signed-off-by: Jonathan Rico <jonathan.rico@nordicsemi.no>
  • Loading branch information
jori-nordic committed Oct 11, 2023
1 parent 8c6a3db commit 3776941
Show file tree
Hide file tree
Showing 12 changed files with 1,228 additions and 0 deletions.
2 changes: 2 additions & 0 deletions tests/bsim/bluetooth/host/compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ app=tests/bsim/bluetooth/host/l2cap/send_on_connect compile
app=tests/bsim/bluetooth/host/l2cap/send_on_connect conf_file=prj_ecred.conf compile

app=tests/bsim/bluetooth/host/misc/disable compile
app=tests/bsim/bluetooth/host/misc/disconnect/dut compile
app=tests/bsim/bluetooth/host/misc/disconnect/tester compile

app=tests/bsim/bluetooth/host/privacy/central compile
app=tests/bsim/bluetooth/host/privacy/peripheral compile
Expand Down
65 changes: 65 additions & 0 deletions tests/bsim/bluetooth/host/misc/disconnect/common/sync.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright (c) 2023 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 "bstests.h"
#include "bs_pc_backchannel.h"

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(sync, LOG_LEVEL_INF);

#define CHANNEL_ID 0
#define MSG_SIZE 1

int backchannel_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;
}

return 0;
}

void backchannel_sync_send(void)
{
uint8_t sync_msg[MSG_SIZE] = { get_device_nbr() };

LOG_INF("Sending sync");
bs_bc_send_msg(CHANNEL_ID, sync_msg, ARRAY_SIZE(sync_msg));
}

void backchannel_sync_wait(void)
{
uint8_t sync_msg[MSG_SIZE];

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_INF("Sync received");
}
9 changes: 9 additions & 0 deletions tests/bsim/bluetooth/host/misc/disconnect/common/sync.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

int backchannel_init(void);
void backchannel_sync_send(void);
void backchannel_sync_wait(void);
63 changes: 63 additions & 0 deletions tests/bsim/bluetooth/host/misc/disconnect/common/utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#include "bs_tracing.h"
#include "bs_types.h"
#include "bstests.h"

#define BS_SECONDS(dur_sec) ((bs_time_t)dur_sec * USEC_PER_SEC)
#define TEST_TIMEOUT_SIMULATED BS_SECONDS(10)

extern enum bst_result_t bst_result;

#define DECLARE_FLAG(flag) extern atomic_t 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 WAIT_FOR_EXPR(var, expr) \
while (atomic_get(&var) expr) { \
(void)k_sleep(K_MSEC(1)); \
}
#define WAIT_FOR_VAL(var, val) \
while (atomic_get(&var) != val) { \
(void)k_sleep(K_MSEC(1)); \
}
#define WAIT_FOR_FLAG(flag) \
while (!(bool)atomic_get(&flag)) { \
(void)k_sleep(K_MSEC(1)); \
}
#define WAIT_FOR_FLAG_UNSET(flag) \
while ((bool)atomic_get(&flag)) { \
(void)k_sleep(K_MSEC(1)); \
}
#define TAKE_FLAG(flag) \
while (!(bool)atomic_cas(&flag, true, false)) { \
(void)k_sleep(K_MSEC(1)); \
}

#define ASSERT(expr, ...) \
do { \
if (!(expr)) { \
FAIL(__VA_ARGS__); \
} \
} while (0)

#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)

#define HVX_HANDLE 0x0012
#define INDICATION_PAYLOAD "indication"
#define NOTIFICATION_PAYLOAD "notification"
17 changes: 17 additions & 0 deletions tests/bsim/bluetooth/host/misc/disconnect/dut/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(bsim_test_disconnect_dut)

target_sources(app PRIVATE
src/main.c
../common/sync.c
)

zephyr_include_directories(
../common/
${BSIM_COMPONENTS_PATH}/libUtilv1/src/
${BSIM_COMPONENTS_PATH}/libPhyComv1/src/
)
38 changes: 38 additions & 0 deletions tests/bsim/bluetooth/host/misc/disconnect/dut/prj.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
CONFIG_LOG=y
CONFIG_ASSERT=y

CONFIG_BT=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_DEVICE_NAME="Sequential"

CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_GATT_ENFORCE_SUBSCRIPTION=n

# Replace `Execute` with `gdb --args` in the shell script
# and get a nice backtrace on assert
CONFIG_ARCH_POSIX_TRAP_ON_FATAL=y

# Prepend logs with thread names
CONFIG_THREAD_NAME=y
CONFIG_LOG_THREAD_ID_PREFIX=y

# Enable those as needed
# CONFIG_BT_L2CAP_LOG_LEVEL_DBG=y
# CONFIG_BT_ATT_LOG_LEVEL_DBG=y
# CONFIG_BT_GATT_LOG_LEVEL_DBG=y

# Allow whole L2CAP PDUs to fit on-air
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_BUF_ACL_RX_SIZE=251
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
CONFIG_BT_DATA_LEN_UPDATE=y
CONFIG_BT_USER_DATA_LEN_UPDATE=y

# Disable auto-initiated procedures so they don't
# mess with the test's execution.
CONFIG_BT_AUTO_PHY_UPDATE=n
CONFIG_BT_AUTO_DATA_LEN_UPDATE=n
CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n

CONFIG_BT_MAX_CONN=1
Loading

0 comments on commit 3776941

Please sign in to comment.