Commit cf3f2194 authored by Ludvig Samuelsen Jordet's avatar Ludvig Samuelsen Jordet Committed by Christopher Friedt
Browse files

Bluetooth: Mesh: Test reprovisioning



This adds tests for config client reset and reprovisioning of a node.

Signed-off-by: default avatarLudvig Samuelsen Jordet <ludvig.jordet@nordicsemi.no>
parent eb31ffe8
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -151,10 +151,16 @@ static struct bt_mesh_model_pub vnd_pub = {

static struct bt_mesh_cfg_cli cfg_cli;

static struct bt_mesh_health_srv health_srv;
static struct bt_mesh_model_pub health_pub = {
	.msg = NET_BUF_SIMPLE(BT_MESH_TX_SDU_MAX),
};

static struct bt_mesh_model models[] = {
	BT_MESH_MODEL_CFG_SRV,
	BT_MESH_MODEL_CFG_CLI(&cfg_cli),
	BT_MESH_MODEL_CB(TEST_MOD_ID, model_op, &pub, NULL, &test_model_cb),
	BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub),
};

struct bt_mesh_model *test_model = &models[2];
+115 −30
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
 */

#define PROV_MULTI_COUNT 3
#define PROV_REPROV_COUNT 10

enum test_flags {
	IS_PROVISIONER,
@@ -30,10 +31,12 @@ enum test_flags {
static ATOMIC_DEFINE(flags, TEST_FLAGS);
extern const struct bt_mesh_comp comp;
extern const uint8_t test_net_key[16];
extern const uint8_t test_app_key[16];

/* Timeout semaphore */
static struct k_sem prov_sem;
static uint16_t prov_addr = 0x0002;
static uint16_t current_dev_addr;
static const uint8_t dev_key[16] = { 0x01, 0x02, 0x03, 0x04, 0x05 };
static uint8_t dev_uuid[16] = { 0x6c, 0x69, 0x6e, 0x67, 0x61, 0x6f };

@@ -75,35 +78,58 @@ static void prov_node_added(uint16_t net_idx, uint8_t uuid[16], uint16_t addr,
			    uint8_t num_elem)
{
	LOG_INF("Device 0x%04x provisioned", prov_addr);
	prov_addr++;
	current_dev_addr = prov_addr++;
	k_sem_give(&prov_sem);
}

static void prov_reset(void)
{
	ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_ADV));
}

static struct bt_mesh_prov prov = {
	.uuid = dev_uuid,
	.unprovisioned_beacon = unprovisioned_beacon,
	.complete = prov_complete,
	.node_added = prov_node_added,
	.reset = prov_reset,
};

/** @brief Verify that this device pb-adv provision.
 */
static void test_device_pb_adv_no_oob(void)
{
	int err;
	k_sem_init(&prov_sem, 0, 1);

	bt_mesh_device_setup(&prov, &comp);

	ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_ADV));

	LOG_INF("Mesh initialized\n");

	/* Keep a long timeout so the prov multi case has time to finish: */
	ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(40)));

	PASS();
}

/** @brief Verify that this device can be reprovisioned after resets
 */
static void test_device_pb_adv_reprovision(void)
{
	k_sem_init(&prov_sem, 0, 1);

	bt_mesh_device_setup(&prov, &comp);

	err = bt_mesh_prov_enable(BT_MESH_PROV_ADV);
	ASSERT_OK(err, "Device PB-ADV Enable failed (err %d)", err);
	ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_ADV));

	LOG_INF("Mesh initialized\n");

	for (int i = 0; i < PROV_REPROV_COUNT; i++) {
		/* Keep a long timeout so the prov multi case has time to finish: */
	ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(40)),
		  "Device provision fail");
		LOG_INF("Dev prov loop #%d, waiting for prov ...\n", i);
		ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(5)));
	}

	PASS();
}
@@ -112,20 +138,15 @@ static void test_device_pb_adv_no_oob(void)
 */
static void test_provisioner_pb_adv_no_oob(void)
{
	int err;

	k_sem_init(&prov_sem, 0, 1);

	bt_mesh_device_setup(&prov, &comp);

	err = bt_mesh_cdb_create(test_net_key);
	ASSERT_OK(err, "Failed to create CDB (err %d)\n", err);
	ASSERT_OK(bt_mesh_cdb_create(test_net_key));

	err = bt_mesh_provision(test_net_key, 0, 0, 0, 0x0001, dev_key);
	ASSERT_OK(err, "Provisioning failed (err %d)", err);
	ASSERT_OK(bt_mesh_provision(test_net_key, 0, 0, 0, 0x0001, dev_key));

	ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(5)),
		  "Provisioner provision fail");
	ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(5)));

	PASS();
}
@@ -134,21 +155,16 @@ static void test_provisioner_pb_adv_no_oob(void)
 */
static void test_provisioner_pb_adv_multi(void)
{
	int err;

	k_sem_init(&prov_sem, 0, 1);

	bt_mesh_device_setup(&prov, &comp);

	err = bt_mesh_cdb_create(test_net_key);
	ASSERT_OK(err, "Failed to create CDB (err %d)\n", err);
	ASSERT_OK(bt_mesh_cdb_create(test_net_key));

	err = bt_mesh_provision(test_net_key, 0, 0, 0, 0x0001, dev_key);
	ASSERT_OK(err, "Provisioning failed (err %d)", err);
	ASSERT_OK(bt_mesh_provision(test_net_key, 0, 0, 0, 0x0001, dev_key));

	for (int i = 0; i < PROV_MULTI_COUNT; i++) {
		ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(20)),
			  "Provisioner provision #%d fail", i);
		ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(20)));
	}

	PASS();
@@ -159,13 +175,11 @@ static void test_provisioner_pb_adv_multi(void)
 */
static void test_provisioner_iv_update_flag_zero(void)
{
	int err;
	uint8_t flags = 0x00;

	bt_mesh_device_setup(&prov, &comp);

	err = bt_mesh_provision(test_net_key, 0, flags, 0, 0x0001, dev_key);
	ASSERT_OK(err, "Provisioning failed (err %d)", err);
	ASSERT_OK(bt_mesh_provision(test_net_key, 0, flags, 0, 0x0001, dev_key));

	if (bt_mesh.ivu_duration != 0) {
		FAIL("IV Update duration counter is not 0 when IV Update flag is zero");
@@ -179,13 +193,11 @@ static void test_provisioner_iv_update_flag_zero(void)
 */
static void test_provisioner_iv_update_flag_one(void)
{
	int err;
	uint8_t flags = 0x02; /* IV Update flag bit set to 1 */

	bt_mesh_device_setup(&prov, &comp);

	err = bt_mesh_provision(test_net_key, 0, flags, 0, 0x0001, dev_key);
	ASSERT_OK(err, "Provisioning failed (err %d)", err);
	ASSERT_OK(bt_mesh_provision(test_net_key, 0, flags, 0, 0x0001, dev_key));

	if (bt_mesh.ivu_duration != 96) {
		FAIL("IV Update duration counter is not 96 when IV Update flag is one");
@@ -200,6 +212,76 @@ static void test_provisioner_iv_update_flag_one(void)
	PASS();
}

/** @brief Verify that the provisioner can provision a device multiple times after resets
 */
static void test_provisioner_pb_adv_reprovision(void)
{
	k_sem_init(&prov_sem, 0, 1);

	bt_mesh_device_setup(&prov, &comp);

	ASSERT_OK(bt_mesh_cdb_create(test_net_key));

	ASSERT_OK(bt_mesh_provision(test_net_key, 0, 0, 0, 0x0001, dev_key));

	for (int i = 0; i < PROV_REPROV_COUNT; i++) {
		LOG_INF("Provisioner prov loop #%d, waiting for prov ...\n", i);
		ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(20)));

		uint8_t status;
		size_t subs_count = 1;
		uint16_t sub;
		struct bt_mesh_cfg_mod_pub healthpub = { 0 };
		struct bt_mesh_cdb_node *node;

		/* Check that publication and subscription are reset after last iteration */
		ASSERT_OK(bt_mesh_cfg_mod_sub_get(0, current_dev_addr, current_dev_addr,
						  BT_MESH_MODEL_ID_HEALTH_SRV, &status, &sub,
						  &subs_count));
		ASSERT_EQUAL(0, status);
		ASSERT_TRUE(subs_count == 0);

		ASSERT_OK(bt_mesh_cfg_mod_pub_get(0, current_dev_addr, current_dev_addr,
						  BT_MESH_MODEL_ID_HEALTH_SRV, &healthpub,
						  &status));
		ASSERT_EQUAL(0, status);
		ASSERT_TRUE(healthpub.addr == BT_MESH_ADDR_UNASSIGNED, "Pub not cleared");


		/* Set pub and sub to check that they are reset */
		healthpub.addr = 0xc001;
		healthpub.app_idx = 0;
		healthpub.cred_flag = false;
		healthpub.ttl = 10;
		healthpub.period = BT_MESH_PUB_PERIOD_10SEC(1);
		healthpub.transmit = BT_MESH_TRANSMIT(3, 100);

		ASSERT_OK(bt_mesh_cfg_app_key_add(0, current_dev_addr, 0, 0, test_app_key,
						  &status));
		ASSERT_EQUAL(0, status);

		ASSERT_OK(bt_mesh_cfg_mod_app_bind(0, current_dev_addr, current_dev_addr, 0x0,
						   BT_MESH_MODEL_ID_HEALTH_SRV, &status));
		ASSERT_EQUAL(0, status);

		ASSERT_OK(bt_mesh_cfg_mod_sub_add(0, current_dev_addr, current_dev_addr, 0xc000,
						  BT_MESH_MODEL_ID_HEALTH_SRV, &status));
		ASSERT_EQUAL(0, status);

		ASSERT_OK(bt_mesh_cfg_mod_pub_set(0, current_dev_addr, current_dev_addr,
						  BT_MESH_MODEL_ID_HEALTH_SRV, &healthpub,
						  &status));
		ASSERT_EQUAL(0, status);

		ASSERT_OK(bt_mesh_cfg_node_reset(0, current_dev_addr, (bool *)&status));

		node = bt_mesh_cdb_node_get(current_dev_addr);
		bt_mesh_cdb_node_del(node, true);
	}

	PASS();
}

#define TEST_CASE(role, name, description)                                     \
	{                                                                      \
		.test_id = "prov_" #role "_" #name, .test_descr = description, \
@@ -211,7 +293,8 @@ static void test_provisioner_iv_update_flag_one(void)
static const struct bst_test_instance test_connect[] = {
	TEST_CASE(device, pb_adv_no_oob,
		  "Device: pb-adv provisioning use no-oob method"),

	TEST_CASE(device, pb_adv_reprovision,
		  "Device: pb-adv provisioning, reprovision"),
	TEST_CASE(provisioner, pb_adv_no_oob,
		  "Provisioner: pb-adv provisioning use no-oob method"),
	TEST_CASE(provisioner, pb_adv_multi,
@@ -220,6 +303,8 @@ static const struct bst_test_instance test_connect[] = {
		  "Provisioner: effect on ivu_duration when IV Update flag is set to zero"),
	TEST_CASE(provisioner, iv_update_flag_one,
		  "Provisioner: effect on ivu_duration when IV Update flag is set to one"),
	TEST_CASE(provisioner, pb_adv_reprovision,
		  "Provisioner: pb-adv provisioning, resetting and reprovisioning multiple times."),

	BSTEST_END_MARKER
};
+1 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ static void test_tx_device_setup(void)
/** Bypassing setting up transmission, and will try to send the raw data that is
 *  provided to the function.
 */
static void test_tx_send_ad_type_msg(uint8_t type, uint8_t *data, uint8_t len)
static void test_tx_send_ad_type_msg(uint8_t type, const uint8_t *data, uint8_t len)
{
	struct bt_le_adv_param param = {};
	uint16_t duration, adv_int;
+9 −0
Original line number Diff line number Diff line
#!/usr/bin/env bash
# Copyright 2021 Nordic Semiconductor
# SPDX-License-Identifier: Apache-2.0

source $(dirname "${BASH_SOURCE[0]}")/../../_mesh_test.sh

RunTest mesh_provision_pb_adv_reprovision \
	prov_device_pb_adv_reprovision \
	prov_provisioner_pb_adv_reprovision