241 lines
8.0 KiB
C++
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);
|
|
}
|