174 lines
4.7 KiB
C++
174 lines
4.7 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));
|
|
|
|
// dst_id unset is a protocol error
|
|
msg->dst_id = DI_CAN_NODEID_UNSET;
|
|
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;
|
|
|
|
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);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/** 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->dst_id
|
|
ASSERT_EQ(DI_CAN_NODEID_UNSET, msg->dst_id);
|
|
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));
|
|
}
|
|
|
|
void reqrep_error_reply_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;
|
|
|
|
di_can_send_errno_reply(msg, DNE_OPNOTSUPP);
|
|
di_can_msg_free(&msg);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/** Verify reply error sets the message error property */
|
|
TEST_F(DI_CAN, reqrep_error_reply) {
|
|
auto thr = std::thread(reqrep_error_reply_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->dst_id
|
|
ASSERT_EQ(DI_CAN_NODEID_UNSET, msg->dst_id);
|
|
msg->src_id = 0xdeadbeef;
|
|
msg->dst_id = DI_CAN_NODEID_BROADCAST;
|
|
|
|
ASSERT_EQ(DNOK, di_can_reqrep(&msg, 100));
|
|
ASSERT_NE(nullptr, msg);
|
|
ASSERT_NE(req, msg);
|
|
ASSERT_EQ(DNE_OPNOTSUPP, msg->error);
|
|
di_can_msg_free(&msg);
|
|
|
|
thr.join();
|
|
}
|