src.dualinventive.com/dinet/sec-multi-proxy/libdi/tests/rpc_serialize.cpp

222 lines
6.0 KiB
C++

#include <string>
#include <memory>
#include <di/stdio.h>
#include <di/rpc.h>
#include <di/device.h>
#include <di/device/uid.h>
#include <di/time.h>
#include <gtest/gtest.h>
#include "tests/rpc_serialize.h"
extern "C" {
#include "rpc/serialize.c"
}
/** Used because serialize message header loads di_time_get_stamp */
TEST(time, init)
{
di_time_init();
}
static void rpc_serialize_dump_mem(const uint8_t *buf, size_t n)
{
for (size_t _n = 0; _n < n; _n++)
printf("%02x ", buf[_n]);
printf("\n");
}
/** Test serialisation of composite data value */
TEST(rpc, serialize_data_value)
{
int ret;
mpack_writer_t w;
uint8_t data[128];
/** @note we should test here how mpack behaves when writing unsigned zeros?
* This really depends on how mpack is configured because it can pack u64 zero write into a smaller stream.
* And it trades CPU cycles for saved bandwidth
*/
struct {
enum di_rpc_data_field field;
union di_rpc_data_value value;
const char *expect; // This is raw messagepack emitted by mpack library
} tv[] = {
{ DI_RPC_DATA_FIELD_BOOL, { false }, "\xa1\x55\xc2" },
{ DI_RPC_DATA_FIELD_BOOL, { false }, "\xa1\x55\xc3" },
{ DI_RPC_DATA_FIELD_INT8, { false }, "\xa1\x55\xd0\x80" },
{ DI_RPC_DATA_FIELD_INT8, { false }, "\xa1\x55\x7f" },
{ DI_RPC_DATA_FIELD_INT16, { false }, "\xa1\x55\xd1\x80\x00" },
{ DI_RPC_DATA_FIELD_INT16, { false }, "\xa1\x55\xcd\x7f\xff" },
{ DI_RPC_DATA_FIELD_INT32, { false }, "\xa1\x55\xd2\x80\x00\x00\x00" },
{ DI_RPC_DATA_FIELD_INT32, { false }, "\xa1\x55\xce\x7f\xff\xff\xff" },
{ DI_RPC_DATA_FIELD_INT64, { false }, "\xa1\x55\xd3\x80\x00\x00\x00\x00\x00\x00\x00" },
{ DI_RPC_DATA_FIELD_INT64, { false }, "\xa1\x55\xcf\x7f\xff\xff\xff\xff\xff\xff\xff" },
{ DI_RPC_DATA_FIELD_UINT8, { false }, "\xa1\x55\xcc\xff" },
{ DI_RPC_DATA_FIELD_UINT16, { false }, "\xa1\x55\xcd\xff\xff" },
{ DI_RPC_DATA_FIELD_UINT32, { false }, "\xa1\x55\xce\xff\xff\xff\xff" },
{ DI_RPC_DATA_FIELD_UINT64, { false }, "\xa1\x55\xcf\xff\xff\xff\xff\xff\xff\xff\xff" }
};
/* NOTE: this is because GNU C++ compiler sucks and will emit (clang works):
sorry, unimplemented: non-trivial designated initializers not supported
*/
/* Boolean */
tv[0].value.b = false;
tv[1].value.b = true;
/* Signed int */
tv[2].value.s8 = INT8_MIN;
tv[3].value.s8 = INT8_MAX;
tv[4].value.s16 = INT16_MIN;
tv[5].value.s16 = INT16_MAX;
tv[6].value.s32 = INT32_MIN;
tv[7].value.s32 = INT32_MAX;
tv[8].value.s64 = INT64_MIN;
tv[9].value.s64 = INT64_MAX;
/* Unsigned int */
tv[10].value.u8 = UINT8_MAX;
tv[11].value.u16 = UINT16_MAX;
tv[12].value.u32 = UINT32_MAX;
tv[13].value.u64 = UINT64_MAX;
for (size_t n = 0; n < sizeof(tv)/(sizeof(tv[0])); n++) {
mpack_writer_init(&w, (char *)data, sizeof(data));
di_rpc_serialize_data_value(&w, (const char *)"U", tv[n].field, tv[n].value);
ret = memcmp(tv[n].expect, data, mpack_writer_buffer_used(&w));
if (ret != 0) {
printf("[tv: %2d] expect (msgpack): ", (int)n + 1);
rpc_serialize_dump_mem((const uint8_t *)tv[n].expect, strlen(tv[n].expect));
printf(" got (msgpack): ");
rpc_serialize_dump_mem(data, mpack_writer_buffer_used(&w));
}
EXPECT_EQ(ret, 0);
}
}
/** "notify:info", "bool" */
TEST(rpc, serialize_rpc_notify_info_bool)
{
auto writer = TEST_RPC_SERIALIZE_WRITER;
struct di_rpc_info info;
info.uid = 1;
info.label = "test-rpc-serialize-bool";
info.data_type = DI_RPC_DATA_TYPE_BOOL;
di_rpc_serialize_item(writer->get(), &info);
}
/** "notify:info", type "number" */
TEST(rpc, serialize_rpc_notify_info_number)
{
auto writer = TEST_RPC_SERIALIZE_WRITER;
struct di_rpc_info info;
info.uid = 2;
info.label = "test-rpc-serialize-number";
info.data_type = DI_RPC_DATA_TYPE_NUMBER;
di_rpc_serialize_item(writer->get(), &info);
}
/** "sensor:info", type "enum" */
TEST(rpc, serialize_rpc_sensor_info_number)
{
struct di_rpc_enum elist[] = {
{ "empty", 0 },
{ "crit", 1 },
{ "low", 2 },
{ "half", 3 },
{ "full", 4 }
};
auto writer = TEST_RPC_SERIALIZE_WRITER;
struct di_rpc_info info;
info.uid = 3;
info.label = "test-rpc-serialize-enum";
info.data_type = DI_RPC_DATA_TYPE_ENUM;
info.enumerator.size = DI_ARRAY_SIZE(elist);
info.enumerator.begin = elist;
di_rpc_serialize_item(writer->get(), &info);
}
/* "sensor:data", type "gps" */
TEST(rpc, serialize_sensor_data_gps)
{
auto writer = TEST_RPC_SERIALIZE_WRITER;
struct di_rpc_sensor_data_gps gps;
memset(&gps, 0, sizeof(gps));
gps.hdop = 1.8f;
gps.latitude = 0.1234;
gps.longitude = 0.5678;
di_rpc_serialize_result(writer->get(), &gps);
}
/* "device:info" */
TEST(rpc, serialize_device_info)
{
auto writer = TEST_RPC_SERIALIZE_WRITER;
struct di_rpc_device_info d;
const char l[] = "zkl-3000-rc";
struct di_rpc_device_info_version version[1];
version[0].key = "fw-main";
version[0].value = "v1.0.2";
d.version = version;
d.versionn = 1;
d.type = l;
di_rpc_serialize_item(writer->get(), &d);
}
/* "config:info" */
TEST(rpc, serialize_config_info_token)
{
auto writer = TEST_RPC_SERIALIZE_WRITER;
struct di_rpc_config_info info;
info.uid = 1;
info.label = "token";
info.data_type = DI_RPC_DATA_TYPE_NUMBER;
info.field = DI_RPC_DATA_FIELD_UINT32;
info.value.u32 = 0;
di_rpc_serialize_item(writer->get(), &info);
}
/* Single struct di_error */
TEST(rpc, serialize_error)
{
auto writer = TEST_RPC_SERIALIZE_WRITER;
struct di_rpc_error err;
err.code = DNE_FIRMWARE_TILT;
err.first = 1000;
err.last = 2000;
err.count = 10;
di_rpc_serialize_item(writer->get(), &err);
}
/** Test serialize of a string array result */
TEST(rpc, serialize_string_array)
{
const char *strs[] = {
"string1",
"string2",
"string3"
};
auto writer = TEST_RPC_SERIALIZE_WRITER;
di_rpc_serialize_result_string_array(writer->get(), strs, DI_ARRAY_SIZE(strs));
}