blob: 6835324256f3f8cb23c3198a465ae4d38ad27f8b [file] [log] [blame]
/*
* Copyright (c) 2021 Nordic Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "mesh_test.h"
#include "argparse.h"
#include "mesh/net.h"
#include "mesh/heartbeat.h"
#define LOG_MODULE_NAME test_heartbeat
#include <logging/log.h>
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
#define WAIT_TIME 60 /*seconds*/
#define SUBSCRIBER_ADDR 0x00fe
#define SUBSCRIBE_PERIOD_SEC 30
#define PUBLISHER_ADDR_START 0x0001
#define PUBLISH_PERIOD_SEC 1
#define PUBLISH_MSG_CNT 10
#define PUBLISH_FEATURES_RANGE 0x0f
#define PUBLISH_TTL 0
#define EXPECTED_HB_HOPS 0x01
static uint16_t pub_addr = BT_MESH_ADDR_UNASSIGNED;
static const struct bt_mesh_test_cfg subscribe_cfg = {
.addr = SUBSCRIBER_ADDR,
.dev_key = { 0xff },
};
static struct bt_mesh_test_cfg pub_cfg;
static void test_publish_init(void)
{
pub_cfg.addr = PUBLISHER_ADDR_START + get_device_nbr();
pub_cfg.dev_key[0] = get_device_nbr();
bt_mesh_test_cfg_set(&pub_cfg, WAIT_TIME);
}
static void test_subscribe_init(void)
{
bt_mesh_test_cfg_set(&subscribe_cfg, WAIT_TIME);
}
static struct sub_context {
uint8_t count;
uint8_t min_hops;
uint8_t max_hops;
} sub_ctx = {
.count = 0,
.min_hops = 0xFF,
.max_hops = 0,
};
static void sub_hb_recv_cb(const struct bt_mesh_hb_sub *sub, uint8_t hops, uint16_t feat)
{
LOG_INF("Heartbeat received from addr: 0x%04x", sub->src);
ASSERT_EQUAL(PUBLISHER_ADDR_START, sub->src);
ASSERT_EQUAL(pub_addr, sub->dst);
ASSERT_EQUAL(SUBSCRIBE_PERIOD_SEC, sub->period);
ASSERT_TRUE(sub->remaining <= SUBSCRIBE_PERIOD_SEC);
ASSERT_EQUAL(sub_ctx.count + 1, sub->count);
ASSERT_EQUAL(hops, EXPECTED_HB_HOPS);
ASSERT_TRUE(feat <= PUBLISH_FEATURES_RANGE);
sub_ctx.count++;
sub_ctx.min_hops = MIN(sub_ctx.min_hops, sub->min_hops);
sub_ctx.max_hops = MAX(sub_ctx.max_hops, sub->max_hops);
}
static void sub_hb_end_cb(const struct bt_mesh_hb_sub *sub)
{
LOG_INF("Heartbeat subscription has ended");
ASSERT_EQUAL(PUBLISHER_ADDR_START, sub->src);
ASSERT_EQUAL(pub_addr, sub->dst);
ASSERT_EQUAL(SUBSCRIBE_PERIOD_SEC, sub->period);
ASSERT_EQUAL(0, sub->remaining);
ASSERT_EQUAL(PUBLISH_MSG_CNT, sub->count);
ASSERT_EQUAL(sub_ctx.count, sub->count);
ASSERT_EQUAL(sub_ctx.min_hops, sub->min_hops);
ASSERT_EQUAL(sub_ctx.max_hops, sub->max_hops);
PASS();
}
BT_MESH_HB_CB_DEFINE(hb_cb) = {
.recv = sub_hb_recv_cb,
.sub_end = sub_hb_end_cb,
};
static void publish_common(void)
{
bt_mesh_test_setup();
struct bt_mesh_hb_pub new_pub = {
.dst = pub_addr,
.count = PUBLISH_MSG_CNT,
.period = PUBLISH_PERIOD_SEC,
.net_idx = 0,
.ttl = PUBLISH_TTL,
};
bt_mesh_hb_pub_set(&new_pub);
}
static void test_publish_unicast(void)
{
pub_addr = SUBSCRIBER_ADDR;
publish_common();
PASS();
}
static void test_publish_all(void)
{
pub_addr = BT_MESH_ADDR_ALL_NODES;
publish_common();
PASS();
}
static void subscribe_commmon(void)
{
bt_mesh_test_setup();
bt_mesh_hb_sub_set(PUBLISHER_ADDR_START, pub_addr, SUBSCRIBE_PERIOD_SEC);
}
static void test_subscribe_unicast(void)
{
pub_addr = SUBSCRIBER_ADDR;
subscribe_commmon();
}
static void test_subscribe_all(void)
{
pub_addr = BT_MESH_ADDR_ALL_NODES;
subscribe_commmon();
}
#define TEST_CASE(role, name, description) \
{ \
.test_id = "heartbeat_" #role "_" #name, \
.test_descr = description, \
.test_post_init_f = test_##role##_init, \
.test_tick_f = bt_mesh_test_timeout, \
.test_main_f = test_##role##_##name, \
}
static const struct bst_test_instance test_connect[] = {
TEST_CASE(publish, unicast, "Heartbeat: Publish heartbeat to unicast"),
TEST_CASE(subscribe, unicast, "Heartbeat: Subscribe to heartbeat from unicast"),
TEST_CASE(publish, all, "Heartbeat: Publish heartbeat to all nodes"),
TEST_CASE(subscribe, all, "Heartbeat: Subscribe to heartbeat all nodes"),
BSTEST_END_MARKER
};
struct bst_test_list *test_heartbeat_install(struct bst_test_list *tests)
{
tests = bst_add_tests(tests, test_connect);
return tests;
}