647 lines
16 KiB
C++
647 lines
16 KiB
C++
/**
|
|
* @file tests/can_msg.cpp
|
|
* @brief brief
|
|
* @date Sep 30, 2015
|
|
* @author jjacobs
|
|
* @copyright 2015 Dual Inventive Technology Centre B.V.
|
|
*
|
|
* CAN Message buffer test
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "tests/can.h"
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <di/time.h>
|
|
#include <di/buffer.h>
|
|
#include <di/can/msg.h>
|
|
|
|
TEST(time, init) {
|
|
di_time_init();
|
|
}
|
|
|
|
TEST(can_msg_gc, all) {
|
|
}
|
|
|
|
#if 0
|
|
extern "C" {
|
|
#include "time.c"
|
|
#include "can/msg.c"
|
|
}
|
|
|
|
static struct di_can_ctx ctx;
|
|
DI_CAN_FRAME_RX_DECL_ARRAY(can_frames, DI_CAN_CFG_FRAME_SIZE);
|
|
DI_CAN_MSG_DECL_ARRAY(can_msg_list, DI_CAN_CFG_MSG_SIZE, DI_CAN_CFG_MSG_DATA_SIZE);
|
|
|
|
/**
|
|
* Put test message into the pool for garbage collection
|
|
* @todo we should move this into tests/can_msg_gc.cpp
|
|
*/
|
|
static void test_can_msg_gc_put(struct di_can_msg **msg) {
|
|
uint8_t _msg[8] = "1234567";
|
|
|
|
*msg = di_can_msg_alloc(&ctx);
|
|
if (*msg) {
|
|
ASSERT_NE((void *)NULL, (*msg)->buf);
|
|
di_buffer_memcpy((*msg)->buf, 0, _msg, sizeof(_msg));
|
|
}
|
|
|
|
ASSERT_NE((void *)NULL, *msg);
|
|
ASSERT_NE((void *)NULL, (*msg)->buf);
|
|
ASSERT_STREQ((const char *)_msg, (const char *)(*msg)->buf->data);
|
|
ASSERT_EQ(0U, (*msg)->timeout);
|
|
}
|
|
|
|
/**
|
|
* The time subsystem needs to be initialized in order to have
|
|
* the garbage collect feature work
|
|
*/
|
|
TEST(time, init) {
|
|
di_time_init();
|
|
}
|
|
|
|
/**
|
|
* Test if initializing array with null or invalid arguments doesn't crash
|
|
* 1. msg_list = NULL
|
|
* 2. buffer_list = NULL
|
|
* 3. msg_size != buffer_size
|
|
*/
|
|
TEST(can_msg, init_array_inval) {
|
|
di_can_msg_init_array(NULL, 0, NULL, 0);
|
|
di_can_msg_init_array(can_msg_list, DI_CAN_CFG_MSG_SIZE, NULL, DI_CAN_CFG_MSG_SIZE);
|
|
di_can_msg_init_array(can_msg_list, DI_CAN_CFG_MSG_SIZE, can_msg_list_buffers, DI_CAN_CFG_MSG_SIZE - 1);
|
|
}
|
|
|
|
/**
|
|
* Initialize the CAN stack msg subsystem invalid
|
|
*/
|
|
TEST(can_msg, init_null) {
|
|
struct di_can_msg *msg;
|
|
|
|
/* ctx = NULL */
|
|
di_can_msg_init(NULL, NULL, 0);
|
|
|
|
/* list = NULL, size = 0 */
|
|
di_can_msg_init(&ctx, NULL, 0);
|
|
ASSERT_EQ(0U, ctx.msg.pool.size);
|
|
ASSERT_EQ((void *)NULL, ctx.msg.pool.begin);
|
|
|
|
/* list != NULL, size = 0 */
|
|
di_can_msg_init(&ctx, (struct di_can_msg *)0x12345678, 0);
|
|
ASSERT_EQ(0U, ctx.msg.pool.size);
|
|
ASSERT_EQ((void *)NULL, ctx.msg.pool.begin);
|
|
|
|
/* list = NULL, size != 0 */
|
|
di_can_msg_init(&ctx, NULL, DI_CAN_CFG_MSG_SIZE);
|
|
ASSERT_EQ(0U, ctx.msg.pool.size);
|
|
ASSERT_EQ((void *)NULL, ctx.msg.pool.begin);
|
|
|
|
/* Check if the subsystem wont crash when not initialized */
|
|
msg = di_can_msg_alloc(&ctx);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
|
|
msg = di_can_msg_search(&ctx, 0x00000000);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
|
|
msg = di_can_msg_get(&ctx);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
|
|
msg = di_can_msg_get_ready(&ctx, DI_CAN_MSGTYPE_RAW);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
|
|
msg = di_can_msg_get_ready(&ctx, DI_CAN_MSGTYPE_RPC);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
}
|
|
|
|
/**
|
|
* Initialize the CAN stack msg subsystem
|
|
*/
|
|
TEST(can_msg, init) {
|
|
struct di_can_msg *msg;
|
|
|
|
/* Initialize the message array */
|
|
DI_CAN_MSG_INIT_ARRAY(can_msg_list, DI_CAN_CFG_MSG_SIZE, DI_CAN_CFG_MSG_DATA_SIZE);
|
|
|
|
for (size_t n = 0; n < DI_CAN_CFG_MSG_SIZE; n++) {
|
|
msg = &can_msg_list[n];
|
|
|
|
ASSERT_EQ(msg->state, DI_CAN_MSG_STATE_UNUSED);
|
|
ASSERT_EQ(0U, msg->canid);
|
|
ASSERT_EQ(DI_CAN_TIMEOUT_GC_SKIP, msg->timeout);
|
|
ASSERT_EQ((void *)NULL, msg->msg);
|
|
ASSERT_EQ(0U, msg->size);
|
|
ASSERT_EQ(0U, msg->size_written);
|
|
ASSERT_NE((void *)NULL, msg->buf);
|
|
ASSERT_EQ((void *)NULL, msg->private_data);
|
|
}
|
|
|
|
/* Initialize the msg subsystem */
|
|
di_can_msg_init(&ctx, can_msg_list, DI_CAN_CFG_MSG_SIZE);
|
|
ASSERT_EQ(DI_CAN_CFG_MSG_SIZE, ctx.msg.pool.size);
|
|
ASSERT_EQ(can_msg_list, ctx.msg.pool.begin);
|
|
}
|
|
|
|
/**
|
|
* Initialize again
|
|
*/
|
|
TEST(can_msg, init_again) {
|
|
/* Initialize again with invalid parameters and see if nothing changed */
|
|
di_can_msg_init(&ctx, NULL, 0);
|
|
ASSERT_EQ(DI_CAN_CFG_MSG_SIZE, ctx.msg.pool.size);
|
|
ASSERT_EQ(can_msg_list, ctx.msg.pool.begin);
|
|
|
|
/* Set msg.pool.begin = NULL, dont touch size */
|
|
ctx.msg.pool.begin = NULL;
|
|
|
|
di_can_msg_init(&ctx, can_msg_list, DI_CAN_CFG_MSG_SIZE);
|
|
ASSERT_EQ(DI_CAN_CFG_MSG_SIZE, ctx.msg.pool.size);
|
|
ASSERT_EQ(can_msg_list, ctx.msg.pool.begin);
|
|
|
|
/* Set msg.pool.size = 0, dont touch begin */
|
|
ctx.msg.pool.size = 0;
|
|
|
|
di_can_msg_init(&ctx, can_msg_list, DI_CAN_CFG_MSG_SIZE);
|
|
ASSERT_EQ(DI_CAN_CFG_MSG_SIZE, ctx.msg.pool.size);
|
|
ASSERT_EQ(can_msg_list, ctx.msg.pool.begin);
|
|
}
|
|
|
|
/**
|
|
* Check if reset of message will reset the correct fields
|
|
* it will not scrub msg->buf->data
|
|
*/
|
|
TEST(can_msg, _reset) {
|
|
const char *text = "Hello World!";
|
|
struct di_can_msg *msg;
|
|
|
|
msg = di_can_msg_alloc(&ctx);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
|
|
/* Set buffer of di_can_msg to "Hello World!" */
|
|
msg->size = 1234;
|
|
di_buffer_memcpy(msg->buf, 0, text, strlen(text) + 1);
|
|
|
|
_di_can_msg_reset(msg);
|
|
ASSERT_EQ(0U, msg->size);
|
|
ASSERT_STREQ(text, (const char *)msg->buf->data);
|
|
|
|
di_can_msg_free(&msg);
|
|
|
|
/* Get message from the pool, and check if still "Hello World!" is set */
|
|
msg = di_can_msg_alloc(&ctx);
|
|
ASSERT_EQ(0U, msg->size);
|
|
ASSERT_STREQ(text, (const char *)msg->buf->data);
|
|
}
|
|
|
|
/**
|
|
* Check if NULL message return will not crash
|
|
*/
|
|
TEST(can_msg, return_null) {
|
|
struct di_can_msg m;
|
|
struct di_can_msg *msg = NULL;
|
|
|
|
/* NULL */
|
|
di_can_msg_return_ready((struct di_can_msg **)NULL);
|
|
di_can_msg_return_unused((struct di_can_msg **)NULL);
|
|
|
|
/* msg = NULL */
|
|
di_can_msg_return_ready(&msg);
|
|
di_can_msg_return_unused(&msg);
|
|
|
|
/* msg.private_data = NULL */
|
|
m.buf = NULL;
|
|
_di_can_msg_reset(&m);
|
|
msg = &m;
|
|
|
|
di_can_msg_return_ready(&msg);
|
|
di_can_msg_return_unused(&msg);
|
|
}
|
|
|
|
/** Test if ctx = NULL argument is correctly handled */
|
|
TEST(can_msg, get_invalid) {
|
|
ASSERT_EQ((void *)NULL, di_can_msg_get_unused(NULL));
|
|
ASSERT_EQ((void *)NULL, di_can_msg_get_used(NULL, 0));
|
|
ASSERT_EQ((void *)NULL, di_can_msg_get_ready(NULL, 0));
|
|
}
|
|
|
|
/**
|
|
* Check internal function
|
|
* * Test if canid doesn't exist (canid 0x12345678)
|
|
* * Put message into used state (canid 0x12345679)
|
|
* * Check if canid exists/used
|
|
* * Return
|
|
* * Check if canid is not used
|
|
*/
|
|
TEST(can_msg, get_used) {
|
|
uint32_t canid = 0;
|
|
struct di_can_msg *msg;
|
|
|
|
DI_CAN_SET_MSGTYPE(canid, DI_CAN_MSGTYPE_RPC);
|
|
DI_CAN_SET_DATATYPE(canid, 1);
|
|
DI_CAN_SET_TRANSACTION(canid, 2);
|
|
|
|
/* Doesn't exist */
|
|
msg = di_can_msg_get_used(&ctx, canid);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
|
|
/* Get unused message and write canid */
|
|
msg = di_can_msg_get_unused(&ctx);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
|
|
msg->canid = canid;
|
|
|
|
/* Check if it is used */
|
|
msg = di_can_msg_get_used(&ctx, canid);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
ASSERT_EQ(canid, msg->canid);
|
|
|
|
/* Doesn't exist */
|
|
msg = di_can_msg_get_used(&ctx, 0xffffffff);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
|
|
/*
|
|
* Change on of the canid fields and check if it doesn't
|
|
* exist in the used state. This also test the correct
|
|
* functioning of the canid macros which are used by the
|
|
* framing layer.
|
|
*/
|
|
|
|
/* Change msgtype and check if it is not in the ctx */
|
|
DI_CAN_SET_MSGTYPE(canid, DI_CAN_MSGTYPE_RAW);
|
|
msg = di_can_msg_get_used(&ctx, canid);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
DI_CAN_SET_MSGTYPE(canid, DI_CAN_MSGTYPE_RPC);
|
|
|
|
/* Change datatype and check if is not in the ctx */
|
|
DI_CAN_SET_DATATYPE(canid, 2);
|
|
msg = di_can_msg_get_used(&ctx, canid);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
DI_CAN_SET_DATATYPE(canid, 1);
|
|
|
|
/* Change transaction and check if it is not in the ctx */
|
|
DI_CAN_SET_TRANSACTION(canid, 3);
|
|
msg = di_can_msg_get_used(&ctx, canid);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
DI_CAN_SET_TRANSACTION(canid, 2);
|
|
|
|
/* Return message */
|
|
msg = di_can_msg_get_used(&ctx, canid);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
ASSERT_EQ(canid, msg->canid);
|
|
di_can_msg_return_unused(&msg);
|
|
|
|
/* Check if removed from ctx */
|
|
msg = di_can_msg_get_used(&ctx, canid);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
|
|
/* Garbage collect all messages */
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_ALL);
|
|
}
|
|
|
|
/** Garbage collect where context is NULL */
|
|
TEST(can_msg, gc_null) {
|
|
di_can_msg_gc(NULL, DI_CAN_GC_SINGLE);
|
|
di_can_msg_gc(NULL, DI_CAN_GC_ALL);
|
|
}
|
|
|
|
/**
|
|
* Normal garbage collect test
|
|
* This uses the single garbage collect run
|
|
*/
|
|
TEST(can_msg, gc_single) {
|
|
struct di_can_msg *msg;
|
|
|
|
/* Test garbage collection on
|
|
m->timeout = 1000ms
|
|
uptime = 2000ms */
|
|
test_can_msg_gc_put(&msg);
|
|
|
|
msg->timeout = 1000;
|
|
_di_time_uptime = 2000;
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_SINGLE);
|
|
|
|
ASSERT_EQ(0U, msg->timeout);
|
|
|
|
/* Test garbage collection on
|
|
m->timeout = 1000ms
|
|
uptime = 1000ms */
|
|
test_can_msg_gc_put(&msg);
|
|
|
|
msg->timeout = 1000;
|
|
_di_time_uptime = 1000;
|
|
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_SINGLE);
|
|
|
|
ASSERT_EQ(0U, msg->timeout);
|
|
|
|
/* Test garbage collection skip on
|
|
m->timeout = 1000ms
|
|
uptime = 750ms */
|
|
test_can_msg_gc_put(&msg);
|
|
|
|
_di_time_uptime = 750;
|
|
msg->timeout = 1000;
|
|
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_SINGLE);
|
|
ASSERT_EQ(1000U, msg->timeout);
|
|
|
|
/* Now garbage collect previous message
|
|
*/
|
|
_di_time_uptime = 1000;
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_SINGLE);
|
|
msg = di_can_msg_get_used(&ctx, 0);
|
|
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
}
|
|
|
|
/**
|
|
* Garbage collection skip and immediate macro test
|
|
* * Put message
|
|
* * Set garbage collect to skip
|
|
* * Garbage collect
|
|
*/
|
|
TEST(can_msg, gc_timeout_skip_and_immediate) {
|
|
struct di_buffer *b;
|
|
struct di_can_msg *msg;
|
|
|
|
/* Test if message GC is skipped */
|
|
test_can_msg_gc_put(&msg);
|
|
|
|
msg->timeout = DI_CAN_TIMEOUT_GC_SKIP;
|
|
b = msg->buf;
|
|
|
|
_di_time_uptime = 1000;
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_ALL);
|
|
|
|
msg = di_can_msg_get_used(&ctx, 0);
|
|
|
|
ASSERT_NE((void *)NULL, msg);
|
|
ASSERT_EQ(b, msg->buf);
|
|
|
|
/* Test if message GC is immediate */
|
|
_di_time_uptime = 0;
|
|
msg->timeout = DI_CAN_TIMEOUT_GC_IMMEDIATE;
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_ALL);
|
|
|
|
msg = di_can_msg_get_used(&ctx, 0);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
}
|
|
|
|
/**
|
|
* Get unused messages after garbage collection
|
|
* * Deplete buffers
|
|
* * Set all buffers timeout to IMMEDIATE
|
|
* * Fetch all buffers
|
|
* * Return all buffers
|
|
*/
|
|
TEST(can_msg, gc_get_unused) {
|
|
struct di_can_msg *msg;
|
|
|
|
/* Deplete buffers */
|
|
for (size_t n = 0; n < DI_CAN_CFG_MSG_SIZE; n++) {
|
|
msg = di_can_msg_get_unused(&ctx);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
msg->timeout = DI_CAN_TIMEOUT_GC_IMMEDIATE;
|
|
}
|
|
|
|
/* Check depletion without gc by using internal function */
|
|
msg = _di_can_msg_get_unused(&ctx);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
|
|
/* Get single garbage collected msg */
|
|
msg = di_can_msg_get_unused(&ctx);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
msg->timeout = DI_CAN_TIMEOUT_GC_IMMEDIATE;
|
|
|
|
/* Let the garbage collect of all frames be performed */
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_ALL);
|
|
|
|
/* Check all free again, and return */
|
|
for (size_t n = 0; n < DI_CAN_CFG_MSG_SIZE; n++) {
|
|
msg = di_can_msg_get_unused(&ctx);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
di_can_msg_return_unused(&msg);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
}
|
|
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_ALL);
|
|
}
|
|
|
|
/**
|
|
* Test if ready msg is correctly stored
|
|
* * Get unused message
|
|
* * Return message in ready state
|
|
* * Get message from ready state
|
|
* * Return message as unused
|
|
*/
|
|
TEST(can_msg, return_get_ready) {
|
|
struct di_can_msg *msg;
|
|
|
|
msg = di_can_msg_get_unused(&ctx);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
|
|
msg->canid = 0xdeadbeef;
|
|
|
|
di_can_msg_return_ready(&msg);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
|
|
msg = di_can_msg_get_ready(&ctx, 0xdeadbeef);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
|
|
di_can_msg_return_unused(&msg);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
}
|
|
|
|
/**
|
|
* Bug: 2 frames should result in two messages
|
|
* the frame -> msg reassambler writes them into one di_can_msg because
|
|
* th.
|
|
*/
|
|
TEST(can_msg, frames_to_one_msg_bug) {
|
|
struct di_can_frame_rx *frame1;
|
|
struct di_can_frame_rx *frame2;
|
|
|
|
struct di_can_msg *msg1;
|
|
struct di_can_msg *msg2;
|
|
|
|
/* Reinitialize can stack by hand
|
|
* reused from tests/can.h TEST(can, init)
|
|
*/
|
|
test_can_dump_file = stderr;
|
|
di_time_init();
|
|
DI_CAN_MSG_INIT_ARRAY(can_msg_list, DI_CAN_CFG_MSG_SIZE, DI_CAN_CFG_MSG_DATA_SIZE);
|
|
ASSERT_EQ(0, di_can_init(&ctx, TEST_CAN_NODEID));
|
|
di_can_frame_init(&ctx, can_frames, DI_CAN_CFG_FRAME_SIZE);
|
|
di_can_msg_init(&ctx, can_msg_list, DI_CAN_CFG_MSG_SIZE);
|
|
|
|
/* di_can_rx_frame, check not NULL and frame1 != frame2 */
|
|
frame1 = di_can_frame_get_unused(&ctx);
|
|
frame2 = di_can_frame_get_unused(&ctx);
|
|
|
|
ASSERT_NE((void *)NULL, frame1);
|
|
ASSERT_NE((void *)NULL, frame2);
|
|
ASSERT_NE(frame1, frame2);
|
|
|
|
/* manual create, frame 2 (raw, pub, datatype 0x3ff, last frame, size 4, data "abc" */
|
|
DI_CAN_SET_MSGTYPE(frame1->canid, DI_CAN_MSGTYPE_RAW);
|
|
DI_CAN_SET_TRANSFERTYPE(frame1->canid, DI_CAN_TRANSFERTYPE_PUB);
|
|
DI_CAN_SET_DATATYPE(frame1->canid, 0x3ff);
|
|
DI_CAN_SET_LAST_FRAME(frame1->canid, DI_CAN_LAST_FRAME_TRUE);
|
|
|
|
snprintf((char *)frame1->buf, sizeof(frame1->buf), "abc");
|
|
frame1->size = 4;
|
|
di_can_frame_return_ready(frame1);
|
|
|
|
/* manual create, frame 2 (raw, pub, datatype 0x3ff, last frame, size 6, data "defgh" */
|
|
DI_CAN_SET_MSGTYPE(frame2->canid, DI_CAN_MSGTYPE_RAW);
|
|
DI_CAN_SET_TRANSFERTYPE(frame2->canid, DI_CAN_TRANSFERTYPE_PUB);
|
|
DI_CAN_SET_DATATYPE(frame2->canid, 0x3ff);
|
|
DI_CAN_SET_LAST_FRAME(frame2->canid, DI_CAN_LAST_FRAME_TRUE);
|
|
|
|
snprintf((char *)frame2->buf, sizeof(frame2->buf), "defgh");
|
|
frame2->size = 6;
|
|
di_can_frame_return_ready(frame2);
|
|
|
|
/* Reassemble frames into two di_can_msg */
|
|
ASSERT_EQ(0, di_can_reassemble(&ctx));
|
|
|
|
/* di_can_msg, check not NULL and msg1 != msg2 */
|
|
// TODO test also di_can_msg_get_ready ?
|
|
msg1 = di_can_msg_get_ready(&ctx, DI_CAN_MSGTYPE_RAW);
|
|
msg2 = di_can_msg_get_ready(&ctx, DI_CAN_MSGTYPE_RAW);
|
|
|
|
ASSERT_NE((void *)NULL, msg1);
|
|
ASSERT_NE((void *)NULL, msg2);
|
|
|
|
ASSERT_NE(msg1, msg2);
|
|
|
|
ASSERT_EQ(4U, msg1->size);
|
|
ASSERT_EQ(6U, msg2->size);
|
|
|
|
ASSERT_STREQ("abc", (const char *)msg1->msg);
|
|
ASSERT_STREQ("defgh", (const char *)msg2->msg);
|
|
}
|
|
|
|
/**
|
|
* Normal garbage collect test
|
|
* This uses the single garbage collect run
|
|
*/
|
|
TEST(can_msg, gc_single) {
|
|
struct di_can_msg *msg;
|
|
|
|
/* Test garbage collection on
|
|
m->timeout = 1000ms
|
|
uptime = 2000ms */
|
|
test_can_msg_gc_put(&msg);
|
|
|
|
msg->timeout = 1000;
|
|
_di_time_uptime = 2000;
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_SINGLE);
|
|
|
|
ASSERT_EQ(0U, msg->timeout);
|
|
|
|
/* Test garbage collection on
|
|
m->timeout = 1000ms
|
|
uptime = 1000ms */
|
|
test_can_msg_gc_put(&msg);
|
|
|
|
msg->timeout = 1000;
|
|
_di_time_uptime = 1000;
|
|
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_SINGLE);
|
|
|
|
ASSERT_EQ(0U, msg->timeout);
|
|
|
|
/* Test garbage collection skip on
|
|
m->timeout = 1000ms
|
|
uptime = 750ms */
|
|
test_can_msg_gc_put(&msg);
|
|
|
|
_di_time_uptime = 750;
|
|
msg->timeout = 1000;
|
|
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_SINGLE);
|
|
ASSERT_EQ(1000U, msg->timeout);
|
|
|
|
/* Now garbage collect previous message
|
|
*/
|
|
_di_time_uptime = 1000;
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_SINGLE);
|
|
msg = di_can_msg_get_used(&ctx, 0);
|
|
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
}
|
|
|
|
/**
|
|
* Garbage collection skip and immediate macro test
|
|
* * Put message
|
|
* * Set garbage collect to skip
|
|
* * Garbage collect
|
|
*/
|
|
TEST(can_msg, gc_timeout_skip_and_immediate) {
|
|
struct di_buffer *b;
|
|
struct di_can_msg *msg;
|
|
|
|
/* Test if message GC is skipped */
|
|
test_can_msg_gc_put(&msg);
|
|
|
|
msg->timeout = DI_CAN_TIMEOUT_GC_SKIP;
|
|
b = msg->buf;
|
|
|
|
_di_time_uptime = 1000;
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_ALL);
|
|
|
|
msg = di_can_msg_get_used(&ctx, 0);
|
|
|
|
ASSERT_NE((void *)NULL, msg);
|
|
ASSERT_EQ(b, msg->buf);
|
|
|
|
/* Test if message GC is immediate */
|
|
_di_time_uptime = 0;
|
|
msg->timeout = DI_CAN_TIMEOUT_GC_IMMEDIATE;
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_ALL);
|
|
|
|
msg = di_can_msg_get_used(&ctx, 0);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
}
|
|
|
|
/**
|
|
* Get unused messages after garbage collection
|
|
* * Deplete buffers
|
|
* * Set all buffers timeout to IMMEDIATE
|
|
* * Fetch all buffers
|
|
* * Return all buffers
|
|
*/
|
|
TEST(can_msg, gc_get_unused) {
|
|
struct di_can_msg *msg;
|
|
|
|
/* Deplete buffers */
|
|
for (size_t n = 0; n < DI_CAN_CFG_MSG_SIZE; n++) {
|
|
msg = di_can_msg_get_unused(&ctx);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
msg->timeout = DI_CAN_TIMEOUT_GC_IMMEDIATE;
|
|
}
|
|
|
|
/* Check depletion without gc by using internal function */
|
|
msg = _di_can_msg_get_unused(&ctx);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
|
|
/* Get single garbage collected msg */
|
|
msg = di_can_msg_get_unused(&ctx);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
msg->timeout = DI_CAN_TIMEOUT_GC_IMMEDIATE;
|
|
|
|
/* Let the garbage collect of all frames be performed */
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_ALL);
|
|
|
|
/* Check all free again, and return */
|
|
for (size_t n = 0; n < DI_CAN_CFG_MSG_SIZE; n++) {
|
|
msg = di_can_msg_get_unused(&ctx);
|
|
ASSERT_NE((void *)NULL, msg);
|
|
di_can_msg_return_unused(&msg);
|
|
ASSERT_EQ((void *)NULL, msg);
|
|
}
|
|
|
|
di_can_msg_gc(&ctx, DI_CAN_GC_ALL);
|
|
}
|
|
#endif
|