src.dualinventive.com/dinet/libdi/tests/rpc_lowlevel.cpp

142 lines
4.8 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);
DI_BUFFER_DECL(buf2, TEST_DI_RPC_LL_MSG_DATA_SIZE);
/**
* Verify if memory copy of remaining data from di_rpc_ll_msg into di_buffer works
* 1. Write two messages into two di_buffers
* 2. Concat second message into buffer of first message
* 3. Decode buffer, verify first message is correct and the buffer is flagged to have data remaining
* 4. Copy remaining data from di_rpc_ll_msg into di_buffer
* 5. Decode second message from di_buffer
* 6. Verify message is correctly decoded
*/
TEST(rpc_ll_memcpy_remaining, two_packets_single_buf)
{
struct di_rpc_ll_msg msg;
const size_t msg1_size = sizeof("AAAA");
const size_t msg2_size = sizeof("BBBBBBBB");
/* Initialize buffer for msg1 */
di_buffer_init(&buf1, buf1_data, sizeof(buf1_data));
di_buffer_flush(&buf1);
/* Initialize buffer for msg2 */
di_buffer_init(&buf2, buf2_data, sizeof(buf2_data));
di_buffer_flush(&buf2);
/* Write first message */
di_rpc_ll_write_header(&buf1, DI_RPC_LL_MSG_TYPE_PLAIN, msg1_size);
ASSERT_EQ(DNOK, di_rpc_ll_write_data(&buf1,
(const uint8_t *)"AAAA", msg1_size));
/* Write second message */
di_rpc_ll_write_header(&buf2, DI_RPC_LL_MSG_TYPE_REPLY, msg2_size);
ASSERT_EQ(DNOK, di_rpc_ll_write_data(&buf2,
(const uint8_t *)"BBBBBBBB", msg2_size));
/* Concat msg2 buffer to msg1 buffer */
ASSERT_EQ(DNOK, di_buffer_append(&buf1, &buf2));
di_buffer_flush(&buf2);
/* Decode message 1 */
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_HDR_SIZE + msg2_size, msg.remaining); /* Remaining bytes HEADER + msg2_size */
ASSERT_EQ(DI_RPC_LL_MSG_TYPE_PLAIN, msg.type);
ASSERT_EQ(msg1_size, msg.size);
ASSERT_STREQ("AAAA", (const char *)msg.data);
/* Memcpy remaining message 2 to start of empty buf1 */
ASSERT_EQ(DNOK, di_rpc_ll_memcpy_remaining(&buf2, &msg));
/* Decode message 2 */
ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, di_rpc_ll_decode(&buf2, &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(msg2_size, msg.size);
ASSERT_STREQ("BBBBBBBB", (const char *)msg.data);
}
/**
* Verify the memory copy operation is not supported if there is no data remaining after decode
*/
TEST(rpc_ll_memcpy, DNE_OPNOTSUPP)
{
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));
ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, di_rpc_ll_decode(&buf1, &msg));
ASSERT_EQ(DNE_OPNOTSUPP, di_rpc_ll_memcpy_remaining(&buf2, &msg));
}
/**
* Verify the memory copy operation will not copy to dst when the buffer is to small
*/
TEST(rpc_ll_memcpy, DNE_NOMEM)
{
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));
test_buffer_dump(&buf1);
ASSERT_EQ(DNOK, di_buffer_append(&buf1, &buf1));
ASSERT_EQ(DI_RPC_LL_MSG_STAT_OK, di_rpc_ll_decode(&buf1, &msg));
/* Fake buf2 is 8 bytes */
buf2.size = 8;
ASSERT_EQ(DNE_NOMEM, di_rpc_ll_memcpy_remaining(&buf2, &msg));
buf2.size = TEST_DI_RPC_LL_MSG_DATA_SIZE;
}
/**
* Check if writing a lowlevel header into a to small buffer (DI_RPC_LL_MSG_HDR_SIZE - 1)
* results in a DNE_NOMEM.
*/
TEST(rpc_ll_write_header, out_of_memory)
{
di_buffer_init(&buf1, buf1_data, sizeof(buf1_data));
di_buffer_flush(&buf1);
/* Check buf1.size < DI_RPC_LL_MSG_TYPE_REPLY */
buf1.size = DI_RPC_LL_MSG_HDR_SIZE - 1;
ASSERT_EQ(DNE_NOMEM, di_rpc_ll_write_header(&buf1, DI_RPC_LL_MSG_TYPE_TIME, 0));
/* Check buf1.size < (DI_RPC_LL_MSG_HDR_SIZE + len)
tries to write 5 bytes as payload in the header
but the buffer only fits 4 bytes payload
*/
buf1.size = DI_RPC_LL_MSG_HDR_SIZE + 4;
ASSERT_EQ(DNE_NOMEM, di_rpc_ll_write_header(&buf1, DI_RPC_LL_MSG_TYPE_TIME, 5));
}
/**
* Verify if writing more than 2^16-1 is not allowed and results in DNE_NOMEM
* This because the lowlevel messages are limited to uint16_t
* @note The assumption is made first the lengths are checked, then the src and dst pointers
*/
TEST(rpc_ll, DNE_NOMEM) {
ASSERT_EQ(DNE_NOMEM, di_rpc_ll_write_header(NULL, DI_RPC_LL_MSG_TYPE_PLAIN, UINT16_MAX + 1));
ASSERT_EQ(DNE_NOMEM, di_rpc_ll_write_data(NULL, NULL, UINT16_MAX + 1));
}