src.dualinventive.com/dinet/sec-multi-proxy/libdi/tests/can_net_self_leader.cpp

134 lines
4.3 KiB
C++

/**
* @file tests/can_net_self_leader.cpp
* @brief CAN Net node events (for application)
* @date Dec 14, 2016
* @author jjacobs
* @copyright 2016 Dual Inventive Technology Centre B.V.
*
* Verify if self becomes leader
* * Set self TYPE_DEVICE
* * Set self ROLE_FOLLOWER
* * Discover network (request)
* * Discover network (finish)
* * Verify ROLE_FOLLOWER -> ROLE_LEADER event on self
* * Verify leadership
*/
#include "fixtures/CANTest.hpp"
extern "C" {
#include "time.c"
}
static size_t g_ev_idx = 0;
static void net_self_leader_event_cb(const struct di_can_net *ctx,
const enum di_can_net_node_events ev,
const struct di_can_net_node *node)
{
(void)ctx;
static const struct _tv {
const enum di_can_net_node_events ev;
const enum di_can_net_node_roles role;
} tv[] = {
{ DI_CAN_NET_NODE_EVENT_ROLE_LEADER, DI_CAN_NET_NODE_ROLE_FOLLOWER }
};
printf("[%s] event(%d): node: %04x, type: %02x, role: %02x\n", __func__, ev, node->nodeid, node->type, node->role);
ASSERT_TRUE(di_can_net_node_is_self(ctx, node));
ASSERT_EQ(0xdeadbeef, node->nodeid);
// ASSERT_EQ(DI_CAN_NET_NODE_TYPE_DEVICE, node->type);
ASSERT_GT(DI_ARRAY_SIZE(tv), g_ev_idx);
ASSERT_EQ(tv[g_ev_idx].ev, ev);
ASSERT_EQ(tv[g_ev_idx].role, node->role);
g_ev_idx++;
}
TEST_F(DI_CAN, net_self_leader) {
SetNodeid(0xdeadbeef);
di_can_net_node_set_event_callback(&_ctx, net_self_leader_event_cb);
// ASSERT_EQ(DNOK, di_can_net_self_set_node_type(&_ctx, DI_CAN_NET_NODE_TYPE_DEVICE));
ASSERT_EQ(DNOK, di_can_net_self_set_node_role(&_ctx, DI_CAN_NET_NODE_ROLE_FOLLOWER));
/* Check discover state and leadership */
ASSERT_EQ(DI_CAN_NET_DISCOVER_STATE_UNKNOWN, _ctx.net.discover.state);
ASSERT_FALSE(di_can_net_self_is_leader(&_ctx));
/* Execute net subsystem once (results in discover request) */
di_can_net_execute(&_ctx);
ASSERT_EQ(DI_CAN_NET_DISCOVER_STATE_REQUEST, _ctx.net.discover.state);
ASSERT_FALSE(di_can_net_self_is_leader(&_ctx));
/* Force discover timeout, execute net subsystem (results in leadership) */
_di_time_uptime = DI_CAN_NET_CFG_DISCOVER_TIMEOUT_MS;
ASSERT_EQ(0U, g_ev_idx);
di_can_net_execute(&_ctx);
ASSERT_EQ(1U, g_ev_idx);
g_ev_idx = 0;
ASSERT_EQ(DI_CAN_NET_DISCOVER_STATE_FINISH, _ctx.net.discover.state);
ASSERT_TRUE(di_can_net_self_is_leader(&_ctx));
}
/**
* Verify the heartbeat is send every DI_CAN_NET_CFG_SELF_LEADER_HEARTBEAT_MS
*/
TEST_F(DI_CAN, net_self_leader_heartbeat) {
struct di_can_msg *msg;
const size_t n_publishes = 8; // TODO: if we send more messages than 8 we are unable to receive them in loopback mode
SetNodeid(0xdeadbeef);
//ASSERT_EQ(DNOK, di_can_net_self_set_node_type(&_ctx, DI_CAN_NET_NODE_TYPE_DEVICE));
_ctx.net.discover.state = DI_CAN_NET_DISCOVER_STATE_FINISH;
_ctx.net.self.role = DI_CAN_NET_NODE_ROLE_LEADER;
/* Execute net subsystem and check if first publish is send */
_di_time_uptime = 0;
ASSERT_EQ(0U, _ctx.net.self.seen);
di_can_net_execute(&_ctx);
ASSERT_EQ(DI_CAN_NET_CFG_SELF_LEADER_HEARTBEAT_MS, _ctx.net.self.seen);
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_NET);
ASSERT_NE(nullptr, msg);
/* Execute net subsystem second time, no publish is send (due to publish timeout not exceeded) */
di_can_net_execute(&_ctx);
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_NET);
ASSERT_EQ(nullptr, msg);
/* Execute net subsystem 10 times (results in LEADER heartbeat publishes) */
_di_time_uptime = DI_CAN_NET_CFG_SELF_LEADER_HEARTBEAT_MS;
for (size_t n = 0; n < n_publishes; n++) {
di_can_net_execute(&_ctx);
_di_time_uptime += DI_CAN_NET_CFG_SELF_LEADER_HEARTBEAT_MS;
}
/* Verify 10 leader heartbeat publishes */
for (size_t n = 0; n < n_publishes; n++) {
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_NET);
if (!msg)
ASSERT_TRUE(false) << "di_can_recv == NULL (n: " << n << ")";
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DI_CAN_TRANSFERTYPE_PUBLISH, DI_CAN_GET_TRANSFERTYPE(msg->canid));
ASSERT_EQ(DI_CAN_NET_DTYPE_HEARTBEAT, DI_CAN_GET_DATATYPE(msg->canid));
ASSERT_EQ(0xdeadbeef, msg->src_id);
ASSERT_EQ(DI_CAN_NODEID_BROADCAST, msg->dst_id);
/* Verify the payload struct */
ASSERT_EQ(DI_CAN_PTYPE_STRUCT, msg->ptype);
ASSERT_EQ(2U, msg->size);
// ASSERT_EQ(DI_CAN_NET_NODE_TYPE_DEVICE, msg->msg[0]);
ASSERT_EQ(DI_CAN_NET_NODE_ROLE_LEADER, msg->msg[1]);
di_can_msg_free(&msg);
}
}