src.dualinventive.com/fw/dncm/libdi/tests/can_frame.cpp

232 lines
5.5 KiB
C++

/**
* @file tests/can_frame.cpp
* @brief brief
* @date Aug 25, 2015
* @author rheijden
* @copyright 2015 Dual Inventive Technology Centre B.V.
*
* @todo add GC tests
* descr
*/
#include "tests/can.h"
#include <gtest/gtest.h>
#include <di/can/frame.h>
extern "C" {
#include "time.c"
#include "can/frame.c"
}
static struct di_can_ctx ctx;
DI_CAN_FRAME_RX_DECL_ARRAY(test_can_frames, DI_CAN_CFG_FRAME_SIZE);
TEST(time, init) {
di_time_init();
}
/**
* Test if NULL, 0 initialization resets the context
* and the other functions dont crash or return incorrect pointers
*/
TEST(can_frame, init_null) {
struct di_can_frame_rx *f;
di_can_frame_init(NULL, NULL, 0);
di_can_frame_init(&ctx, NULL, 0);
ASSERT_EQ(0U, ctx.frame.pool.size);
ASSERT_EQ((void *)NULL, ctx.frame.pool.begin);
di_can_frame_init(&ctx, NULL, 10);
ASSERT_EQ(0U, ctx.frame.pool.size);
ASSERT_EQ((void *)NULL, ctx.frame.pool.begin);
di_can_frame_init(&ctx, (struct di_can_frame_rx *)0x1234567, 0);
ASSERT_EQ(0U, ctx.frame.pool.size);
ASSERT_EQ((void *)NULL, ctx.frame.pool.begin);
f = di_can_frame_get_unused(&ctx);
ASSERT_EQ((void *)NULL, f);
f = di_can_frame_get_ready(&ctx);
ASSERT_EQ((void *)NULL, f);
}
/**
* Initialize the frame subsystem, then try to initialize again (with other parameters)
*/
TEST(can_frame, init) {
/* Initialize */
di_can_frame_init(&ctx, test_can_frames, DI_CAN_CFG_FRAME_SIZE);
ASSERT_EQ(DI_CAN_CFG_FRAME_SIZE, ctx.frame.pool.size);
ASSERT_EQ(&test_can_frames, ctx.frame.pool.begin);
}
/**
* Initialize again
*/
TEST(can_frame, init_again) {
/* Initialize again with invalid parameters and see if nothing changed */
di_can_frame_init(&ctx, NULL, 0);
ASSERT_EQ(DI_CAN_CFG_FRAME_SIZE, ctx.frame.pool.size);
ASSERT_EQ(&test_can_frames, ctx.frame.pool.begin);
/* Set frame.pool.begin = NULL, dont touch size */
ctx.frame.pool.begin = NULL;
di_can_frame_init(&ctx, test_can_frames, DI_CAN_CFG_FRAME_SIZE);
ASSERT_EQ(DI_CAN_CFG_FRAME_SIZE, ctx.frame.pool.size);
ASSERT_EQ(&test_can_frames, ctx.frame.pool.begin);
/* Set frame.pool.size = 0, dont touch begin */
ctx.frame.pool.size = 0;
di_can_frame_init(&ctx, test_can_frames, DI_CAN_CFG_FRAME_SIZE);
ASSERT_EQ(DI_CAN_CFG_FRAME_SIZE, ctx.frame.pool.size);
ASSERT_EQ(&test_can_frames, ctx.frame.pool.begin);
}
/**
* Get free and return a single buffer
*/
TEST(can_frame, get_unused__return_ready) {
struct di_can_frame_rx *f;
f = di_can_frame_get_unused(&ctx);
ASSERT_NE((void *)NULL, f);
ASSERT_TRUE(DI_BIT_SET(f->flags, DI_CAN_FRAME_FLAGS_BIT_USED));
f->canid = 0x12345678;
f->size = 8;
memset(&f->buf, 0x55, 8);
di_can_frame_return_ready(f);
ASSERT_TRUE(DI_BIT_SET(f->flags, DI_CAN_FRAME_FLAGS_BIT_USED));
ASSERT_TRUE(DI_BIT_SET(f->flags, DI_CAN_FRAME_FLAGS_BIT_READY));
}
/**
* Get used frame from previous test
*/
TEST(can_frame, get_ready__return_unused) {
struct di_can_frame_rx *f;
f = di_can_frame_get_ready(&ctx);
ASSERT_NE((void *)NULL, f);
ASSERT_TRUE(DI_BIT_SET(f->flags, DI_CAN_FRAME_FLAGS_BIT_USED));
ASSERT_TRUE(DI_BIT_SET(f->flags, DI_CAN_FRAME_FLAGS_BIT_READY));
ASSERT_EQ(0x12345678U, f->canid);
ASSERT_EQ(8U, f->size);
for (size_t n = 0; n < f->size; n++)
ASSERT_EQ(0x55, f->buf[n]);
di_can_frame_return_unused(f);
}
/**
* Deplete pool and check if null is returned
*/
TEST(can_frame, get_unused_null) {
struct di_can_frame_rx *f;
/* Get all frames with unused flag */
for (size_t n = 0; n < DI_CAN_CFG_FRAME_SIZE; n++) {
f = di_can_frame_get_unused(&ctx);
ASSERT_NE((void *)NULL, f);
di_can_frame_return_ready(f);
}
/* Check if pool is empty */
f = di_can_frame_get_unused(&ctx);
ASSERT_EQ((void *)NULL, f);
/* Return all ready frames back to ready */
for (size_t n = 0; n < DI_CAN_CFG_FRAME_SIZE; n++) {
f = di_can_frame_get_ready(&ctx);
ASSERT_NE((void *)NULL, f);
di_can_frame_return_unused(f);
}
/* Check if pool is usable again */
f = di_can_frame_get_unused(&ctx);
ASSERT_NE((void *)NULL, f);
di_can_frame_return_unused(f);
}
/**
* Check if get_ready returns null
*/
TEST(can_frame, get_ready_null) {
struct di_can_frame_rx *f;
f = di_can_frame_get_ready(&ctx);
ASSERT_EQ((void *)NULL, f);
}
/**
* Non-behaviour test of gc
*/
TEST(can_frame, gc) {
di_can_frame_gc(&ctx, DI_CAN_GC_SINGLE);
di_can_frame_gc(&ctx, DI_CAN_GC_ALL);
}
/**
* Test GC
*/
TEST(can_frame, gc_all) {
_di_time_uptime = 1234;
for (size_t n = 0; n < ctx.frame.pool.size; n++) {
struct di_can_frame_rx *f = di_can_frame_get_unused(&ctx);
ASSERT_NE((void *)NULL, f);
di_can_frame_return_ready(f);
}
_di_time_uptime += ctx.frame.timeout + 1;
di_can_frame_gc(&ctx, DI_CAN_GC_SINGLE);
di_can_frame_gc(&ctx, DI_CAN_GC_ALL);
}
/**
* Check if the correct application specific private_data pointer is returned
*/
static di_errno_t test_private_data_can_recv_cb(struct di_can_frame_rx *frame)
{
bool *is_ok = static_cast<bool *>(di_can_frame_rx_get_private_data(frame));
*is_ok = true;
return DNOK;
}
static di_errno_t test_private_data_can_send_cb(const struct di_can_frame_tx *frame)
{
bool *is_ok = static_cast<bool *>(di_can_frame_tx_get_private_data(frame));
*is_ok = true;
return DNOK;
}
TEST(can_frame, private_data) {
bool is_ok = false;
di_can_callback_set_recv(&ctx, test_private_data_can_recv_cb);
di_can_callback_set_send(&ctx, test_private_data_can_send_cb);
di_can_set_private_data(&ctx, &is_ok);
di_can_lowlevel_recv(&ctx);
ASSERT_TRUE(is_ok);
is_ok = false;
struct di_can_frame_tx tx;
tx.canid = 0;
tx.ctx = &ctx;
di_can_lowlevel_send(&ctx, &tx);
ASSERT_TRUE(is_ok);
}