tests: Bluetooth: Add some more tests for bt_le_create_conn()

Adds coverage for attempting to connect while already connecting
or connecting to a device that already exists.

Signed-off-by: Rubin Gerritsen <rubin.gerritsen@nordicsemi.no>
This commit is contained in:
Rubin Gerritsen 2024-09-11 14:06:11 +02:00 committed by Mahesh Mahadevan
commit f6712c43d4
5 changed files with 238 additions and 11 deletions

View file

@ -1,3 +1,4 @@
CONFIG_ASSERT=y
CONFIG_BT=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_PERIPHERAL=y

View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2024 Nordic Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "bstests.h"
#include "babblekit/testcase.h"
#include <zephyr/bluetooth/conn.h>
static K_SEM_DEFINE(sem_connected, 0, 1);
static void connected_cb(struct bt_conn *conn, uint8_t err)
{
TEST_ASSERT(conn);
TEST_ASSERT(err == 0, "Expected success");
k_sem_give(&sem_connected);
bt_conn_unref(conn);
}
static struct bt_conn_cb conn_cb = {
.connected = connected_cb,
};
static void test_peripheral_dummy(void)
{
int err;
const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR))};
bt_conn_cb_register(&conn_cb);
bt_addr_le_t addr = {.type = BT_ADDR_LE_RANDOM,
.a.val = {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}};
err = bt_id_create(&addr, NULL);
TEST_ASSERT(err == 0, "Failed to create iD (err %d)", err);
/* Initialize Bluetooth */
err = bt_enable(NULL);
TEST_ASSERT(err == 0, "Can't enable Bluetooth (err %d)", err);
err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0);
TEST_ASSERT(err == 0, "Advertising failed to start (err %d)", err);
err = k_sem_take(&sem_connected, K_FOREVER);
TEST_ASSERT(err == 0, "Failed getting connected timeout", err);
TEST_PASS("Passed");
}
static const struct bst_test_instance test_def[] = {
{
.test_id = "peripheral_dummy",
.test_descr = "Connectable peripheral",
.test_tick_f = bst_tick,
.test_main_f = test_peripheral_dummy,
},
BSTEST_END_MARKER,
};
struct bst_test_list *test_peripheral_install(struct bst_test_list *tests)
{
return bst_add_tests(tests, test_def);
}

View file

@ -8,17 +8,36 @@
#include "babblekit/testcase.h"
#include <zephyr/bluetooth/conn.h>
/* Include conn_internal for the purpose of checking reference counts. */
#include "host/conn_internal.h"
struct bst_test_list *test_peripheral_install(struct bst_test_list *tests);
static K_SEM_DEFINE(sem_failed_to_connect, 0, 1);
static K_SEM_DEFINE(sem_connected, 0, 1);
static void connected_cb(struct bt_conn *conn, uint8_t err)
static void connected_cb_expect_fail(struct bt_conn *conn, uint8_t err)
{
TEST_ASSERT(conn);
TEST_ASSERT(err == BT_HCI_ERR_UNKNOWN_CONN_ID, "Expected connection timeout");
k_sem_give(&sem_failed_to_connect);
bt_conn_unref(conn);
}
static void connected_cb(struct bt_conn *conn, uint8_t err)
{
TEST_ASSERT(conn);
TEST_ASSERT(err == BT_HCI_ERR_SUCCESS, "Expected connection establishment");
k_sem_give(&sem_connected);
bt_conn_unref(conn);
}
static struct bt_conn_cb conn_cb_expect_fail = {
.connected = connected_cb_expect_fail,
};
static struct bt_conn_cb conn_cb = {
.connected = connected_cb,
};
@ -44,14 +63,14 @@ static void test_central_connect_timeout_with_timeout(uint32_t timeout_ms)
.timeout = timeout_ms / 10,
};
k_sem_reset(&sem_connected);
k_sem_reset(&sem_failed_to_connect);
const uint64_t conn_create_start = k_uptime_get();
err = bt_conn_le_create(&peer, &create_param, BT_LE_CONN_PARAM_DEFAULT, &conn);
TEST_ASSERT(err == 0, "Failed starting initiator (err %d)", err);
err = k_sem_take(&sem_connected, K_MSEC(2 * expected_conn_timeout_ms));
err = k_sem_take(&sem_failed_to_connect, K_MSEC(2 * expected_conn_timeout_ms));
TEST_ASSERT(err == 0, "Failed getting connected timeout within %d s (err %d)",
2 * expected_conn_timeout_ms, err);
@ -63,14 +82,15 @@ static void test_central_connect_timeout_with_timeout(uint32_t timeout_ms)
TEST_PRINT("Connection timeout after %d ms", time_diff_ms);
TEST_ASSERT(diff_to_expected_ms < 0.1 * expected_conn_timeout_ms,
"Connection timeout not within 10%% of expected timeout. "
"Actual timeout: %d", time_diff_ms);
"Actual timeout: %d",
time_diff_ms);
}
static void test_central_connect_timeout(void)
{
int err;
bt_conn_cb_register(&conn_cb);
bt_conn_cb_register(&conn_cb_expect_fail);
/* Initialize Bluetooth */
err = bt_enable(NULL);
@ -82,14 +102,118 @@ static void test_central_connect_timeout(void)
TEST_PASS("Correct timeout");
}
static void test_central_connect_when_connecting(void)
{
int err;
bt_conn_cb_register(&conn_cb_expect_fail);
/* Initialize Bluetooth */
err = bt_enable(NULL);
TEST_ASSERT(err == 0, "Can't enable Bluetooth (err %d)", err);
struct bt_conn *conn;
bt_addr_le_t peer = {.a.val = {0x01}};
const struct bt_conn_le_create_param create_param = {
.options = BT_CONN_LE_OPT_NONE,
.interval = BT_GAP_SCAN_FAST_INTERVAL,
.window = BT_GAP_SCAN_FAST_WINDOW,
};
k_sem_reset(&sem_failed_to_connect);
err = bt_conn_le_create(&peer, &create_param, BT_LE_CONN_PARAM_DEFAULT, &conn);
TEST_ASSERT(err == 0, "Failed starting initiator (err %d)", err);
/* Now we have a valid connection reference */
atomic_val_t initial_refs = atomic_get(&conn->ref);
TEST_ASSERT(initial_refs >= 1, "Expect to have at least once reference");
err = bt_conn_le_create(&peer, &create_param, BT_LE_CONN_PARAM_DEFAULT, &conn);
TEST_ASSERT(err == -EALREADY, "Expected to fail to create connection (err %d)", err);
/* Expect the number of refs to be unchanged. */
TEST_ASSERT(atomic_get(&conn->ref) == initial_refs,
"Expect number of references to be unchanged");
err = k_sem_take(&sem_failed_to_connect, K_FOREVER);
TEST_ASSERT(err == 0, "Failed getting connected timeout", err);
TEST_ASSERT(atomic_get(&conn->ref) == 0, "Expect no more references");
TEST_PASS("Passed");
}
static void test_central_connect_to_existing(void)
{
int err;
bt_conn_cb_register(&conn_cb);
/* Initialize Bluetooth */
err = bt_enable(NULL);
TEST_ASSERT(err == 0, "Can't enable Bluetooth (err %d)", err);
struct bt_conn *conn;
bt_addr_le_t peer = {.type = BT_ADDR_LE_RANDOM,
.a.val = {0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0}};
const struct bt_conn_le_create_param create_param = {
.options = BT_CONN_LE_OPT_NONE,
.interval = BT_GAP_SCAN_FAST_INTERVAL,
.window = BT_GAP_SCAN_FAST_WINDOW,
};
k_sem_reset(&sem_connected);
err = bt_conn_le_create(&peer, &create_param, BT_LE_CONN_PARAM_DEFAULT, &conn);
TEST_ASSERT(err == 0, "Failed starting initiator (err %d)", err);
err = k_sem_take(&sem_connected, K_FOREVER);
TEST_ASSERT(err == 0, "Failed establishing connection", err);
/* Now we have a valid connection reference */
atomic_val_t initial_refs = atomic_get(&conn->ref);
TEST_ASSERT(initial_refs >= 1, "Expect to have at least once reference");
err = bt_conn_le_create(&peer, &create_param, BT_LE_CONN_PARAM_DEFAULT, &conn);
TEST_ASSERT(err == -EINVAL, "Expected to fail to create a connection (err %d)", err);
/* Expect the number of refs to be unchanged. */
TEST_ASSERT(atomic_get(&conn->ref) == initial_refs,
"Expect number of references to be unchanged");
TEST_PASS("Passed");
}
static const struct bst_test_instance test_def[] = {
{
.test_id = "central_connect_timeout",
.test_descr = "Verifies that the default connection timeout is used correctly",
.test_tick_f = bst_tick,
.test_main_f = test_central_connect_timeout
.test_main_f = test_central_connect_timeout,
},
BSTEST_END_MARKER
{
.test_id = "central_connect_when_connecting",
.test_descr = "Verifies that the stack returns an error code when trying to connect"
" while already connecting",
.test_tick_f = bst_tick,
.test_main_f = test_central_connect_when_connecting,
},
{
.test_id = "central_connect_to_existing",
.test_descr =
"Verifies that the stack returns an error code when trying to connect"
" to an existing device and does not unref the existing connection object.",
.test_tick_f = bst_tick,
.test_main_f = test_central_connect_to_existing,
},
BSTEST_END_MARKER,
};
static struct bst_test_list *test_central_install(struct bst_test_list *tests)
@ -97,10 +221,7 @@ static struct bst_test_list *test_central_install(struct bst_test_list *tests)
return bst_add_tests(tests, test_def);
}
bst_test_install_t test_installers[] = {
test_central_install,
NULL
};
bst_test_install_t test_installers[] = {test_central_install, test_peripheral_install, NULL};
int main(void)
{

View file

@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Copyright (c) 2024 Nordic Semiconductor
# SPDX-License-Identifier: Apache-2.0
source ${ZEPHYR_BASE}/tests/bsim/sh_common.source
simulation_id="central_connect_timeout_to_existing"
verbosity_level=2
cd ${BSIM_OUT_PATH}/bin
Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_central_prj_conf \
-v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central_connect_to_existing
Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_central_prj_conf \
-v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral_dummy
Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \
-D=2 -sim_length=60e6 $@
wait_for_background_jobs

View file

@ -0,0 +1,18 @@
#!/usr/bin/env bash
# Copyright (c) 2024 Nordic Semiconductor
# SPDX-License-Identifier: Apache-2.0
source ${ZEPHYR_BASE}/tests/bsim/sh_common.source
simulation_id="central_connect_when_connecting"
verbosity_level=2
cd ${BSIM_OUT_PATH}/bin
Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_central_prj_conf \
-v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central_connect_when_connecting
Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \
-D=1 -sim_length=60e6 $@
wait_for_background_jobs