/** * @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 #include 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(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(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); }