src.dualinventive.com/fw/libdi_fw-tests/libdi/tests/can_msg_reqrep.cpp

163 lines
4.4 KiB
C++

/**
* @file tests/can_msg.cpp
* @brief CAN message unit test
* @date Sep 30, 2015
* @author jjacobs
* @copyright 2015 Dual Inventive Technology Centre B.V.
*
* CAN Message unit test
*/
#include <thread>
#include "fixtures/CANTest.hpp"
/** Check if DNE_TIMEOUT is returned when no reply is received */
TEST_F(DI_CAN, reqrep_timeout) {
struct di_can_msg *msg = di_can_msg_alloc_with_canid(&_ctx,
DI_CAN_MSGTYPE_RAW,
DI_CAN_TRANSFERTYPE_REPLY,
DI_CAN_RAW_DTYPE_DEVICE_UID);
msg->src_id = 0xdeadbeef;
msg->dst_id = 0xcafebabe;
ASSERT_EQ(DNE_TIMEOUT, di_can_reqrep(&msg, 10));
}
/** Check if the the di_can_reqrep parameters are check correct */
TEST_F(DI_CAN, reqrep_params) {
struct di_can_msg *msg = di_can_msg_alloc_with_canid(&_ctx,
DI_CAN_MSGTYPE_RAW,
DI_CAN_TRANSFERTYPE_REPLY,
DI_CAN_RAW_DTYPE_DEVICE_UID);
struct di_can_msg **_msg = NULL;
// NULL check
ASSERT_EQ(DNE_PARAM, di_can_reqrep(NULL, 10));
ASSERT_EQ(DNE_PARAM, di_can_reqrep(_msg, 10));
// !broadcast and dst_id unset is a protocol error
msg->dst_id = DI_CAN_NODEID_UNSET;
msg->broadcast = false;
ASSERT_EQ(DNE_PROTO, di_can_reqrep(&msg, 10));
}
void reqrep_dnok_thread(struct di_can_ctx *ctx) {
struct di_can_msg *msg;
while (true) {
msg = di_can_recv(ctx, DI_CAN_MSGTYPE_ANY);
if (!msg)
continue;
/* Send reply on request */
if (DI_CAN_GET_TRANSFERTYPE(msg->canid) == DI_CAN_TRANSFERTYPE_REQUEST) {
struct di_can_msg *rep = di_can_msg_alloc_with_canid(ctx,
DI_CAN_MSGTYPE_RAW,
DI_CAN_TRANSFERTYPE_REPLY,
DI_CAN_RAW_DTYPE_DEVICE_UID);
rep->src_id = msg->dst_id;
rep->dst_id = msg->src_id;
DI_CAN_SET_TRANSACTION(rep->canid, DI_CAN_GET_TRANSACTION(msg->canid));
di_can_send(&rep);
return;
}
di_can_msg_free(&msg);
di_can_msg_gc(ctx, DI_CAN_GC_ALL);
di_can_frame_gc(ctx, DI_CAN_GC_ALL);
}
}
/** Check if DNOK is returned when a reply is received with a unicast */
TEST_F(DI_CAN, reqrep_unicast_dnok) {
auto thr = std::thread(reqrep_dnok_thread, &_ctx);
/* Prepare request */
struct di_can_msg *msg = di_can_msg_alloc_with_canid(&_ctx,
DI_CAN_MSGTYPE_RAW,
DI_CAN_TRANSFERTYPE_REQUEST,
DI_CAN_RAW_DTYPE_DEVICE_UID);
struct di_can_msg *req = msg;
msg->src_id = 0xdeadbeef;
msg->dst_id = 0xcafebabe;
ASSERT_EQ(DNOK, di_can_reqrep(&msg, 10));
ASSERT_NE(nullptr, msg);
ASSERT_NE(req, msg);
di_can_msg_free(&msg);
thr.join();
}
/** Check if DNOK is returned when a reply is received with a broadcast
* * Test msg->broadcast = true
* * Test msg->dst_id = DI_CAN_NODEID_BROADCAST
*/
TEST_F(DI_CAN, reqrep_broadcast_dnok) {
auto thr = std::thread(reqrep_dnok_thread, &_ctx);
/* Prepare request */
struct di_can_msg *msg = di_can_msg_alloc_with_canid(&_ctx,
DI_CAN_MSGTYPE_RAW,
DI_CAN_TRANSFERTYPE_REQUEST,
DI_CAN_RAW_DTYPE_DEVICE_UID);
struct di_can_msg *req = msg;
// Send broadcast request by setting msg->broadcast
ASSERT_EQ(DI_CAN_NODEID_UNSET, msg->dst_id);
msg->src_id = 0xdeadbeef;
msg->broadcast = true;
ASSERT_EQ(DNOK, di_can_reqrep(&msg, 10));
ASSERT_NE(nullptr, msg);
ASSERT_NE(req, msg);
di_can_msg_free(&msg);
thr.join();
// Send broadcast request by setting msg->dst_id to DI_CAN_NODEID_BROADCAST
thr = std::thread(reqrep_dnok_thread, &_ctx);
msg = di_can_msg_alloc_with_canid(&_ctx,
DI_CAN_MSGTYPE_RAW,
DI_CAN_TRANSFERTYPE_REQUEST,
DI_CAN_RAW_DTYPE_DEVICE_UID);
req = msg;
ASSERT_FALSE(msg->broadcast);
msg->src_id = 0xdeadbeef;
msg->dst_id = DI_CAN_NODEID_BROADCAST;
ASSERT_EQ(DNOK, di_can_reqrep(&msg, 10));
ASSERT_NE(nullptr, msg);
ASSERT_NE(req, msg);
di_can_msg_free(&msg);
thr.join();
}
/** Verify unicast outstanding reply is matched correctly and the semaphore works as expected */
TEST_F(DI_CAN, reqrep_add_item_unicast) {
// Prepare a outstanding reply item
_ctx.reqrep.item.canid = 0x12345678;
_ctx.reqrep.item.src_id = 0xdeadbeef;
// Prepare and add the reply
struct di_can_msg *msg = di_can_msg_alloc(&_ctx);
msg->canid = _ctx.reqrep.item.canid;
msg->src_id = _ctx.reqrep.item.src_id;
msg->dst_id = 0xcafebabe;
ASSERT_EQ(DNOK, di_can_reqrep_add_reply(&_ctx, msg));
// Verify the message pointer is set, and the semaphore works as expected
ASSERT_EQ(_ctx.reqrep.item.msg, msg);
ASSERT_EQ(DNOK, di_bsem_wait_timeout(&_ctx.reqrep.item.sem, 10));
ASSERT_EQ(DNE_TIMEOUT, di_bsem_wait_timeout(&_ctx.reqrep.item.sem, 10));
}