mirror of
https://github.com/logos-co/logos-protocol.git
synced 2026-08-27 20:11:07 +00:00
193 lines
5.3 KiB
C++
193 lines
5.3 KiB
C++
#include <gtest/gtest.h>
|
|||
|
|
|
||
|
|
#include "json_codec.h"
|
||
|
|
|
||
|
|
#include <cstdint>
|
||
|
|
|
||
|
|
using namespace logos::plain;
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
AnyMessage roundtrip(JsonCodec& codec, const AnyMessage& msg)
|
||
|
|
{
|
||
|
|
auto bytes = codec.encode(msg);
|
||
|
|
return codec.decode(messageTypeOf(msg), bytes.data(), bytes.size());
|
||
|
|
}
|
||
|
|
} // anonymous namespace
|
||
|
|
|
||
|
|
TEST(JsonCodecTest, CallMessage)
|
||
|
|
{
|
||
|
|
JsonCodec codec;
|
||
|
|
CallMessage c;
|
||
|
|
c.id = 7;
|
||
|
|
c.authToken = "tok";
|
||
|
|
c.object = "core_service";
|
||
|
|
c.method = "loadModule";
|
||
|
|
c.args.push_back(RpcValue{std::string{"chat"}});
|
||
|
|
c.args.push_back(RpcValue{int64_t{42}});
|
||
|
|
c.args.push_back(RpcValue{true});
|
||
|
|
|
||
|
|
auto dec = std::get<CallMessage>(roundtrip(codec, AnyMessage{c}));
|
||
|
|
EXPECT_EQ(dec.id, 7u);
|
||
|
|
EXPECT_EQ(dec.authToken, "tok");
|
||
|
|
EXPECT_EQ(dec.object, "core_service");
|
||
|
|
EXPECT_EQ(dec.method, "loadModule");
|
||
|
|
ASSERT_EQ(dec.args.size(), 3u);
|
||
|
|
EXPECT_EQ(dec.args[0].asString(), "chat");
|
||
|
|
EXPECT_EQ(dec.args[1].asInt(), 42);
|
||
|
|
EXPECT_EQ(dec.args[2].asBool(), true);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(JsonCodecTest, ResultOk)
|
||
|
|
{
|
||
|
|
JsonCodec codec;
|
||
|
|
ResultMessage r;
|
||
|
|
r.id = 99;
|
||
|
|
r.ok = true;
|
||
|
|
RpcMap m;
|
||
|
|
m.emplace("status", RpcValue{std::string{"ok"}});
|
||
|
|
m.emplace("count", RpcValue{int64_t{3}});
|
||
|
|
r.value = RpcValue{std::move(m)};
|
||
|
|
|
||
|
|
auto dec = std::get<ResultMessage>(roundtrip(codec, AnyMessage{r}));
|
||
|
|
EXPECT_EQ(dec.id, 99u);
|
||
|
|
EXPECT_TRUE(dec.ok);
|
||
|
|
ASSERT_TRUE(dec.value.isMap());
|
||
|
|
EXPECT_EQ(dec.value.asMap().at("status").asString(), "ok");
|
||
|
|
EXPECT_EQ(dec.value.asMap().at("count").asInt(), 3);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(JsonCodecTest, ResultError)
|
||
|
|
{
|
||
|
|
JsonCodec codec;
|
||
|
|
ResultMessage r;
|
||
|
|
r.id = 1;
|
||
|
|
r.ok = false;
|
||
|
|
r.err = "module not loaded";
|
||
|
|
r.errCode = "MODULE_NOT_LOADED";
|
||
|
|
|
||
|
|
auto dec = std::get<ResultMessage>(roundtrip(codec, AnyMessage{r}));
|
||
|
|
EXPECT_FALSE(dec.ok);
|
||
|
|
EXPECT_EQ(dec.err, "module not loaded");
|
||
|
|
EXPECT_EQ(dec.errCode, "MODULE_NOT_LOADED");
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(JsonCodecTest, EventWithNestedData)
|
||
|
|
{
|
||
|
|
JsonCodec codec;
|
||
|
|
EventMessage e;
|
||
|
|
e.object = "core_service";
|
||
|
|
e.eventName = "module_event";
|
||
|
|
RpcList inner;
|
||
|
|
inner.items.push_back(RpcValue{std::string{"nested"}});
|
||
|
|
inner.items.push_back(RpcValue{double{3.14}});
|
||
|
|
e.data.push_back(RpcValue{std::string{"testEvent"}});
|
||
|
|
e.data.push_back(RpcValue{std::move(inner)});
|
||
|
|
|
||
|
|
auto dec = std::get<EventMessage>(roundtrip(codec, AnyMessage{e}));
|
||
|
|
ASSERT_EQ(dec.data.size(), 2u);
|
||
|
|
EXPECT_EQ(dec.data[0].asString(), "testEvent");
|
||
|
|
ASSERT_TRUE(dec.data[1].isList());
|
||
|
|
const auto& il = dec.data[1].asList().items;
|
||
|
|
ASSERT_EQ(il.size(), 2u);
|
||
|
|
EXPECT_EQ(il[0].asString(), "nested");
|
||
|
|
EXPECT_DOUBLE_EQ(il[1].asDouble(), 3.14);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(JsonCodecTest, BytesRoundTrip)
|
||
|
|
{
|
||
|
|
JsonCodec codec;
|
||
|
|
CallMessage c;
|
||
|
|
c.id = 3;
|
||
|
|
c.object = "storage";
|
||
|
|
c.method = "write";
|
||
|
|
RpcBytes bytes;
|
||
|
|
bytes.data = {0x00, 0x01, 0xfe, 0xff, 0xff, 0x42};
|
||
|
|
c.args.push_back(RpcValue{std::move(bytes)});
|
||
|
|
|
||
|
|
auto dec = std::get<CallMessage>(roundtrip(codec, AnyMessage{c}));
|
||
|
|
ASSERT_EQ(dec.args.size(), 1u);
|
||
|
|
ASSERT_TRUE(dec.args[0].isBytes());
|
||
|
|
const auto& back = dec.args[0].asBytes().data;
|
||
|
|
std::vector<uint8_t> expect = {0x00, 0x01, 0xfe, 0xff, 0xff, 0x42};
|
||
|
|
EXPECT_EQ(back, expect);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(JsonCodecTest, SubscribeUnsubscribe)
|
||
|
|
{
|
||
|
|
JsonCodec codec;
|
||
|
|
|
||
|
|
SubscribeMessage s;
|
||
|
|
s.object = "x";
|
||
|
|
s.eventName = "e";
|
||
|
|
auto ds = std::get<SubscribeMessage>(roundtrip(codec, AnyMessage{s}));
|
||
|
|
EXPECT_EQ(ds.object, "x");
|
||
|
|
EXPECT_EQ(ds.eventName, "e");
|
||
|
|
|
||
|
|
UnsubscribeMessage u;
|
||
|
|
u.object = "x";
|
||
|
|
u.eventName = ""; // wildcard
|
||
|
|
auto du = std::get<UnsubscribeMessage>(roundtrip(codec, AnyMessage{u}));
|
||
|
|
EXPECT_EQ(du.object, "x");
|
||
|
|
EXPECT_EQ(du.eventName, "");
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(JsonCodecTest, TokenMessage)
|
||
|
|
{
|
||
|
|
JsonCodec codec;
|
||
|
|
TokenMessage t;
|
||
|
|
t.authToken = "ca";
|
||
|
|
t.moduleName = "chat";
|
||
|
|
t.token = "secret";
|
||
|
|
|
||
|
|
auto dec = std::get<TokenMessage>(roundtrip(codec, AnyMessage{t}));
|
||
|
|
EXPECT_EQ(dec.authToken, "ca");
|
||
|
|
EXPECT_EQ(dec.moduleName, "chat");
|
||
|
|
EXPECT_EQ(dec.token, "secret");
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(JsonCodecTest, MethodsRequestAndResult)
|
||
|
|
{
|
||
|
|
JsonCodec codec;
|
||
|
|
|
||
|
|
MethodsMessage q;
|
||
|
|
q.id = 5;
|
||
|
|
q.authToken = "t";
|
||
|
|
q.object = "obj";
|
||
|
|
auto dq = std::get<MethodsMessage>(roundtrip(codec, AnyMessage{q}));
|
||
|
|
EXPECT_EQ(dq.id, 5u);
|
||
|
|
EXPECT_EQ(dq.object, "obj");
|
||
|
|
|
||
|
|
MethodsResultMessage r;
|
||
|
|
r.id = 5;
|
||
|
|
r.ok = true;
|
||
|
|
MethodMetadata m;
|
||
|
|
m.name = "foo";
|
||
|
|
m.signature = "foo(QString)";
|
||
|
|
m.returnType = "int";
|
||
|
|
r.methods.push_back(std::move(m));
|
||
|
|
auto dr = std::get<MethodsResultMessage>(roundtrip(codec, AnyMessage{r}));
|
||
|
|
EXPECT_EQ(dr.id, 5u);
|
||
|
|
EXPECT_TRUE(dr.ok);
|
||
|
|
ASSERT_EQ(dr.methods.size(), 1u);
|
||
|
|
EXPECT_EQ(dr.methods[0].name, "foo");
|
||
|
|
EXPECT_EQ(dr.methods[0].signature, "foo(QString)");
|
||
|
|
EXPECT_EQ(dr.methods[0].returnType, "int");
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(JsonCodecTest, NullAndDoubleRoundTrip)
|
||
|
|
{
|
||
|
|
JsonCodec codec;
|
||
|
|
CallMessage c;
|
||
|
|
c.id = 1;
|
||
|
|
c.object = "o";
|
||
|
|
c.method = "m";
|
||
|
|
c.args.push_back(RpcValue{std::monostate{}});
|
||
|
|
c.args.push_back(RpcValue{double{-2.5}});
|
||
|
|
|
||
|
|
auto dec = std::get<CallMessage>(roundtrip(codec, AnyMessage{c}));
|
||
|
|
ASSERT_EQ(dec.args.size(), 2u);
|
||
|
|
EXPECT_TRUE(dec.args[0].isNull());
|
||
|
|
ASSERT_TRUE(dec.args[1].isDouble());
|
||
|
|
EXPECT_DOUBLE_EQ(dec.args[1].asDouble(), -2.5);
|
||
|
|
}
|