/** * @file tests/can_callback.cpp * @brief brief * @date Feb 10, 2016 * @author jjacobs * @copyright 2016 Dual Inventive Technology Centre B.V. * * descr */ #include #include "tests/can.h" #include #include #include TEST_CAN_INIT_DECL static unsigned int cb_test_12345678_cnt = 0; static unsigned int cb_test_send_msg_cnt = 0; static void cb_test_12345678(const struct di_can_msg *msg, struct di_can_ctx *ctx) { (void)ctx; printf("%s: msg: %p\n", __func__, (void *)msg); cb_test_12345678_cnt++; } static void cb_test_send_msg(const struct di_can_msg *msg, struct di_can_ctx *ctx) { (void)msg; (void)ctx; //ASSERT_EQ(DNOK, di_can_send(&msg)); cb_test_send_msg_cnt++; } static struct di_can_callback callbacks[] = { { 0x12345678, cb_test_12345678 }, { 0xdeadbeef, cb_test_send_msg } }; TEST(can_callback, CANID) { uint32_t canid = DI_CAN_CALLBACK_CANID(DI_CAN_MSGTYPE_NET, DI_CAN_TRANSFERTYPE_PUBLISH, 0x7c1); ASSERT_EQ(0x17C1C000, canid); } /** Test if di_can_callback_init wont crash */ TEST(can_callback, init_invalid) { struct di_can_ctx _ctx; di_can_init(&_ctx); 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); ASSERT_EQ(DNE_PARAM, di_can_callback_init(NULL, NULL, 0)); ASSERT_EQ(DNE_PARAM, di_can_callback_init(NULL, callbacks, 0)); ASSERT_EQ(DNE_PARAM, di_can_callback_init(&_ctx, NULL, 0)); ASSERT_EQ(DNE_PARAM, di_can_callback_init(&_ctx, NULL, 1)); ASSERT_EQ(DNE_PARAM, di_can_callback_init(&_ctx, callbacks, 0)); } /** Test if invalid send and receive callbacks wont crash */ TEST(can_callback, set_send_recv_invalid) { can_ctx.send = test_can_send_callback; can_ctx.recv = test_can_recv_callback; // Check if invalid set doesn't overwrite existing callback pointer di_can_callback_set_send(NULL, NULL); di_can_callback_set_send(&can_ctx, NULL); ASSERT_EQ(&test_can_send_callback, can_ctx.send); // Reset callback to NULL, then set with function and check can_ctx.send = NULL; di_can_callback_set_send(&can_ctx, test_can_send_callback); ASSERT_EQ(&test_can_send_callback, can_ctx.send); // Check if invalid set doesn't overwrite existing callback pointer di_can_callback_set_recv(NULL, NULL); di_can_callback_set_recv(&can_ctx, NULL); ASSERT_EQ(&test_can_recv_callback, can_ctx.recv); // Reset callback to NULL, then set with function and check can_ctx.recv = NULL; di_can_callback_set_recv(&can_ctx, test_can_recv_callback); ASSERT_EQ(&test_can_recv_callback, can_ctx.recv); } /** Test if di_can_execute wont crash */ TEST(can_callback, execute_invalid) { struct di_can_ctx _ctx; di_can_init(&_ctx); 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_callback_execute(NULL, NULL); di_can_callback_execute(&_ctx, NULL); di_can_callback_init(&_ctx, callbacks, 0); di_can_callback_execute(&_ctx, NULL); } /** Test if initialisation sets the correct fields in the context */ TEST(can_callback, init_check) { di_can_callback_init(&can_ctx, callbacks, DI_ARRAY_SIZE(callbacks)); ASSERT_EQ(callbacks, can_ctx.msg.callback.begin); ASSERT_EQ(DI_ARRAY_SIZE(callbacks), can_ctx.msg.callback.size); } /** Execute callback for canid 0x12345678 on one single message */ TEST(can_callback, execute_single) { struct di_can_msg *msg; msg = di_can_msg_alloc_reassemble(&can_ctx); ASSERT_NE((void *)NULL, msg); msg->canid = 0x12345678; msg->size = 0; di_can_msg_set_ready(&msg); msg = di_can_recv(&can_ctx, DI_CAN_MSGTYPE_ANY); ASSERT_EQ(DNOK, di_can_callback_execute(&can_ctx, msg)); di_can_msg_free(&msg); ASSERT_EQ(1, cb_test_12345678_cnt); cb_test_12345678_cnt = 0; } /** Check if NULL callback will return the message back to the pool as ready */ TEST(can_callback, execute_null_cb_single) { struct di_can_msg *msg; msg = di_can_msg_alloc_reassemble(&can_ctx); ASSERT_NE((void *)NULL, msg); msg->canid = 0x12345678; msg->size = 0; di_can_msg_set_ready(&msg); // Set callback pointer to NULL callbacks[0].callback = NULL; msg = di_can_recv(&can_ctx, DI_CAN_MSGTYPE_ANY); ASSERT_EQ(DNE_OPNOTSUPP, di_can_callback_execute(&can_ctx, msg)); ASSERT_EQ(0, cb_test_12345678_cnt); // Restore callback pointer callbacks[0].callback = cb_test_12345678; ASSERT_EQ(DNOK, di_can_callback_execute(&can_ctx, msg)); di_can_msg_free(&msg); ASSERT_EQ(1, cb_test_12345678_cnt); cb_test_12345678_cnt = 0; } /** Execute callback for canid 0x12345678 on all messages in the pool */ TEST(can_callback, execute_multiple) { struct di_can_msg *msg; /* Deplete pool with only messages for callback 0x12345678 */ for (size_t n = 0; n < can_ctx.msg.pool.size; n++) { msg = di_can_msg_alloc_reassemble(&can_ctx); ASSERT_NE((void *)NULL, msg); msg->canid = 0x12345678; msg->size = 0; di_can_msg_set_ready(&msg); } for (size_t n = 0; n < can_ctx.msg.pool.size; n++) { msg = di_can_recv(&can_ctx, DI_CAN_MSGTYPE_ANY); ASSERT_EQ(DNOK, di_can_callback_execute(&can_ctx, msg)); di_can_msg_free(&msg); } ASSERT_EQ(can_ctx.msg.pool.size, cb_test_12345678_cnt); cb_test_12345678_cnt = 0; } /** Execute callback for canid 0xdeadbeef on one single message, * which will send the message. The callback runs di_can_send and the * stack will return the message to the pool. When the callback execution * has finished it is freed again because we have currently no signal of * the callback that it has consumed the message. */ TEST(can_callback, execute_single_reuse_msg) { struct di_can_msg *msg; msg = di_can_msg_alloc_reassemble(&can_ctx); ASSERT_NE((void *)NULL, msg); msg->canid = 0xdeadbeef; msg->size = 0; di_can_msg_set_ready(&msg); msg = di_can_recv(&can_ctx, DI_CAN_MSGTYPE_ANY); ASSERT_EQ(DNOK, di_can_callback_execute(&can_ctx, msg)); di_can_msg_free(&msg); ASSERT_EQ(1, cb_test_send_msg_cnt); cb_test_send_msg_cnt = 0; }