142 lines
4.8 KiB
C++
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));
|
|
}
|