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