Skip to content

Commit

Permalink
tests: Bluetooth: Add some more tests for bt_le_create_conn()
Browse files Browse the repository at this point in the history
Adds coverage for attempting to connect while already connecting
or connecting to a device that already exists.

Signed-off-by: Rubin Gerritsen <[email protected]>
  • Loading branch information
rugeGerritsen authored and mmahadevan108 committed Sep 17, 2024
1 parent c394234 commit f6712c4
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 11 deletions.
1 change: 1 addition & 0 deletions tests/bsim/bluetooth/host/central/prj.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
CONFIG_ASSERT=y
CONFIG_BT=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_PERIPHERAL=y
66 changes: 66 additions & 0 deletions tests/bsim/bluetooth/host/central/src/dummy_peripheral.c
Original file line number Diff line number Diff line change
@@ -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);
}
143 changes: 132 additions & 11 deletions tests/bsim/bluetooth/host/central/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand All @@ -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);

Expand All @@ -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);
Expand All @@ -82,25 +102,126 @@ 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,
},
{
.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,
},
BSTEST_END_MARKER
{
.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)
{
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)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit f6712c4

Please sign in to comment.