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

158 lines
4.0 KiB
C++

/**
* @file tests/can_msg_gc.cpp
* @date Mar 13, 2019
* @copyright 2019 Dual Inventive Technology Centre B.V.
*
* CAN Message buffer test
*/
#include <cstdio>
#include <di/device/uid.h>
#include "fixtures/CANTest.hpp"
extern "C" {
#include "can.c"
#include "time.c"
#include "can/msg.c"
}
/**
* Put test message into the pool for garbage collection
*/
static void test_can_msg_gc_put(DI_CAN *t, struct di_can_ctx *ctx, struct di_can_msg **msg) {
uint8_t _msg[] = "0123456789";
*msg = di_can_msg_alloc_reassemble(ctx);
if (*msg) {
ASSERT_NE((void *)NULL, (*msg)->buf);
di_buffer_memcpy((*msg)->buf, 0, _msg, sizeof(_msg));
}
DI_CAN_SET_MSGTYPE((*msg)->canid, DI_CAN_MSGTYPE_RAW);
ASSERT_NE(nullptr, *msg);
ASSERT_NE(nullptr, (*msg)->buf);
ASSERT_STREQ((const char *)_msg, (const char *)(*msg)->buf->data);
ASSERT_EQ(t->getCurrentMsgTimeout(), (*msg)->timeout);
}
/**
* Normal garbage collect test
* This uses the single garbage collect run
*/
TEST_F(DI_CAN, gc_single) {
struct di_can_msg *msg;
/* Test garbage collection on
m->timeout = 1000ms
uptime = 2000ms */
test_can_msg_gc_put(this, &_ctx, &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(this, &_ctx, &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(this, &_ctx, &msg);
_di_time_uptime = 750;
di_can_msg_gc(&_ctx, DI_CAN_GC_SINGLE);
ASSERT_EQ(1500, 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_ready_type(&_ctx, DI_CAN_MSGTYPE_RAW);
ASSERT_EQ(nullptr, msg);
}
/**
* Test if the di_can_msg_alloc_reassemble executed the DI_CAN_GC_SINGLE
* when the message pool is depleted.
*/
TEST_F(DI_CAN, gc_single_alloc_reassemble_internal) {
struct di_can_msg *msg;
// Check if the context message timeout is set
ASSERT_EQ(DI_CAN_CFG_MSG_TIMEOUT, _ctx.msg.timeout);
// Deplete the pool
for (size_t n = 0; n < _ctx.msg.pool.size; n++) {
msg = di_can_msg_alloc_reassemble(&_ctx);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(getCurrentMsgTimeout(), msg->timeout);
}
// Check if the pool is depleted by trying to alloc with gc
ASSERT_EQ(nullptr, di_can_msg_alloc_reassemble(&_ctx));
// Run GC single and check if the pool messages are stil in REASSEMBLE state
_di_can_msg_gc(&_ctx, DI_CAN_GC_ALL);
ASSERT_EQ(nullptr, di_can_msg_alloc_reassemble(&_ctx));
// Move time forward so all allocated REASSEMBLE state messages expire
_di_time_uptime = getCurrentMsgTimeout();
msg = di_can_msg_alloc_reassemble(&_ctx);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(getCurrentMsgTimeout(), msg->timeout);
}
/**
* Garbage collection skip and immediate macro test
* * Put message
* * Set garbage collect to skip
* * Garbage collect
*/
TEST_F(DI_CAN, 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(this, &_ctx, &msg);
msg->timeout = DI_CAN_TIMEOUT_GC_SKIP;
msg->state = DI_CAN_MSG_STATE_READY;
b = msg->buf;
_di_time_uptime = 1000;
di_can_msg_gc(&_ctx, DI_CAN_GC_ALL);
msg = di_can_msg_get_ready_type(&_ctx, DI_CAN_MSGTYPE_RAW);
ASSERT_NE(nullptr, msg);
ASSERT_EQ(b, msg->buf);
// Message state after get is application so the GC will not touch it
ASSERT_EQ(DI_CAN_MSG_STATE_APPLICATION, msg->state);
msg->state = DI_CAN_MSG_STATE_READY;
// Test if message GC is immediate
_di_time_uptime = 0;
DI_CAN_SET_MSGTYPE(msg->canid, DI_CAN_MSGTYPE_RAW);
msg->timeout = DI_CAN_TIMEOUT_GC_IMMEDIATE;
msg = di_can_msg_get_ready_type(&_ctx, DI_CAN_MSGTYPE_RAW);
ASSERT_NE(nullptr, msg);
di_can_msg_gc(&_ctx, DI_CAN_GC_ALL);
msg = di_can_msg_get_ready_type(&_ctx, DI_CAN_MSGTYPE_RAW);
ASSERT_EQ(nullptr, msg);
}