Bluetooth: tests: use global testlib in read_fill_buf

This deduplicates a copy of testlib from before testlib was a globally
available cmake library.

Signed-off-by: Aleksander Wasaznik <aleksander.wasaznik@nordicsemi.no>
This commit is contained in:
Aleksander Wasaznik 2024-03-15 23:24:40 +01:00 committed by Fabio Baltieri
parent adedf14c42
commit 1e2b889bbb
16 changed files with 20 additions and 532 deletions

View file

@ -6,11 +6,7 @@ find_package(Zephyr HINTS $ENV{ZEPHYR_BASE})
project(app)
target_sources(app PRIVATE
../testlib/bs_main.c
../testlib/scan.c
../testlib/connect.c
../testlib/security.c
../testlib/att_read.c
../bs_main.c
main.c
)
@ -18,3 +14,6 @@ zephyr_include_directories(
${BSIM_COMPONENTS_PATH}/libPhyComv1/src/
${BSIM_COMPONENTS_PATH}/libUtilv1/src/
)
add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/common/testlib testlib)
target_link_libraries(app PRIVATE testlib)

View file

@ -10,19 +10,19 @@
#include <zephyr/sys/byteorder.h>
#include <zephyr/logging/log.h>
#include "../common_defs.h"
#include <testlib/att_read.h>
#include <testlib/conn.h>
#include <testlib/scan.h>
#include <testlib/security.h>
#include "../testlib/att_read.h"
#include "../testlib/bs_macro.h"
#include "../testlib/connect.h"
#include "../testlib/scan.h"
#include "../testlib/security.h"
#include "../bs_macro.h"
#include "../common_defs.h"
LOG_MODULE_REGISTER(client, LOG_LEVEL_DBG);
#define BT_LOCAL_ATT_MTU_EATT MIN(BT_L2CAP_SDU_RX_MTU, BT_L2CAP_SDU_TX_MTU)
#define BT_LOCAL_ATT_MTU_UATT MIN(BT_L2CAP_RX_MTU, BT_L2CAP_TX_MTU)
#define BT_ATT_BUF_SIZE MAX(BT_LOCAL_ATT_MTU_UATT, BT_LOCAL_ATT_MTU_EATT)
#define BT_ATT_BUF_SIZE MAX(BT_LOCAL_ATT_MTU_UATT, BT_LOCAL_ATT_MTU_EATT)
void test_long_read(struct bt_conn *conn, enum bt_att_chan_opt bearer)
{
@ -43,20 +43,20 @@ void test_long_read(struct bt_conn *conn, enum bt_att_chan_opt bearer)
LOG_INF("ATT_READ_BY_TYPE");
/* Aka. "read by uuid". */
err = bt_testlib_att_read_by_type_sync(&attr_value, &actual_read_len,
&handle, conn, bearer,
&handle, NULL, conn, bearer,
MTU_VALIDATION_CHRC, 1, 0xffff);
break;
case 1:
LOG_INF("ATT_READ");
/* Arg `offset == 0`: the stack should choose ATT_READ PDU. */
err = bt_testlib_att_read_by_handle_sync(&attr_value, &actual_read_len,
conn, bearer, handle, 0);
NULL, conn, bearer, handle, 0);
break;
case 2:
LOG_INF("ATT_READ_BLOB");
/* Arg `offset != 0`: the stack should choose ATT_READ_BLOB PDU. */
err = bt_testlib_att_read_by_handle_sync(&attr_value, &actual_read_len,
conn, bearer, handle, 1);
NULL, conn, bearer, handle, 1);
break;
}

View file

@ -6,8 +6,7 @@ find_package(Zephyr HINTS $ENV{ZEPHYR_BASE})
project(app)
target_sources(app PRIVATE
../testlib/bs_main.c
../testlib/adv.c
../bs_main.c
main.c
)
@ -15,3 +14,6 @@ zephyr_include_directories(
${BSIM_COMPONENTS_PATH}/libPhyComv1/src/
${BSIM_COMPONENTS_PATH}/libUtilv1/src/
)
add_subdirectory(${ZEPHYR_BASE}/tests/bluetooth/common/testlib testlib)
target_link_libraries(app PRIVATE testlib)

View file

@ -8,9 +8,9 @@
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/byteorder.h>
#include "../testlib/bs_macro.h"
#include "../testlib/adv.h"
#include <testlib/adv.h>
#include "../bs_macro.h"
#include "../common_defs.h"
LOG_MODULE_REGISTER(server, LOG_LEVEL_DBG);

View file

@ -1,83 +0,0 @@
/* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/l2cap.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/kernel.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/__assert.h>
struct bt_testlib_adv_ctx {
struct bt_conn **result;
struct k_condvar done;
};
/* Context pool (with capacity of one). */
static K_SEM_DEFINE(g_ctx_free, 1, 1);
static K_MUTEX_DEFINE(g_ctx_lock);
static struct bt_testlib_adv_ctx *g_ctx;
static void connected_cb(struct bt_le_ext_adv *adv, struct bt_le_ext_adv_connected_info *info)
{
k_mutex_lock(&g_ctx_lock, K_FOREVER);
if (g_ctx->result) {
*g_ctx->result = bt_conn_ref(info->conn);
}
k_condvar_signal(&g_ctx->done);
k_mutex_unlock(&g_ctx_lock);
}
int bt_testlib_adv_conn(struct bt_conn **conn, int id, uint32_t adv_options)
{
int api_err;
struct bt_le_ext_adv *adv = NULL;
struct bt_le_adv_param param = {};
struct bt_testlib_adv_ctx ctx = {
.result = conn,
};
static const struct bt_le_ext_adv_cb cb = {
.connected = connected_cb,
};
param.id = id;
param.interval_min = BT_GAP_ADV_FAST_INT_MIN_1;
param.interval_max = BT_GAP_ADV_FAST_INT_MAX_1;
param.options |= BT_LE_ADV_OPT_CONNECTABLE;
param.options |= adv_options;
k_condvar_init(&ctx.done);
k_sem_take(&g_ctx_free, K_FOREVER);
k_mutex_lock(&g_ctx_lock, K_FOREVER);
g_ctx = &ctx;
api_err = bt_le_ext_adv_create(&param, &cb, &adv);
if (!api_err) {
api_err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
}
if (!api_err) {
k_condvar_wait(&ctx.done, &g_ctx_lock, K_FOREVER);
}
/* Delete adv before giving semaphore so that it's potentially available
* for the next taker of the semaphore.
*/
if (adv) {
bt_le_ext_adv_delete(adv);
}
g_ctx = NULL;
k_mutex_unlock(&g_ctx_lock);
k_sem_give(&g_ctx_free);
return api_err;
}

View file

@ -1,7 +0,0 @@
/* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/bluetooth/bluetooth.h>
int bt_testlib_adv_conn(struct bt_conn **conn, int id, uint32_t adv_options);

View file

@ -1,126 +0,0 @@
/* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/l2cap.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/__assert.h>
#include "att_read.h"
struct bt_testlib_att_read_closure {
uint8_t att_err;
struct bt_conn *conn;
struct bt_gatt_read_params params;
uint16_t *result_size;
uint16_t *result_handle;
struct net_buf_simple *result_data;
struct k_mutex lock;
struct k_condvar done;
};
static inline uint8_t att_read_cb(struct bt_conn *conn, uint8_t att_err,
struct bt_gatt_read_params *params, const void *read_data,
uint16_t read_len)
{
struct bt_testlib_att_read_closure *ctx =
CONTAINER_OF(params, struct bt_testlib_att_read_closure, params);
k_mutex_lock(&ctx->lock, K_FOREVER);
ctx->att_err = att_err;
if (!att_err && ctx->result_handle) {
*ctx->result_handle = params->by_uuid.start_handle;
}
if (!att_err && ctx->result_size) {
*ctx->result_size = read_len;
}
if (!att_err && ctx->result_data) {
uint16_t result_data_size =
MIN(read_len, net_buf_simple_tailroom(ctx->result_data));
net_buf_simple_add_mem(ctx->result_data, read_data, result_data_size);
}
k_condvar_signal(&ctx->done);
k_mutex_unlock(&ctx->lock);
return BT_GATT_ITER_STOP;
}
static inline int bt_testlib_sync_bt_gatt_read(struct bt_testlib_att_read_closure *ctx)
{
int api_err;
ctx->params.func = att_read_cb;
k_mutex_init(&ctx->lock);
k_condvar_init(&ctx->done);
k_mutex_lock(&ctx->lock, K_FOREVER);
api_err = bt_gatt_read(ctx->conn, &ctx->params);
if (!api_err) {
k_condvar_wait(&ctx->done, &ctx->lock, K_FOREVER);
}
k_mutex_unlock(&ctx->lock);
if (api_err) {
__ASSERT_NO_MSG(api_err < 0);
return api_err;
}
__ASSERT_NO_MSG(ctx->att_err >= 0);
return ctx->att_err;
}
int bt_testlib_att_read_by_type_sync(struct net_buf_simple *result_data, uint16_t *result_size,
uint16_t *result_handle, struct bt_conn *conn,
enum bt_att_chan_opt bearer, const struct bt_uuid *type,
uint16_t start_handle, uint16_t end_handle)
{
struct bt_testlib_att_read_closure ctx = {
.result_handle = result_handle,
.result_size = result_size,
.conn = conn,
.result_data = result_data,
.params = {.by_uuid = {.uuid = type,
.start_handle = start_handle,
.end_handle = end_handle},
IF_ENABLED(CONFIG_BT_EATT, (.chan_opt = bearer))},
};
if (bearer == BT_ATT_CHAN_OPT_ENHANCED_ONLY) {
__ASSERT(IS_ENABLED(CONFIG_BT_EATT), "EATT not complied in");
}
return bt_testlib_sync_bt_gatt_read(&ctx);
}
int bt_testlib_att_read_by_handle_sync(struct net_buf_simple *result_data, uint16_t *result_size,
struct bt_conn *conn, enum bt_att_chan_opt bearer,
uint16_t handle, uint16_t offset)
{
struct bt_testlib_att_read_closure ctx = {
.result_size = result_size,
.conn = conn,
.result_data = result_data,
.params = {.handle_count = 1,
.single = {.handle = handle, .offset = offset},
IF_ENABLED(CONFIG_BT_EATT, (.chan_opt = bearer))},
};
if (bearer == BT_ATT_CHAN_OPT_ENHANCED_ONLY) {
__ASSERT(IS_ENABLED(CONFIG_BT_EATT), "EATT not complied in");
}
return bt_testlib_sync_bt_gatt_read(&ctx);
}

View file

@ -1,15 +0,0 @@
/* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/bluetooth/gatt.h>
int bt_testlib_att_read_by_type_sync(struct net_buf_simple *result_data, uint16_t *result_size,
uint16_t *result_handle, struct bt_conn *conn,
enum bt_att_chan_opt bearer, const struct bt_uuid *type,
uint16_t start_handle, uint16_t end_handle);
int bt_testlib_att_read_by_handle_sync(struct net_buf_simple *result_data, uint16_t *result_size,
struct bt_conn *conn, enum bt_att_chan_opt bearer,
uint16_t handle, uint16_t offset);

View file

@ -1,71 +0,0 @@
/* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/kernel.h>
#include "connect.h"
struct bt_testlib_connect_closure {
uint8_t conn_err;
struct bt_conn **conn;
struct k_mutex lock;
struct k_condvar done;
};
/* Context pool (with capacity of one). */
static K_SEM_DEFINE(g_ctx_free, 1, 1);
static K_MUTEX_DEFINE(g_ctx_lock);
static struct bt_testlib_connect_closure *g_ctx;
static void connected_cb(struct bt_conn *conn, uint8_t conn_err)
{
/* Loop over each (allocated) item in pool. */
k_mutex_lock(&g_ctx_lock, K_FOREVER);
if (g_ctx && conn == *g_ctx->conn) {
g_ctx->conn_err = conn_err;
k_condvar_signal(&g_ctx->done);
}
k_mutex_unlock(&g_ctx_lock);
}
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected_cb,
};
int bt_testlib_connect(const bt_addr_le_t *peer, struct bt_conn **conn)
{
int api_err;
struct bt_testlib_connect_closure ctx = {
.conn = conn,
};
k_condvar_init(&ctx.done);
k_sem_take(&g_ctx_free, K_FOREVER);
k_mutex_lock(&g_ctx_lock, K_FOREVER);
g_ctx = &ctx;
api_err = bt_conn_le_create(peer, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, conn);
if (!api_err) {
k_condvar_wait(&ctx.done, &g_ctx_lock, K_FOREVER);
}
g_ctx = NULL;
k_mutex_unlock(&g_ctx_lock);
k_sem_give(&g_ctx_free);
if (api_err) {
__ASSERT_NO_MSG(api_err < 0);
return api_err;
}
__ASSERT_NO_MSG(ctx.conn_err >= 0);
return ctx.conn_err;
}

View file

@ -1,7 +0,0 @@
/* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/bluetooth/conn.h>
int bt_testlib_connect(const bt_addr_le_t *peer, struct bt_conn **conn);

View file

@ -1,87 +0,0 @@
/* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/__assert.h>
#include "scan.h"
struct bt_scan_find_name_closure {
char *wanted_name;
bt_addr_le_t *result;
struct k_condvar done;
};
/* Context pool (with capacity of one). */
static K_SEM_DEFINE(g_ctx_free, 1, 1);
static K_MUTEX_DEFINE(g_ctx_lock);
static struct bt_scan_find_name_closure *g_ctx;
static bool bt_scan_find_name_cb_data_cb(struct bt_data *data, void *user_data)
{
char **wanted = user_data;
if (data->type == BT_DATA_NAME_COMPLETE) {
if (data->data_len == strlen(*wanted) &&
!memcmp(*wanted, data->data, data->data_len)) {
*wanted = NULL;
/* Stop bt_data_parse. */
return false;
}
}
/* Continue with next ad data. */
return true;
}
static void bt_scan_find_name_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type,
struct net_buf_simple *buf)
{
char *wanted;
k_mutex_lock(&g_ctx_lock, K_FOREVER);
__ASSERT_NO_MSG(g_ctx);
__ASSERT_NO_MSG(g_ctx->wanted_name);
wanted = g_ctx->wanted_name;
bt_data_parse(buf, bt_scan_find_name_cb_data_cb, &wanted);
if (!wanted) {
(void)bt_le_scan_stop();
*g_ctx->result = *addr;
k_condvar_signal(&g_ctx->done);
}
k_mutex_unlock(&g_ctx_lock);
}
int bt_testlib_scan_find_name(bt_addr_le_t *result, char name[])
{
int api_err;
struct bt_scan_find_name_closure ctx = {
.wanted_name = name,
.result = result,
};
k_condvar_init(&ctx.done);
k_sem_take(&g_ctx_free, K_FOREVER);
k_mutex_lock(&g_ctx_lock, K_FOREVER);
g_ctx = &ctx;
api_err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, bt_scan_find_name_cb);
if (!api_err) {
k_condvar_wait(&ctx.done, &g_ctx_lock, K_FOREVER);
}
g_ctx = NULL;
k_mutex_unlock(&g_ctx_lock);
k_sem_give(&g_ctx_free);
return api_err;
}

View file

@ -1,7 +0,0 @@
/* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/bluetooth/bluetooth.h>
int bt_testlib_scan_find_name(bt_addr_le_t *result, char name[]);

View file

@ -1,103 +0,0 @@
/* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/l2cap.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/__assert.h>
struct testlib_security_ctx {
enum bt_security_err result;
struct bt_conn *conn;
bt_security_t new_minimum;
struct k_condvar done;
};
/* Context pool (with capacity of one). */
static K_SEM_DEFINE(g_ctx_free, 1, 1);
static K_MUTEX_DEFINE(g_ctx_lock);
static struct testlib_security_ctx *g_ctx;
static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err)
{
/* Mutex operations establish a happens-before relationship. This
* ensures variables have the expected values despite non-atomic
* accesses.
*/
k_mutex_lock(&g_ctx_lock, K_FOREVER);
if (g_ctx && (g_ctx->conn == conn)) {
g_ctx->result = err;
/* Assumption: A security error means there will be further
* security changes for this connection.
*/
if (err || level >= g_ctx->new_minimum) {
k_condvar_signal(&g_ctx->done);
}
}
k_mutex_unlock(&g_ctx_lock);
}
BT_CONN_CB_DEFINE(conn_callbacks) = {
.security_changed = security_changed,
};
int bt_testlib_secure(struct bt_conn *conn, bt_security_t new_minimum)
{
int api_err = 0;
struct testlib_security_ctx ctx = {
.conn = conn,
.new_minimum = new_minimum,
};
k_condvar_init(&ctx.done);
/* The semaphore allocates `g_ctx` to this invocation of
* `bt_testlib_secure`, in case this function is called from multiple
* threads in parallel.
*/
k_sem_take(&g_ctx_free, K_FOREVER);
/* The mutex synchronizes this function with `security_changed()`. */
k_mutex_lock(&g_ctx_lock, K_FOREVER);
/* Do the thing. */
api_err = bt_conn_set_security(conn, new_minimum);
/* Holding the mutex will pause any thread entering
* `security_changed_cb`, delaying it until `k_condvar_wait`. This
* ensures that the condition variable is signaled while this thread is
* in `k_condvar_wait`, even if the event happens before, e.g. between
* `bt_conn_get_security` and `k_condvar_wait`.
*
* If the security level is already satisfied, there is no point in
* waiting, and it would deadlock if security was already satisfied
* before the mutex was taken, `bt_conn_set_security` will result in no
* operation.
*/
if (!api_err && bt_conn_get_security(conn) < new_minimum) {
/* Waiting on a condvar releases the mutex and waits for a
* signal on the condvar, atomically, without a gap between the
* release and wait. The mutex is locked again before returning.
*/
g_ctx = &ctx;
k_condvar_wait(&ctx.done, &g_ctx_lock, K_FOREVER);
g_ctx = NULL;
}
k_mutex_unlock(&g_ctx_lock);
k_sem_give(&g_ctx_free);
if (api_err) {
__ASSERT_NO_MSG(api_err < 0);
return api_err;
}
__ASSERT_NO_MSG(ctx.result >= 0);
return ctx.result;
}

View file

@ -1,7 +0,0 @@
/* Copyright (c) 2023 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/bluetooth/conn.h>
int bt_testlib_secure(struct bt_conn *conn, bt_security_t new_minimum);