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

241 lines
8.0 KiB
C++

/**
* @file tests/can_net_node_error.cpp
* @brief CAN Net node events (for application)
* @date Dec 14, 2016
* @author jjacobs
* @copyright 2016 Dual Inventive Technology Centre B.V.
*/
#include "fixtures/CANTest.hpp"
extern "C" {
#include "time.c"
}
/**
* Test DI_CAN_NET_CANID_MSG_NODE_ERROR macro
*/
TEST_F(DI_CAN, CANID_MSG_NODE_ERROR) {
struct di_can_msg *msg;
msg = di_can_msg_alloc_with_canid(&_ctx, DI_CAN_NET_CANID_MSG_NODE_ERROR(PUBLISH));
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DI_CAN_MSGTYPE_NET, DI_CAN_GET_MSGTYPE(msg->canid));
ASSERT_EQ(DI_CAN_TRANSFERTYPE_PUBLISH, DI_CAN_GET_TRANSFERTYPE(msg->canid));
ASSERT_EQ(DI_CAN_NET_DTYPE_NODE_ERROR, DI_CAN_GET_DATATYPE(msg->canid));
di_can_msg_free(&msg);
}
/**
* Test di_can_net_serialize_node_error
*/
TEST_F(DI_CAN, net_serialize_node_error) {
struct di_can_msg *msg;
msg = di_can_msg_alloc_with_canid(&_ctx, DI_CAN_NET_CANID_MSG_NODE_ERROR(PUBLISH));
ASSERT_NE(nullptr, msg);
di_can_net_serialize_node_error(msg, DNE_FIRMWARE_TILT);
ASSERT_EQ(4U, msg->size);
di_can_msg_free(&msg);
}
/**
* Test di_can_net_publish_node_error
*/
TEST_F(DI_CAN, net_publish_node_error) {
ASSERT_EQ(DNOK, di_can_net_publish_node_error(&_ctx, DNE_FIRMWARE_TILT));
struct di_can_msg *msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_ANY);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DI_CAN_TRANSFERTYPE_PUBLISH, DI_CAN_GET_TRANSFERTYPE(msg->canid));
ASSERT_EQ(DI_CAN_NET_DTYPE_NODE_ERROR, DI_CAN_GET_DATATYPE(msg->canid));
ASSERT_EQ(DI_CAN_NODEID_BROADCAST, msg->dst_id);
ASSERT_EQ(DI_CAN_PTYPE_DI_ERRNO, msg->ptype);
ASSERT_EQ(4U, msg->size);
di_errno_t v;
ASSERT_EQ(DNOK, di_can_msg_read_data_di_errno(msg, &v));
ASSERT_EQ(DNE_FIRMWARE_TILT, v);
di_can_msg_free(&msg);
}
/**
* Test node error:
* * DI_CAN_NET_CALLBACK_NODE_ERROR_PUBLISH_ITEM
* * di_can_net_cb_node_error_publish
*/
TEST_F(DI_CAN, net_cb_node_error_publish) {
static struct di_can_callback callbacks[] = {
DI_CAN_NET_CALLBACK_NODE_ERROR_PUBLISH_ITEM
};
struct di_can_msg *msg;
ASSERT_EQ(DNOK, di_can_callback_init(&_ctx, callbacks, DI_ARRAY_SIZE(callbacks)));
ASSERT_EQ(DNOK, di_can_net_publish_node_error(&_ctx, DNE_FIRMWARE_TILT));
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_ANY);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DNOK, di_can_callback_execute(&_ctx, msg));
di_can_msg_free(&msg);
}
/**
* Test net node error event callback
* * Publish node error with di_can_net_publish_node_error
* * Recv the published message and feed it to di_can_callback_execute
* * Check in the callback
* * ev == DI_CAN_NET_NODE_EVENT_ERROR
* * node->nodeid == 0xdeadbeef
* * node->error == DNE_FIRMWARE_TILT
* * node->type == DI_CAN_NET_NODE_TYPE_UNKNOWN (undiscovered node)
* * node->role == DI_CAN_NET_NODE_ROLE_UNKNOWN (undiscovered node)
* * Publish again node error with di_can_net_publish_node_error
* * Recv the published message and feed it to di_can_callback_execute
* * Check if callback is not run
* * Publish node error with di_can_net_publish_node_error
* * Recv the published message and feed it to di_can_callback_execute
* * Check in the callback
* * ev == DI_CAN_NET_NODE_EVENT_ERROR
* * node->nodeid == 0xdeadbeef
* * node->error == DNOK
* * node->type == DI_CAN_NET_NODE_TYPE_UNKNOWN (undiscovered node)
* * node->role == DI_CAN_NET_NODE_ROLE_UNKNOWN (undiscovered node)
*/
static size_t net_node_error_event_cb_ctr = 0; /**< Event callback fired counter */
TEST_F(DI_CAN, net_node_error_event) {
void net_node_error_event_cb(const struct di_can_net *ctx,
const enum di_can_net_node_events ev,
const struct di_can_net_node *node);
static struct di_can_callback callbacks[] = {
DI_CAN_NET_CALLBACK_NODE_ERROR_PUBLISH_ITEM
};
struct di_can_msg *msg;
ASSERT_EQ(DNOK, di_can_callback_init(&_ctx, callbacks, DI_ARRAY_SIZE(callbacks)));
di_can_net_node_set_event_callback(&_ctx, net_node_error_event_cb);
/* Publish DNE_FIRMWARE_TILT as 0xcafebabe node */
SetNodeid(0xcafebabe);
di_can_net_publish_node_error(&_ctx, DNE_FIRMWARE_TILT);
/* Receive publish msg and execute net_node_error_event_cb on it */
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_ANY);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DNOK, di_can_callback_execute(&_ctx, msg));
di_can_msg_free(&msg);
/* Callback should have run exactly once */
ASSERT_EQ(1U, net_node_error_event_cb_ctr);
/* Publish second DNE_FIRMWARE_TILT as 0xcafebabe node */
di_can_net_publish_node_error(&_ctx, DNE_FIRMWARE_TILT);
/* Receive publish msg and execute net_node_error_event_cb on it */
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_ANY);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DNOK, di_can_callback_execute(&_ctx, msg));
di_can_msg_free(&msg);
/* Callback should have run exactly once, second same node_error is ignored */
ASSERT_EQ(1U, net_node_error_event_cb_ctr);
/* Publish second DNOK as 0xcafebabe node */
di_can_net_publish_node_error(&_ctx, DNOK);
/* Receive publish msg and execute net_node_error_event_cb on it */
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_ANY);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DNOK, di_can_callback_execute(&_ctx, msg));
di_can_msg_free(&msg);
/* Callback should have run exactly once, second same node_error is ignored */
ASSERT_EQ(2U, net_node_error_event_cb_ctr);
}
void net_node_error_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("[%s] event(%d): node: %04x, type: %02x, role: %02x\n", __func__, ev, node->nodeid, node->type, node->role);
ASSERT_EQ(DI_CAN_NET_NODE_EVENT_ERROR, ev);
ASSERT_EQ(0xcafebabe, node->nodeid);
/* Check on first callback if the error is DNE_FIRMWARE_TILT, second callback DNOK */
if (net_node_error_event_cb_ctr == 0)
ASSERT_EQ(DNE_FIRMWARE_TILT, node->error);
else if (net_node_error_event_cb_ctr == 1)
ASSERT_EQ(DNOK, node->error);
else
ASSERT_TRUE(false);
/* The node type and role are unknown because the node was not previously discovered */
ASSERT_EQ(DI_CAN_NET_NODE_TYPE_UNKNOWN, node->type);
ASSERT_EQ(DI_CAN_NET_NODE_ROLE_UNKNOWN, node->role);
net_node_error_event_cb_ctr++;
}
/**
* Verify di_can_net_execute publishes self node error when !DNOK
*/
TEST_F(DI_CAN, net_self_execute_error_publish) {
struct di_can_msg *msg;
// Set error, check if it is directly published. Then truncate the send message
di_can_net_self_set_error(&_ctx, DNE_FIRMWARE_TILT);
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_ANY);
ASSERT_NE(nullptr, msg);
di_can_msg_free(&msg);
// Set time after the self node error timeout exact on DI_CAN_NET_CFG_SELF_ERROR_PUBLISH_MS, then run di_can_net_execute
_ctx.net.discover.state = DI_CAN_NET_DISCOVER_STATE_FINISH;
_di_time_uptime = DI_CAN_NET_CFG_SELF_ERROR_PUBLISH_MS;
di_can_net_execute(&_ctx);
// Receive the published self node error message send by di_can_net_execute
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_ANY);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DI_CAN_NET_DTYPE_NODE_ERROR, DI_CAN_GET_DATATYPE(msg->canid));
di_can_msg_free(&msg);
// Send next publish with net execute
_di_time_uptime = (DI_CAN_NET_CFG_SELF_ERROR_PUBLISH_MS * 2) + 1;
di_can_net_execute(&_ctx);
// Receive the published self node error message send by di_can_net_execute
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_ANY);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DI_CAN_NET_DTYPE_NODE_ERROR, DI_CAN_GET_DATATYPE(msg->canid));
di_can_msg_free(&msg);
// Clear self node error by setting it to DNOK
di_can_net_self_set_error(&_ctx, DNOK);
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_ANY);
ASSERT_NE(nullptr, msg);
// Check DNOK is published by di_can_net_self_set_error
di_errno_t err;
ASSERT_EQ(DNOK, di_can_msg_read_data_di_errno(msg, &err));
ASSERT_EQ(DNOK, err);
di_can_msg_free(&msg);
// Check di_can_net_execute doesn't publish when self node error == DNOK
_di_time_uptime = (DI_CAN_NET_CFG_SELF_ERROR_PUBLISH_MS * 3);
di_can_net_execute(&_ctx);
// Receive the published self node error message send by di_can_net_execute
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_ANY);
ASSERT_EQ(nullptr, msg);
}