#include #include #include "tests/buffer.h" extern "C" { #include "rpc/lowlevel.c" } #define TEST_DI_RPC_LL_MSG_DATA_SIZE 64 DI_BUFFER_DECL(buf1, TEST_DI_RPC_LL_MSG_DATA_SIZE); /** * Verify the lowlevel decode returns with status ERR_MORE_DATA_NEEDED * Only a small piece of the header is written (magic-only) */ TEST(rpc_ll_decode, need_more_data) { struct di_rpc_ll_msg msg; /* Only write "DJR", 3 bytes */ di_buffer_init(&buf1, buf1_data, sizeof(buf1_data)); di_buffer_flush(&buf1); di_buffer_write_data(&buf1, DI_RPC_LL_MSG_HDR_MAGIC, DI_RPC_LL_MSG_HDR_MAGIC_SIZE); /* Check if buffer is correctly set */ EXPECT_EQ(buf1.used, DI_RPC_LL_MSG_HDR_MAGIC_SIZE); ASSERT_STREQ(DI_RPC_LL_MSG_HDR_MAGIC, (const char *)buf1.data); /* Decode needs more data, then only the header (3 bytes) */ EXPECT_EQ(DI_RPC_LL_MSG_STAT_ERR_MORE_DATA_NEEDED, di_rpc_ll_decode(&buf1, &msg)); EXPECT_EQ(DI_RPC_LL_MSG_STAT_ERR_MORE_DATA_NEEDED, msg.status); } /** * Verify the lowlevel decode returns with status ERR_MORE_DATA_NEEDED when there is a * header and no data payload. */ TEST(rpc_ll_decode, need_more_after_header) { const size_t msg_size = sizeof("DEADBEEFCAFEBABE"); struct di_rpc_ll_msg msg; /* Write "DJR" + DI_RPC_LL_MSG_TYPE_PLAIN + (DI_RPC_LL_MSG_HDR_SIZE + 16 bytes data payload) */ di_buffer_init(&buf1, buf1_data, sizeof(buf1_data)); di_buffer_flush(&buf1); di_rpc_ll_write_header(&buf1, DI_RPC_LL_MSG_TYPE_PLAIN, msg_size); /* Check if buffer is correctly set */ ASSERT_EQ(DI_RPC_LL_MSG_HDR_SIZE, buf1.used); /* Decode needs more data, then only the header */ ASSERT_EQ(DI_RPC_LL_MSG_STAT_ERR_MORE_DATA_NEEDED, di_rpc_ll_decode(&buf1, &msg)); ASSERT_EQ(DI_RPC_LL_MSG_STAT_ERR_MORE_DATA_NEEDED, msg.status); /* Write data */ ASSERT_EQ(DNOK, di_rpc_ll_write_data(&buf1, (const uint8_t *)"DEADBEEFCAFEBABE", msg_size)); /* Decode */ ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, di_rpc_ll_decode(&buf1, &msg)); ASSERT_EQ(DI_RPC_LL_MSG_TYPE_PLAIN, msg.type); ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, msg.status); ASSERT_EQ(msg_size, msg.size); ASSERT_STREQ("DEADBEEFCAFEBABE", (const char *)msg.data); } /** * Verify the lowlevel decode returns with status ERR_MORE_DATA_NEEDED when there is a * header and no data payload. */ TEST(rpc_ll_decode, reply_ok__mkay_payload) { struct di_rpc_ll_msg msg; di_buffer_init(&buf1, buf1_data, sizeof(buf1_data)); di_buffer_flush(&buf1); di_rpc_ll_write_header(&buf1, DI_RPC_LL_MSG_TYPE_REPLY, DI_RPC_LL_MSG_REPLY_MKAY_SIZE); ASSERT_EQ(DNOK, di_rpc_ll_write_data(&buf1, (const uint8_t *)DI_RPC_LL_MSG_REPLY_MKAY, DI_RPC_LL_MSG_REPLY_MKAY_SIZE)); /* Decode */ ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, di_rpc_ll_decode(&buf1, &msg)); ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, msg.status); ASSERT_EQ(DI_RPC_LL_MSG_TYPE_REPLY, msg.type); ASSERT_EQ(DI_RPC_LL_MSG_REPLY_OK, msg.reply); ASSERT_EQ(DI_RPC_LL_MSG_REPLY_MKAY_SIZE, msg.size); ASSERT_STREQ(DI_RPC_LL_MSG_REPLY_MKAY, (const char *)msg.data); } /** * Check if reply which matches the size of "WTF" payload. But "ABC" payload is read * it should set DI_RPC_LL_MSG_TYPE_REPLY and DI_RPC_LL_MSG_REPLY_UNKNOWN */ TEST(rpc_ll_decode, reply_unknown__abc_payload) { struct di_rpc_ll_msg msg; di_buffer_init(&buf1, buf1_data, sizeof(buf1_data)); di_buffer_flush(&buf1); di_rpc_ll_write_header(&buf1, DI_RPC_LL_MSG_TYPE_REPLY, DI_RPC_LL_MSG_REPLY_WTF_SIZE); ASSERT_EQ(DNOK, di_rpc_ll_write_data(&buf1, (const uint8_t *)"ABC", DI_RPC_LL_MSG_REPLY_WTF_SIZE)); /* Decode */ ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, di_rpc_ll_decode(&buf1, &msg)); ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, msg.status); ASSERT_EQ(DI_RPC_LL_MSG_TYPE_REPLY, msg.type); ASSERT_EQ(DI_RPC_LL_MSG_REPLY_UNKNOWN, msg.reply); ASSERT_EQ(DI_RPC_LL_MSG_REPLY_WTF_SIZE, msg.size); } /** * Verify the lowlevel decode returns with status ERR_MORE_DATA_NEEDED when there is a * header and no data payload. */ TEST(rpc_ll_decode, reply_error__wtf_payload) { struct di_rpc_ll_msg msg; di_buffer_init(&buf1, buf1_data, sizeof(buf1_data)); di_buffer_flush(&buf1); di_rpc_ll_write_header(&buf1, DI_RPC_LL_MSG_TYPE_REPLY, DI_RPC_LL_MSG_REPLY_WTF_SIZE); ASSERT_EQ(DNOK, di_rpc_ll_write_data(&buf1, (const uint8_t *)DI_RPC_LL_MSG_REPLY_WTF, DI_RPC_LL_MSG_REPLY_WTF_SIZE)); /* Decode */ ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, di_rpc_ll_decode(&buf1, &msg)); ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, msg.status); ASSERT_EQ(DI_RPC_LL_MSG_TYPE_REPLY, msg.type); ASSERT_EQ(DI_RPC_LL_MSG_REPLY_ERROR, msg.reply); ASSERT_EQ(DI_RPC_LL_MSG_REPLY_WTF_SIZE, msg.size); ASSERT_STREQ(DI_RPC_LL_MSG_REPLY_WTF, (const char *)msg.data); } /** * Verify the lowlevel decode returns with status ERR_MORE_DATA_NEEDED when there is a * header and no data payload. */ TEST(rpc_ll_decode, reply_unknown_more_data_needed__abc_payload) { const size_t data_size = sizeof("ABC"); struct di_rpc_ll_msg msg; di_buffer_init(&buf1, buf1_data, sizeof(buf1_data)); di_buffer_flush(&buf1); di_rpc_ll_write_header(&buf1, DI_RPC_LL_MSG_TYPE_REPLY, data_size); ASSERT_EQ(DNOK, di_rpc_ll_write_data(&buf1, (const uint8_t *)"ABC", data_size)); /* Decode */ ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, di_rpc_ll_decode(&buf1, &msg)); ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, msg.status); ASSERT_EQ(DI_RPC_LL_MSG_TYPE_REPLY, msg.type); ASSERT_EQ(DI_RPC_LL_MSG_REPLY_UNKNOWN, msg.reply); ASSERT_EQ(data_size, msg.size); ASSERT_STREQ("ABC", (const char *)msg.data); } /** * Test if unknown lowlevel message (where header is not found) is correctly handled */ TEST(rpc_ll_decode, unknown_msg) { struct di_rpc_ll_msg msg; const char llmsg[] = "\x12\x13\x14\x15\x16\x17\x18\x19\x20"; di_buffer_init(&buf1, buf1_data, sizeof(buf1_data)); di_buffer_memcpy(&buf1, 0, llmsg, sizeof(llmsg)); buf1.used = sizeof(llmsg); ASSERT_EQ(DI_RPC_LL_MSG_STAT_UNKNOWN, di_rpc_ll_decode(&buf1, &msg)); } /** * Test if invalid msg type (field in header) returns DI_RPC_LL_MSG_STAT_ERR_INVALID_TYPE */ TEST(rpc_ll_decode, unknown_msg_type) { struct di_rpc_ll_msg msg; const char llmsg[] = "DJR\x11\xff\xff\xde\xad\xbe\xef"; di_buffer_init(&buf1, buf1_data, sizeof(buf1_data)); di_buffer_memcpy(&buf1, 0, llmsg, sizeof(llmsg)); buf1.used = sizeof(llmsg); ASSERT_EQ(DI_RPC_LL_MSG_STAT_ERR_INVALID_TYPE, di_rpc_ll_decode(&buf1, &msg)); ASSERT_EQ(DI_RPC_LL_MSG_TYPE_UNKNOWN, msg.type); ASSERT_EQ(DI_RPC_LL_MSG_STAT_ERR_INVALID_TYPE, msg.status); }