/** * @file tests/can_msg.cpp * @brief CAN message states unit test * @date Jan 21, 2016 * @author jjacobs * @copyright 2016 Dual Inventive Technology Centre B.V. * * CAN messsage state unit test */ #include #include "tests/can.h" #include #include #include #include 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); /** * Initialize the CAN stack msg subsystem */ TEST(can_msg_state, init) { di_can_init(&ctx); di_can_frame_init(&ctx, can_frames, DI_CAN_CFG_FRAME_SIZE); DI_CAN_MSG_INIT_ARRAY(&ctx, can_msg_list, DI_CAN_CFG_MSG_SIZE, DI_CAN_CFG_MSG_DATA_SIZE); di_can_msg_init(&ctx, can_msg_list, DI_CAN_CFG_MSG_SIZE); } /** Check if correct state and timeout is set after initialisation loop directly over the pool */ TEST(can_msg_state, after_init) { di_array_foreach(ctx.msg.pool, msg, struct di_can_msg) { ASSERT_EQ(DI_CAN_MSG_STATE_UNUSED, msg->state); ASSERT_EQ(DI_CAN_TIMEOUT_GC_SKIP, msg->timeout); } } /** Get all unused messages with internal function which changes state UNUSED -> REASSEMBLE */ TEST(can_msg_state, di_can_msg_get) { struct di_can_msg *msg; for (size_t i = 0; i < DI_CAN_CFG_MSG_SIZE; i++) { // Get message UNUSED -> REASSEMBLE msg = di_can_msg_alloc_reassemble(&ctx); ASSERT_NE((void *)NULL, msg); ASSERT_EQ(DI_CAN_MSG_STATE_REASSEMBLE, msg->state); // We set the message timeout when it is being reassembled, // this due to when the peer node resets and the message is never completed // then the garbage collector will happily clean it ASSERT_EQ(ctx.msg.timeout, msg->timeout); // Mark msg to be garbage collected on next run because we lose the msg pointer on // next itteration msg->timeout = DI_CAN_TIMEOUT_GC_IMMEDIATE; } di_can_msg_gc(&ctx, DI_CAN_GC_ALL); } /** Mark all messages from REASSEMBLE -> READY -> APPLICATION -> DIRTY (no timeout) */ TEST(can_msg_state, di_can_msg_set_get_ready_type) { struct di_can_msg *msg; // UNUSED -> REASSEMBLE -> READY for (size_t i = 0; i < DI_CAN_CFG_MSG_SIZE; i++) { msg = di_can_msg_alloc_reassemble(&ctx); ASSERT_NE((void *)NULL, msg); ASSERT_EQ(DI_CAN_MSG_STATE_REASSEMBLE, msg->state); // We set the message timeout when it is being reassembled, // this due to when the peer node resets and the message is never completed // then the garbage collector will happily clean it ASSERT_EQ(ctx.msg.timeout, msg->timeout); di_can_msg_set_ready(&msg); ASSERT_EQ((void *)NULL, msg); } // READY -> APPLICATION -> DIRTY for (size_t i = 0; i < DI_CAN_CFG_MSG_SIZE; i++) { // We know the canid is set to zero so the msgtype is == 0 (RAW) msg = di_can_msg_get_ready_type(&ctx, DI_CAN_MSGTYPE_RAW); ASSERT_NE((void *)NULL, msg); ASSERT_EQ(DI_CAN_MSG_STATE_APPLICATION, msg->state); ASSERT_EQ(DI_CAN_TIMEOUT_GC_SKIP, msg->timeout); di_can_msg_free(&msg); ASSERT_EQ((void *)NULL, msg); } // DIRTY -> UNUSED di_can_msg_gc(&ctx, DI_CAN_GC_ALL); } /** Application allocated UNUSED -> APPLICATION -> DIRTY */ TEST(can_msg_state, di_can_msg_alloc_free) { struct di_can_msg *msg; for (size_t i = 0; i < DI_CAN_CFG_MSG_SIZE; i++) { msg = di_can_msg_alloc(&ctx); ASSERT_NE((void *)NULL, msg); ASSERT_EQ(DI_CAN_MSG_STATE_APPLICATION, msg->state); ASSERT_EQ(DI_CAN_TIMEOUT_GC_SKIP, msg->timeout); di_can_msg_free(&msg); ASSERT_EQ((void *)NULL, msg); } di_can_msg_gc(&ctx, DI_CAN_GC_ALL); }