src.dualinventive.com/jjacobs/dinetrpcll-sniffer/libdi/tests/device_error.cpp

248 lines
8.0 KiB
C++

/**
* @file tests/device_error.cpp
* @brief Device error state tests
* @date Apr 1, 2016
* @author jjacobs
* @copyright 2016 Dual Inventive Technology Centre B.V.
*/
#include "fixtures/CANTest.hpp"
#include "tests/rpc_serialize.h"
#include <di/array.h>
#include <di/can/rpc/callbacks.h>
#include <di/device.h>
/**
* Check if initial device error is set to DNOK
*/
TEST(device_error, initial) {
di_device_init();
}
/**
* Check if set and unset work as expected
*/
TEST(device_error, set_unset) {
ASSERT_EQ(DNOK, di_device_error_set(DNE_TIMEOUT));
EXPECT_TRUE(di_device_error_is_specific_set(DNE_TIMEOUT));
di_device_error_unset(DNE_TIMEOUT);
EXPECT_FALSE(di_device_error_is_specific_set(DNE_TIMEOUT));
// Try to unset a non-set error and see if it not crashes
di_device_error_unset(DNE_TIMEOUT);
}
/**
* Try to set a error in the forbidden range
*/
TEST(device_error, set_unset_invalid_range) {
ASSERT_EQ(DNE_PARAM, di_device_error_set(DNE_DUPLICATE_PROJECT));
EXPECT_FALSE(di_device_error_is_specific_set(DNE_DUPLICATE_PROJECT));
di_device_error_unset(DNE_DUPLICATE_PROJECT);
}
/**
* Verify the error list can be full and no one can be added
*/
TEST(device_error, set_returns_DNE_NOMEM) {
static const di_errno_t tv[] {
DNE_PARAM, DNE_RANGE, DNE_NODEV, DNE_NORES,
DNE_BUSY, DNE_OPNOTSUPP, DNE_FIRMWARE_TILT, DNE_CAN_TIMEOUT,
};
ASSERT_EQ(8U, di_device_error_list_size());
for (size_t n = 0; n < DI_ARRAY_SIZE(tv); n++)
ASSERT_EQ(DNOK, di_device_error_set(tv[n]));
ASSERT_EQ(DNE_NOMEM, di_device_error_set(DNE_CAN_IO));
di_device_error_reset_all();
ASSERT_FALSE(di_device_error_is_set());
}
/**
* Check if multiple same error (DNE_TIMEOUT) set work as expected
*/
TEST(device_error, set_error_multiple_times) {
for (size_t n = 0; n < 16; n++)
ASSERT_EQ(DNOK, di_device_error_set(DNE_TIMEOUT));
EXPECT_TRUE(di_device_error_is_specific_set(DNE_TIMEOUT));
di_device_error_reset_all();
ASSERT_FALSE(di_device_error_is_set());
}
/** Set multiple errors */
TEST(device_error, set_multiple) {
ASSERT_EQ(DNOK, di_device_error_set(DNE_TIMEOUT));
ASSERT_EQ(DNOK, di_device_error_set(DNE_FIRMWARE_EEPROM));
ASSERT_EQ(DNOK, di_device_error_set(DNE_CAN_AGAIN));
ASSERT_TRUE(di_device_error_is_set());
ASSERT_TRUE(di_device_error_is_specific_set(DNE_TIMEOUT));
ASSERT_TRUE(di_device_error_is_specific_set(DNE_FIRMWARE_EEPROM));
ASSERT_TRUE(di_device_error_is_specific_set(DNE_CAN_AGAIN));
di_device_error_reset_all();
ASSERT_FALSE(di_device_error_is_set());
}
/** Verify serialize with three errors using list_write_rpc_msg_result and generates correct MessagePack */
TEST(device_error, list_write_rpc_msg_result)
{
auto writer = TEST_RPC_SERIALIZE_WRITER;
ASSERT_EQ(DNOK, di_device_error_set(DNE_TIMEOUT));
ASSERT_EQ(DNOK, di_device_error_set(DNE_CAN_INVAL));
ASSERT_EQ(DNOK, di_device_error_set(DNE_CAN_AGAIN));
di_device_error_list_write_rpc_result_msg(writer->get());
di_device_error_reset_all();
}
/** Verify serialize with three errors using list_write_rpc_msg_result and generates correct MessagePack empty array object */
TEST(device_error, list_write_rpc_msg_result_empty_array)
{
auto writer = TEST_RPC_SERIALIZE_WRITER;
di_device_error_list_write_rpc_result_msg(writer->get());
}
/** Verify the correct DI-Net CAN RPC message (result) is published with an MessagePack empty array */
TEST_F(DI_CAN, can_rpc_send_device_errors_array_pub_empty)
{
SetNodeid(0xdead1337);
struct di_can_msg *msg;
/* Publish device:errors empty array */
ASSERT_EQ(DNOK, di_can_rpc_send_device_errors(&_ctx, DI_CAN_NODEID_BROADCAST, DI_CAN_TRANSFERTYPE_PUBLISH));
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_RPC);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DI_CAN_TRANSFERTYPE_PUBLISH, DI_CAN_GET_TRANSFERTYPE(msg->canid));
ASSERT_EQ(DI_RPC_TYPE_DEVICE_ERRORS, DI_CAN_GET_DATATYPE(msg->canid));
ASSERT_EQ(0xdead1337, msg->src_id);
ASSERT_EQ(DI_CAN_NODEID_BROADCAST, msg->dst_id);
ASSERT_EQ(1U, msg->size);
ASSERT_EQ(0x90, msg->msg[0]); // MessagePack empty array opcode
di_can_msg_free(&msg);
}
/** Verify the correct DI-Net CAN RPC message (result) is replied or published */
TEST_F(DI_CAN, can_rpc_send_device_errors_array_rep_pub)
{
ASSERT_EQ(DNOK, di_device_error_set(DNE_TIMEOUT));
ASSERT_EQ(DNOK, di_device_error_set(DNE_CAN_INVAL));
ASSERT_EQ(DNOK, di_device_error_set(DNE_CAN_AGAIN));
SetNodeid(0xdead1337);
struct di_can_msg *msg;
/* Publish device:errors empty array */
ASSERT_EQ(DNOK, di_can_rpc_send_device_errors(&_ctx, DI_CAN_NODEID_BROADCAST, DI_CAN_TRANSFERTYPE_PUBLISH));
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_RPC);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DI_CAN_TRANSFERTYPE_PUBLISH, DI_CAN_GET_TRANSFERTYPE(msg->canid));
ASSERT_EQ(DI_RPC_TYPE_DEVICE_ERRORS, DI_CAN_GET_DATATYPE(msg->canid));
ASSERT_EQ(0xdead1337, msg->src_id);
ASSERT_EQ(DI_CAN_NODEID_BROADCAST, msg->dst_id);
ASSERT_EQ(86U, msg->size);
di_can_msg_free(&msg);
/* Send reply device:errors empty array */
ASSERT_EQ(DNOK, di_can_rpc_send_device_errors(&_ctx, 0xcafebabe, DI_CAN_TRANSFERTYPE_REPLY));
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_RPC);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DI_CAN_TRANSFERTYPE_REPLY, DI_CAN_GET_TRANSFERTYPE(msg->canid));
ASSERT_EQ(DI_RPC_TYPE_DEVICE_ERRORS, DI_CAN_GET_DATATYPE(msg->canid));
ASSERT_EQ(0xdead1337, msg->src_id);
ASSERT_EQ(0xcafebabe, msg->dst_id);
ASSERT_EQ(86U, msg->size);
di_can_msg_free(&msg);
di_device_error_reset_all();
}
/** Unset errors */
TEST(device_error, unset) {
di_device_error_unset(DNOK);
di_device_error_unset(DNE_TIMEOUT);
di_device_error_set(DNE_CAN_INVAL);
ASSERT_TRUE(di_device_error_is_set());
ASSERT_TRUE(di_device_error_is_specific_set(DNE_CAN_INVAL));
di_device_error_unset(DNE_CAN_INVAL);
ASSERT_FALSE(di_device_error_is_set());
}
/** Verify the correct DI-Net CAN RPC message is replied with the can callbacks */
static struct di_can_callback test_device_errors_callbacks[] = {
DI_CAN_RPC_CALLBACK_DEVICE_ERRORS_REQUEST_ITEM
};
static struct di_can_msg *device_errors_can_rpc_generate_request(struct di_can_ctx *ctx)
{
struct di_can_msg *msg = di_can_msg_alloc_with_canid(ctx,
DI_CAN_MSGTYPE_RPC,
DI_CAN_TRANSFERTYPE_REQUEST,
DI_RPC_TYPE_DEVICE_ERRORS);
msg->src_id = 0xcafebabe;
msg->dst_id = 0xdeadbeef;
return msg;
}
TEST_F(DI_CAN, device_errors_can_rpc_request_callback)
{
SetNodeid(0xdeadbeef);
di_can_callback_init(&_ctx, test_device_errors_callbacks, DI_ARRAY_SIZE(test_device_errors_callbacks));
/* Generate request and execute request callback (which must send a reply) */
struct di_can_msg *msg = device_errors_can_rpc_generate_request(&_ctx);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DNOK, di_can_callback_execute(&_ctx, msg));
di_can_msg_free(&msg);
/* Verify empty reply array is send */
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_RPC);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DI_CAN_TRANSFERTYPE_REPLY, DI_CAN_GET_TRANSFERTYPE(msg->canid));
ASSERT_EQ(DI_RPC_TYPE_DEVICE_ERRORS, DI_CAN_GET_DATATYPE(msg->canid));
ASSERT_EQ(0xdeadbeef, msg->src_id);
ASSERT_EQ(0xcafebabe, msg->dst_id);
ASSERT_EQ(1U, msg->size);
ASSERT_EQ(0x90, msg->msg[0]); // MessagePack empty array code
di_can_msg_free(&msg);
/* Set 3 device errors */
ASSERT_EQ(DNOK, di_device_error_set(DNE_TIMEOUT));
ASSERT_EQ(DNOK, di_device_error_set(DNE_CAN_INVAL));
ASSERT_EQ(DNOK, di_device_error_set(DNE_CAN_AGAIN));
/* Generate request and execute request callback (which must send a reply) */
msg = device_errors_can_rpc_generate_request(&_ctx);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DNOK, di_can_callback_execute(&_ctx, msg));
di_can_msg_free(&msg);
msg = di_can_recv(&_ctx, DI_CAN_MSGTYPE_RPC);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(DI_CAN_TRANSFERTYPE_REPLY, DI_CAN_GET_TRANSFERTYPE(msg->canid));
ASSERT_EQ(DI_RPC_TYPE_DEVICE_ERRORS, DI_CAN_GET_DATATYPE(msg->canid));
ASSERT_EQ(0xdeadbeef, msg->src_id);
ASSERT_EQ(0xcafebabe, msg->dst_id);
ASSERT_EQ(86U, msg->size);
ASSERT_EQ(0x93, msg->msg[0]);
di_can_msg_free(&msg);
}