213 lines
6.0 KiB
C++
213 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.uid = 10003;
|
|
gps.fix = false;
|
|
gps.siv = 2;
|
|
di_snprintf(gps.hdop, sizeof(gps.hdop), "1.8");
|
|
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[] = "awesome-device-label";
|
|
const char v[] = "1.2.3+abcdefg+20160224";
|
|
|
|
d.version = NULL; // We let libdi generate the version for us :-)
|
|
d.revision = 123;
|
|
d.type = l;
|
|
|
|
di_rpc_serialize_item(writer->get(), &d);
|
|
|
|
// Here we supply the version ourselves
|
|
writer = TEST_RPC_SERIALIZE_WRITER;
|
|
d.version = v;
|
|
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);
|
|
}
|