Skip to content

Commit 11a0ed4

Browse files
committed
tests: bsim: bluetooth: host: Add tests for bonding with the same id
This commit adds the following tests: - a test that checks undirected advertisements - a test that checks directed advertisements - a test that checks undirected advertisement with the Filter Accept List - a test that checks unpairing - a test that checks start of multiple advertisements in parallel Signed-off-by: Pavel Vasilyev <[email protected]>
1 parent 6a45f9d commit 11a0ed4

File tree

21 files changed

+1929
-0
lines changed

21 files changed

+1929
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(bsim_test_multi_id_bond_keep)
7+
8+
add_subdirectory(${ZEPHYR_BASE}/tests/bsim/babblekit babblekit)
9+
target_link_libraries(app PRIVATE babblekit)
10+
11+
target_sources(app PRIVATE
12+
src/bs_bt_utils.c
13+
src/central.c
14+
src/main.c
15+
src/peripheral.c
16+
)
17+
18+
zephyr_include_directories(
19+
${BSIM_COMPONENTS_PATH}/libUtilv1/src/
20+
${BSIM_COMPONENTS_PATH}/libPhyComv1/src/
21+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CONFIG_BT=y
2+
3+
CONFIG_BT_SMP=y
4+
5+
CONFIG_ASSERT=y
6+
CONFIG_BT_TESTING=y
7+
CONFIG_LOG=y
8+
9+
CONFIG_BT_ID_MAX=4
10+
CONFIG_BT_MAX_PAIRED=3
11+
CONFIG_BT_MAX_CONN=1
12+
13+
CONFIG_BT_PRIVACY=y
14+
CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS=y
15+
16+
CONFIG_BT_FILTER_ACCEPT_LIST=y
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "host/hci_core.h"
8+
9+
#include "bs_bt_utils.h"
10+
11+
BUILD_ASSERT(CONFIG_BT_MAX_PAIRED >= 3, "Test needs to pair with 3 devices.");
12+
BUILD_ASSERT(CONFIG_BT_ID_MAX >= 4, "Need 4 IDs: 1 default + 3 for the test.");
13+
14+
DEFINE_FLAG(flag_is_connected);
15+
16+
struct bt_conn *g_conn;
17+
18+
const char *addr_to_str(const bt_addr_le_t *addr)
19+
{
20+
static char str[BT_ADDR_LE_STR_LEN];
21+
22+
bt_addr_le_to_str(addr, str, sizeof(str));
23+
24+
return str;
25+
}
26+
27+
static void disconnected(struct bt_conn *conn, uint8_t reason)
28+
{
29+
const bt_addr_le_t *dst;
30+
char addr_str[BT_ADDR_LE_STR_LEN];
31+
32+
dst = bt_conn_get_dst(conn);
33+
bt_addr_le_to_str(dst, addr_str, sizeof(addr_str));
34+
printk("Disconnected from %p (addr %s) (reason %d)\n", conn, addr_str, reason);
35+
36+
UNSET_FLAG(flag_is_connected);
37+
}
38+
39+
BUILD_ASSERT(CONFIG_BT_MAX_CONN == 1, "This test assumes a single link.");
40+
static void connected(struct bt_conn *conn, uint8_t err)
41+
{
42+
const bt_addr_le_t *dst;
43+
char addr_str[BT_ADDR_LE_STR_LEN];
44+
45+
TEST_ASSERT((!g_conn || (conn == g_conn)), "Unexpected new connection.");
46+
47+
UNSET_FLAG(security_changed_flag);
48+
49+
dst = bt_conn_get_dst(conn);
50+
bt_addr_le_to_str(dst, addr_str, sizeof(addr_str));
51+
printk("Connected to %p, err %d dst %s\n", conn, err, addr_str);
52+
53+
if (!g_conn) {
54+
g_conn = bt_conn_ref(conn);
55+
}
56+
57+
if (err != 0) {
58+
clear_g_conn();
59+
return;
60+
}
61+
62+
printk("Set flag_is_connected\n");
63+
SET_FLAG(flag_is_connected);
64+
}
65+
66+
DEFINE_FLAG(security_changed_flag);
67+
68+
static void security_changed(struct bt_conn *conn, bt_security_t level,
69+
enum bt_security_err err)
70+
{
71+
const bt_addr_le_t *dst;
72+
char addr_str[BT_ADDR_LE_STR_LEN];
73+
74+
dst = bt_conn_get_dst(conn);
75+
bt_addr_le_to_str(dst, addr_str, sizeof(addr_str));
76+
printk("Security changed for %p (addr %s), level %d, err %d\n", conn, addr_str, level, err);
77+
78+
if (!err && level == BT_SECURITY_L2) {
79+
SET_FLAG(security_changed_flag);
80+
}
81+
}
82+
83+
BT_CONN_CB_DEFINE(conn_callbacks) = {
84+
.connected = connected,
85+
.disconnected = disconnected,
86+
.security_changed = security_changed,
87+
};
88+
89+
void clear_g_conn(void)
90+
{
91+
struct bt_conn *conn;
92+
93+
conn = g_conn;
94+
g_conn = NULL;
95+
TEST_ASSERT(conn, "Test error: No g_conn!");
96+
bt_conn_unref(conn);
97+
}
98+
99+
/* The pairing complete flags is raised by events and lowered by test code. */
100+
DEFINE_FLAG(flag_pairing_complete);
101+
102+
static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
103+
{
104+
printk("Pairing failed with %p (reason %d)\n", conn, reason);
105+
106+
/* Pairing should never fail in this test. */
107+
TEST_ASSERT(false, "Pairing failed with %p (reason %d)", conn, reason);
108+
}
109+
110+
static void pairing_complete(struct bt_conn *conn, bool bonded)
111+
{
112+
const bt_addr_le_t *dst;
113+
char addr_str[BT_ADDR_LE_STR_LEN];
114+
115+
dst = bt_conn_get_dst(conn);
116+
bt_addr_le_to_str(dst, addr_str, sizeof(addr_str));
117+
printk("Pairing complete with %p (bonded %d) dst %s\n", conn, bonded, addr_str);
118+
119+
SET_FLAG(flag_pairing_complete);
120+
}
121+
122+
static struct bt_conn_auth_info_cb bt_conn_auth_info_cb = {
123+
.pairing_failed = pairing_failed,
124+
.pairing_complete = pairing_complete,
125+
};
126+
127+
void bs_bt_utils_setup(void)
128+
{
129+
int err;
130+
131+
err = bt_enable(NULL);
132+
TEST_ASSERT(!err, "bt_enable failed.");
133+
err = bt_conn_auth_info_cb_register(&bt_conn_auth_info_cb);
134+
TEST_ASSERT(!err, "bt_conn_auth_info_cb_register failed.");
135+
}
136+
137+
#if defined(CONFIG_BT_CENTRAL)
138+
static enum bt_gap_adv_type scan_adv_type;
139+
140+
static void scan_connect_to_first_result__device_found(const bt_addr_le_t *addr, int8_t rssi,
141+
uint8_t type, struct net_buf_simple *ad)
142+
{
143+
char addr_str[BT_ADDR_LE_STR_LEN];
144+
int err;
145+
146+
if (g_conn != NULL) {
147+
printk("Already connected, ignoring advertisement.");
148+
return;
149+
}
150+
151+
/* We're only interested in connectable events */
152+
if (type != scan_adv_type) {
153+
TEST_FAIL("Unexpected advertisement type %d, expected %d", type, scan_adv_type);
154+
}
155+
156+
bt_addr_le_to_str(addr, addr_str, sizeof(addr_str));
157+
printk("Got scan result, connecting.. dst %s, RSSI %d\n", addr_str, rssi);
158+
159+
err = bt_le_scan_stop();
160+
TEST_ASSERT(!err, "Err bt_le_scan_stop %d", err);
161+
162+
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &g_conn);
163+
TEST_ASSERT(!err, "Err bt_conn_le_create %d", err);
164+
}
165+
166+
int scan_connect_to_first_result(bool directed, bool filter)
167+
{
168+
struct bt_le_scan_param param = BT_LE_SCAN_PARAM_INIT(BT_LE_SCAN_TYPE_PASSIVE,
169+
BT_LE_SCAN_OPT_FILTER_DUPLICATE,
170+
BT_GAP_SCAN_FAST_INTERVAL,
171+
BT_GAP_SCAN_FAST_WINDOW);
172+
173+
if (filter) {
174+
param.options = BT_LE_SCAN_OPT_FILTER_ACCEPT_LIST;
175+
}
176+
177+
if (directed) {
178+
scan_adv_type = BT_GAP_ADV_TYPE_ADV_DIRECT_IND;
179+
} else {
180+
scan_adv_type = BT_GAP_ADV_TYPE_ADV_IND;
181+
}
182+
183+
return bt_le_scan_start(&param, scan_connect_to_first_result__device_found);
184+
}
185+
#endif /* CONFIG_BT_CENTRAL */
186+
187+
#if defined(CONFIG_BT_PERIPHERAL)
188+
int advertise_connectable(int id, bt_addr_le_t *directed_dst, bool filter)
189+
{
190+
struct bt_le_adv_param param = {};
191+
192+
param.id = id;
193+
param.interval_min = 0x0020;
194+
param.interval_max = 0x4000;
195+
param.options |= BT_LE_ADV_OPT_CONN;
196+
197+
if (filter) {
198+
param.options |= BT_LE_ADV_OPT_FILTER_CONN;
199+
}
200+
201+
if (directed_dst) {
202+
param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA;
203+
param.peer = directed_dst;
204+
}
205+
206+
return bt_le_adv_start(&param, NULL, 0, NULL, 0);
207+
}
208+
#endif /* CONFIG_BT_PERIPHERAL */
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "bs_tracing.h"
8+
#include "bs_types.h"
9+
#include "bstests.h"
10+
#include "time_machine.h"
11+
#include <zephyr/sys/__assert.h>
12+
13+
#include <errno.h>
14+
#include <stddef.h>
15+
#include <stdint.h>
16+
17+
#include <zephyr/bluetooth/bluetooth.h>
18+
#include <zephyr/bluetooth/conn.h>
19+
#include <zephyr/bluetooth/gatt.h>
20+
#include <zephyr/bluetooth/hci.h>
21+
#include <zephyr/kernel.h>
22+
#include <zephyr/types.h>
23+
24+
#include "babblekit/testcase.h"
25+
#include "babblekit/flags.h"
26+
27+
DECLARE_FLAG(flag_pairing_complete);
28+
DECLARE_FLAG(flag_is_connected);
29+
DECLARE_FLAG(security_changed_flag);
30+
31+
#define WAIT_FOR_CONNECTED() WAIT_FOR_FLAG(flag_is_connected)
32+
#define WAIT_FOR_DISCONNECTED() WAIT_FOR_FLAG_UNSET(flag_is_connected)
33+
#define WAIT_FOR_ENCRYPTED_CONNECTION() \
34+
do { \
35+
WAIT_FOR_FLAG(security_changed_flag); \
36+
bool pairing_not_triggered; \
37+
pairing_not_triggered = !IS_FLAG_SET(flag_pairing_complete); \
38+
TEST_ASSERT(pairing_not_triggered, "Pairing triggered during encryption"); \
39+
} while (0)
40+
41+
#define FAL_ADD(addr) \
42+
do { \
43+
int err; \
44+
err = bt_le_filter_accept_list_add(addr); \
45+
TEST_ASSERT(!err, "Err bt_le_filter_accept_list_add %d", err); \
46+
} while (0)
47+
48+
#define FAL_CLEAR() \
49+
do { \
50+
int err; \
51+
err = bt_le_filter_accept_list_clear(); \
52+
TEST_ASSERT(!err, "Err bt_le_filter_accept_list_clear %d", err); \
53+
} while (0)
54+
55+
extern struct bt_conn *g_conn;
56+
57+
const char *addr_to_str(const bt_addr_le_t *addr);
58+
void clear_g_conn(void);
59+
void bs_bt_utils_setup(void);
60+
int scan_connect_to_first_result(bool directed, bool filter);
61+
int advertise_connectable(int id, bt_addr_le_t *directed_dst, bool filter);

0 commit comments

Comments
 (0)