src.dualinventive.com/fw/dncm/libdi/tests/rpc_lowlevel_decode.cpp

197 lines
6.3 KiB
C++

#include <di/rpc/lowlevel.h>
#include <gtest/gtest.h>
#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);
}