193 lines
7.5 KiB
C++
193 lines
7.5 KiB
C++
/**
|
|
* @file tests/can_net_discover_fsm.cpp
|
|
* @brief CAN Net discover mechanism (leader,follower)
|
|
* @date Sep 5, 2015
|
|
* @author jjacobs
|
|
* @copyright 2015 Dual Inventive Technology Centre B.V.
|
|
*/
|
|
#include "fixtures/CANTest.hpp"
|
|
|
|
/**
|
|
* Verify the correct network discover request broadcast message is send
|
|
* * msgtype : DI_CAN_MSGTYPE_NET
|
|
* * transfertype : DI_CAN_TRANSFERTYPE_REQUEST
|
|
* * datatype : DI_CAN_NET_DTYPE_DISCOVER
|
|
* * src node id : 0xdead1337
|
|
* * dst node id : DI_CAN_NODEID_BROADCAST (0xffffffff)
|
|
*/
|
|
TEST_F(DI_CAN, net_discover) {
|
|
SetNodeid(0xdead1337);
|
|
ASSERT_EQ(DNOK, di_can_net_discover(&_ctx));
|
|
|
|
struct di_can_msg *msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_NET);
|
|
|
|
ASSERT_NE((void *)NULL, msg);
|
|
ASSERT_EQ(DI_CAN_TRANSFERTYPE_REQUEST, DI_CAN_GET_TRANSFERTYPE(msg->canid));
|
|
ASSERT_EQ(DI_CAN_NET_DTYPE_DISCOVER, DI_CAN_GET_DATATYPE(msg->canid));
|
|
ASSERT_EQ(0xdead1337, msg->src_id);
|
|
ASSERT_EQ(DI_CAN_NODEID_BROADCAST, msg->dst_id);
|
|
|
|
di_can_msg_free(&msg);
|
|
}
|
|
|
|
/**
|
|
* Verify the DISCOVER request is correctly handled by the DI_CAN_NET_CALLBACK_DISCOVER_ITEM
|
|
* * Call di_can_net_discover (src_id: 0xdeadbeef -> dst_id: broadcast)
|
|
* * Execute callback on msg (src_id: 0xcafebabe -> dst_id: 0xdeadbeef)
|
|
* * Verify reply is send
|
|
*/
|
|
static struct di_can_callback test_discover_callbacks[] = {
|
|
DI_CAN_NET_DISCOVER_CALLBACK_REQUEST_ITEM,
|
|
DI_CAN_NET_DISCOVER_CALLBACK_REPLY_ITEM
|
|
};
|
|
|
|
TEST_F(DI_CAN, discover_cb_trigger_on_request) {
|
|
di_can_callback_init(&_ctx, test_discover_callbacks, DI_ARRAY_SIZE(test_discover_callbacks));
|
|
|
|
/* Request discover from node id 0xdeadbeef */
|
|
SetNodeid(0xdeadbeef);
|
|
ASSERT_EQ(DNOK, di_can_net_discover(&_ctx));
|
|
|
|
/* Reply discover */
|
|
SetNodeid(0xcafebabe);
|
|
di_can_net_self_set_node_type(&_ctx, DI_CAN_NET_NODE_TYPE_GATEWAY);
|
|
di_can_net_self_set_node_role(&_ctx, DI_CAN_NET_NODE_ROLE_FOLLOWER);
|
|
|
|
/* Read request and execute request callback (which sends a reply) */
|
|
struct di_can_msg *msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_NET);
|
|
ASSERT_NE(nullptr, msg);
|
|
ASSERT_EQ(DI_CAN_TRANSFERTYPE_REQUEST, DI_CAN_GET_TRANSFERTYPE(msg->canid));
|
|
ASSERT_EQ(DI_CAN_NET_DTYPE_DISCOVER, DI_CAN_GET_DATATYPE(msg->canid));
|
|
ASSERT_EQ(0xdeadbeef, msg->src_id);
|
|
ASSERT_EQ(DI_CAN_NODEID_BROADCAST, msg->dst_id);
|
|
ASSERT_EQ(0U, msg->size);
|
|
ASSERT_EQ(DNOK, di_can_callback_execute(&_ctx, msg));
|
|
di_can_msg_free(&msg);
|
|
|
|
/* Read the DI_CAN_NET_DTYPE_HEARTBEAT publish message which was send by the
|
|
* di_can_net_self_set_node_role call (necessary for fast-takeover)
|
|
*/
|
|
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_NET);
|
|
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(DI_CAN_PTYPE_STRUCT, msg->ptype);
|
|
ASSERT_EQ(2U, msg->size);
|
|
ASSERT_EQ(0xcafebabe, msg->src_id);
|
|
ASSERT_EQ(DI_CAN_NODEID_BROADCAST, msg->dst_id);
|
|
di_can_msg_free(&msg);
|
|
|
|
/* Check if the correct reply is send from the callback */
|
|
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_NET);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
ASSERT_EQ(DI_CAN_TRANSFERTYPE_REPLY, DI_CAN_GET_TRANSFERTYPE(msg->canid));
|
|
ASSERT_EQ(DI_CAN_NET_DTYPE_DISCOVER, DI_CAN_GET_DATATYPE(msg->canid));
|
|
ASSERT_EQ(DI_CAN_PTYPE_STRUCT, msg->ptype);
|
|
ASSERT_EQ(2U, msg->size);
|
|
ASSERT_EQ(0xcafebabe, msg->src_id);
|
|
ASSERT_EQ(0xdeadbeef, msg->dst_id);
|
|
}
|
|
|
|
/**
|
|
* Verify execution of DI_CAN_NET_DISCOVER_CALLBACK_REPLY_ITEM
|
|
* The nodes list is updated with:
|
|
* - nodeid: 0xdeadbeef
|
|
* - type: DI_CAN_NET_NODE_TYPE_GATEWAY
|
|
* - role: DI_CAN_NET_NODE_ROLE_FOLLOWER
|
|
*/
|
|
|
|
static bool discover_cb_trigger_on_reply_node_new;
|
|
static bool discover_cb_trigger_on_reply_node_conflict;
|
|
static struct di_can_net_node discover_cb_trigger_on_reply_node;
|
|
|
|
void discover_cb_trigger_on_reply_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;
|
|
printf("event(%d): node: %04x, type: %02x, role: %02x\n", ev, node->nodeid, node->type, node->role);
|
|
|
|
/* Only copy the node structure for the test when it is correct */
|
|
if (node->nodeid == 0xcafebabe &&
|
|
node->type == DI_CAN_NET_NODE_TYPE_GATEWAY) {
|
|
memcpy(&discover_cb_trigger_on_reply_node, node, sizeof(*node));
|
|
|
|
switch (ev) {
|
|
case DI_CAN_NET_NODE_EVENT_NEW:
|
|
if (node->role == DI_CAN_NET_NODE_ROLE_FOLLOWER)
|
|
discover_cb_trigger_on_reply_node_new = true;
|
|
break;
|
|
case DI_CAN_NET_NODE_EVENT_CONFLICT:
|
|
discover_cb_trigger_on_reply_node_conflict = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(DI_CAN, discover_cb_trigger_on_reply) {
|
|
di_can_callback_init(&_ctx, test_discover_callbacks, DI_ARRAY_SIZE(test_discover_callbacks));
|
|
di_can_net_node_set_event_callback(&_ctx, discover_cb_trigger_on_reply_event_cb);
|
|
|
|
/* Request discover from node id 0xdeadbeef */
|
|
SetNodeid(0xdeadbeef);
|
|
ASSERT_EQ(DNOK, di_can_net_discover(&_ctx));
|
|
|
|
/* Reply discover */
|
|
SetNodeid(0xcafebabe); // Fake a nodeid (for reply)
|
|
|
|
di_can_net_self_set_node_type(&_ctx, DI_CAN_NET_NODE_TYPE_GATEWAY);
|
|
di_can_net_self_set_node_role(&_ctx, DI_CAN_NET_NODE_ROLE_FOLLOWER);
|
|
|
|
struct di_can_msg *msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_NET);
|
|
ASSERT_NE(nullptr, msg);
|
|
ASSERT_EQ(DI_CAN_TRANSFERTYPE_REQUEST, DI_CAN_GET_TRANSFERTYPE(msg->canid));
|
|
ASSERT_EQ(DI_CAN_NET_DTYPE_DISCOVER, DI_CAN_GET_DATATYPE(msg->canid));
|
|
ASSERT_EQ(0U, msg->size);
|
|
ASSERT_EQ(0xdeadbeef, msg->src_id);
|
|
ASSERT_EQ(DI_CAN_NODEID_BROADCAST, msg->dst_id);
|
|
ASSERT_EQ(DNOK, di_can_callback_execute(&_ctx, msg));
|
|
di_can_msg_free(&msg);
|
|
|
|
SetNodeid(0xdeadbeef); // Restore the local nodeid, else a nodeid conflict is detected
|
|
|
|
/* Read the DI_CAN_NET_DTYPE_HEARTBEAT publish message which was send by the
|
|
* di_can_net_self_set_node_role call (necessary for fast-takeover)
|
|
*/
|
|
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_NET);
|
|
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(DI_CAN_PTYPE_STRUCT, msg->ptype);
|
|
ASSERT_EQ(2U, msg->size);
|
|
ASSERT_EQ(0xcafebabe, msg->src_id);
|
|
ASSERT_EQ(DI_CAN_NODEID_BROADCAST, msg->dst_id);
|
|
di_can_msg_free(&msg);
|
|
|
|
/* Check if the correct reply is send from the callback */
|
|
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_NET);
|
|
ASSERT_NE(nullptr, msg);
|
|
ASSERT_EQ(DI_CAN_TRANSFERTYPE_REPLY, DI_CAN_GET_TRANSFERTYPE(msg->canid));
|
|
ASSERT_EQ(DI_CAN_NET_DTYPE_DISCOVER, DI_CAN_GET_DATATYPE(msg->canid));
|
|
ASSERT_EQ(DI_CAN_PTYPE_STRUCT, msg->ptype);
|
|
ASSERT_EQ(2U, msg->size);
|
|
ASSERT_EQ(0xcafebabe, msg->src_id);
|
|
ASSERT_EQ(0xdeadbeef, msg->dst_id);
|
|
ASSERT_EQ(DNOK, di_can_callback_execute(&_ctx, msg));
|
|
|
|
/* Check if the discover_cb_trigger_on_reply_event_cb is fired and the node is correct */
|
|
ASSERT_EQ(0xcafebabe, discover_cb_trigger_on_reply_node.nodeid);
|
|
ASSERT_EQ(DI_CAN_NET_NODE_TYPE_GATEWAY, discover_cb_trigger_on_reply_node.type);
|
|
ASSERT_EQ(DI_CAN_NET_NODE_ROLE_FOLLOWER, discover_cb_trigger_on_reply_node.role);
|
|
|
|
/* Check if NEW event is fired */
|
|
ASSERT_TRUE(discover_cb_trigger_on_reply_node_new);
|
|
ASSERT_FALSE(discover_cb_trigger_on_reply_node_conflict);
|
|
|
|
/* Check if the CONFLICT event is NOT fired (due to probably self and node[0] have the same nodeid)
|
|
*/
|
|
PrintNetNodes();
|
|
ASSERT_FALSE(discover_cb_trigger_on_reply_node_conflict);
|
|
}
|