bb052be002
Reviewers: teon.banek Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1852
336 lines
12 KiB
C++
336 lines
12 KiB
C++
#include <experimental/optional>
|
|
#include <sstream>
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
#include "capnp/message.h"
|
|
#include "rpc/serialization.hpp"
|
|
|
|
using std::experimental::optional;
|
|
using std::string_literals::operator""s;
|
|
|
|
void CheckOptionalInt(const std::experimental::optional<int> &x1) {
|
|
::capnp::MallocMessageBuilder message;
|
|
std::experimental::optional<int> y1;
|
|
{
|
|
auto builder =
|
|
message.initRoot<utils::capnp::Optional<utils::capnp::BoxInt32>>();
|
|
auto save = [](utils::capnp::BoxInt32::Builder *builder, int value) {
|
|
builder->setValue(value);
|
|
};
|
|
utils::SaveOptional<utils::capnp::BoxInt32, int>(x1, &builder, save);
|
|
}
|
|
|
|
{
|
|
auto reader =
|
|
message.getRoot<utils::capnp::Optional<utils::capnp::BoxInt32>>();
|
|
auto load = [](const utils::capnp::BoxInt32::Reader &reader) -> int {
|
|
return reader.getValue();
|
|
};
|
|
y1 = utils::LoadOptional<utils::capnp::BoxInt32, int>(reader, load);
|
|
}
|
|
|
|
EXPECT_EQ(x1, y1);
|
|
}
|
|
|
|
TEST(Serialization, CapnpOptional) {
|
|
std::experimental::optional<int> x1 = {};
|
|
std::experimental::optional<int> x2 = 42;
|
|
|
|
CheckOptionalInt(x1);
|
|
CheckOptionalInt(x2);
|
|
}
|
|
|
|
TEST(Serialization, CapnpOptionalNonCopyable) {
|
|
std::experimental::optional<std::unique_ptr<int>> data =
|
|
std::make_unique<int>(5);
|
|
::capnp::MallocMessageBuilder message;
|
|
{
|
|
auto builder = message.initRoot<utils::capnp::Optional<
|
|
utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
|
|
auto save = [](auto *ptr_builder, const auto &data) {
|
|
auto save_int = [](auto *int_builder, int value) {
|
|
int_builder->setValue(value);
|
|
};
|
|
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(data, ptr_builder,
|
|
save_int);
|
|
};
|
|
utils::SaveOptional<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
|
|
std::unique_ptr<int>>(data, &builder, save);
|
|
}
|
|
std::experimental::optional<std::unique_ptr<int>> element;
|
|
{
|
|
auto reader = message.getRoot<utils::capnp::Optional<
|
|
utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
|
|
auto load = [](const auto &ptr_reader) {
|
|
auto load_int = [](const auto &int_reader) {
|
|
return new int(int_reader.getValue());
|
|
};
|
|
return utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(ptr_reader,
|
|
load_int);
|
|
};
|
|
element =
|
|
utils::LoadOptional<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
|
|
std::unique_ptr<int>>(reader, load);
|
|
}
|
|
EXPECT_EQ(*element.value(), 5);
|
|
}
|
|
|
|
void CheckUniquePtrInt(const std::unique_ptr<int> &x1) {
|
|
::capnp::MallocMessageBuilder message;
|
|
std::unique_ptr<int> y1;
|
|
{
|
|
auto builder =
|
|
message.initRoot<utils::capnp::UniquePtr<utils::capnp::BoxInt32>>();
|
|
auto save = [](utils::capnp::BoxInt32::Builder *builder, int value) {
|
|
builder->setValue(value);
|
|
};
|
|
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(x1, &builder, save);
|
|
}
|
|
{
|
|
auto reader =
|
|
message.getRoot<utils::capnp::UniquePtr<utils::capnp::BoxInt32>>();
|
|
auto load = [](const auto &int_reader) {
|
|
return new int(int_reader.getValue());
|
|
};
|
|
y1 = utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(reader, load);
|
|
}
|
|
if (!x1)
|
|
EXPECT_EQ(y1, nullptr);
|
|
else
|
|
EXPECT_EQ(*x1, *y1);
|
|
}
|
|
|
|
TEST(Serialization, CapnpUniquePtr) {
|
|
auto x1 = std::make_unique<int>(42);
|
|
std::unique_ptr<int> x2;
|
|
|
|
CheckUniquePtrInt(x1);
|
|
CheckUniquePtrInt(x2);
|
|
}
|
|
|
|
TEST(Serialization, CapnpUniquePtrNonCopyable) {
|
|
std::unique_ptr<std::unique_ptr<int>> data =
|
|
std::make_unique<std::unique_ptr<int>>(std::make_unique<int>(5));
|
|
::capnp::MallocMessageBuilder message;
|
|
{
|
|
auto builder = message.initRoot<utils::capnp::UniquePtr<
|
|
utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
|
|
auto save = [](auto *ptr_builder, const auto &data) {
|
|
auto save_int = [](auto *int_builder, int value) {
|
|
int_builder->setValue(value);
|
|
};
|
|
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(data, ptr_builder,
|
|
save_int);
|
|
};
|
|
utils::SaveUniquePtr<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
|
|
std::unique_ptr<int>>(data, &builder, save);
|
|
}
|
|
std::unique_ptr<std::unique_ptr<int>> element;
|
|
{
|
|
auto reader = message.getRoot<utils::capnp::UniquePtr<
|
|
utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
|
|
auto load = [](const auto &ptr_reader) {
|
|
auto load_int = [](const auto &int_reader) {
|
|
return new int(int_reader.getValue());
|
|
};
|
|
return new std::unique_ptr<int>(
|
|
utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(ptr_reader,
|
|
load_int));
|
|
};
|
|
element =
|
|
utils::LoadUniquePtr<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
|
|
std::unique_ptr<int>>(reader, load);
|
|
}
|
|
EXPECT_EQ(**element, 5);
|
|
}
|
|
|
|
TEST(Serialization, CapnpSharedPtr) {
|
|
std::vector<int *> saved_pointers;
|
|
auto p1 = std::make_shared<int>(5);
|
|
std::shared_ptr<int> p2;
|
|
std::vector<std::shared_ptr<int>> pointers{p1, p1, p2};
|
|
::capnp::MallocMessageBuilder message;
|
|
{
|
|
auto builders = message.initRoot<
|
|
::capnp::List<utils::capnp::SharedPtr<utils::capnp::BoxInt32>>>(
|
|
pointers.size());
|
|
auto save = [](utils::capnp::BoxInt32::Builder *builder, int value) {
|
|
builder->setValue(value);
|
|
};
|
|
for (size_t i = 0; i < pointers.size(); ++i) {
|
|
auto ptr_builder = builders[i];
|
|
utils::SaveSharedPtr<utils::capnp::BoxInt32, int>(
|
|
pointers[i], &ptr_builder, save, &saved_pointers);
|
|
}
|
|
}
|
|
EXPECT_EQ(saved_pointers.size(), 1);
|
|
std::vector<std::pair<uint64_t, std::shared_ptr<int>>> loaded_pointers;
|
|
std::vector<std::shared_ptr<int>> elements;
|
|
{
|
|
auto reader = message.getRoot<
|
|
::capnp::List<utils::capnp::SharedPtr<utils::capnp::BoxInt32>>>();
|
|
auto load = [](const auto &int_reader) {
|
|
return new int(int_reader.getValue());
|
|
};
|
|
for (const auto ptr_reader : reader) {
|
|
elements.emplace_back(utils::LoadSharedPtr<utils::capnp::BoxInt32, int>(
|
|
ptr_reader, load, &loaded_pointers));
|
|
}
|
|
}
|
|
EXPECT_EQ(loaded_pointers.size(), 1);
|
|
EXPECT_EQ(elements.size(), 3);
|
|
EXPECT_EQ(*elements[0], 5);
|
|
EXPECT_EQ(*elements[0], *elements[1]);
|
|
EXPECT_EQ(elements[2].get(), nullptr);
|
|
}
|
|
|
|
TEST(Serialization, CapnpSharedPtrNonCopyable) {
|
|
std::shared_ptr<std::unique_ptr<int>> data =
|
|
std::make_shared<std::unique_ptr<int>>(std::make_unique<int>(5));
|
|
std::vector<std::unique_ptr<int> *> saved_pointers;
|
|
::capnp::MallocMessageBuilder message;
|
|
{
|
|
auto builder = message.initRoot<utils::capnp::SharedPtr<
|
|
utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
|
|
auto save = [](auto *ptr_builder, const auto &data) {
|
|
auto save_int = [](auto *int_builder, int value) {
|
|
int_builder->setValue(value);
|
|
};
|
|
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(data, ptr_builder,
|
|
save_int);
|
|
};
|
|
utils::SaveSharedPtr<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
|
|
std::unique_ptr<int>>(data, &builder, save,
|
|
&saved_pointers);
|
|
}
|
|
std::shared_ptr<std::unique_ptr<int>> element;
|
|
std::vector<std::pair<uint64_t, std::shared_ptr<std::unique_ptr<int>>>>
|
|
loaded_pointers;
|
|
{
|
|
auto reader = message.getRoot<utils::capnp::SharedPtr<
|
|
utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
|
|
auto load = [](const auto &ptr_reader) {
|
|
auto load_int = [](const auto &int_reader) {
|
|
return new int(int_reader.getValue());
|
|
};
|
|
return new std::unique_ptr<int>(
|
|
utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(ptr_reader,
|
|
load_int));
|
|
};
|
|
element =
|
|
utils::LoadSharedPtr<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
|
|
std::unique_ptr<int>>(reader, load,
|
|
&loaded_pointers);
|
|
}
|
|
EXPECT_EQ(**element, 5);
|
|
}
|
|
|
|
TEST(Serialization, CapnpVectorPrimitive) {
|
|
std::vector<int> data{1, 2, 3};
|
|
::capnp::MallocMessageBuilder message;
|
|
{
|
|
auto list_builder = message.initRoot<::capnp::List<int>>(data.size());
|
|
utils::SaveVector<int>(data, &list_builder);
|
|
}
|
|
std::vector<int> elements;
|
|
{
|
|
auto reader = message.getRoot<::capnp::List<int>>();
|
|
utils::LoadVector<int>(&elements, reader);
|
|
}
|
|
EXPECT_EQ(elements.size(), 3);
|
|
EXPECT_EQ(elements[0], 1);
|
|
EXPECT_EQ(elements[1], 2);
|
|
EXPECT_EQ(elements[2], 3);
|
|
}
|
|
|
|
TEST(Serialization, CapnpVector) {
|
|
std::vector<int> data{1, 2, 3};
|
|
::capnp::MallocMessageBuilder message;
|
|
{
|
|
auto list_builder =
|
|
message.initRoot<::capnp::List<utils::capnp::BoxInt32>>(data.size());
|
|
auto save = [](utils::capnp::BoxInt32::Builder *builder, int value) {
|
|
builder->setValue(value);
|
|
};
|
|
utils::SaveVector<utils::capnp::BoxInt32, int>(data, &list_builder, save);
|
|
}
|
|
std::vector<int> elements;
|
|
{
|
|
auto reader = message.getRoot<::capnp::List<utils::capnp::BoxInt32>>();
|
|
auto load = [](const utils::capnp::BoxInt32::Reader &reader) -> int {
|
|
return reader.getValue();
|
|
};
|
|
utils::LoadVector<utils::capnp::BoxInt32, int>(&elements, reader, load);
|
|
}
|
|
EXPECT_EQ(elements.size(), 3);
|
|
EXPECT_EQ(elements[0], 1);
|
|
EXPECT_EQ(elements[1], 2);
|
|
EXPECT_EQ(elements[2], 3);
|
|
}
|
|
|
|
TEST(Serialization, CapnpVectorNonCopyable) {
|
|
std::vector<std::unique_ptr<int>> data;
|
|
data.emplace_back(std::make_unique<int>(5));
|
|
data.emplace_back(std::make_unique<int>(10));
|
|
::capnp::MallocMessageBuilder message;
|
|
{
|
|
auto list_builder = message.initRoot<
|
|
::capnp::List<utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>(
|
|
data.size());
|
|
auto save = [](auto *ptr_builder, const auto &data) {
|
|
auto save_int = [](auto *int_builder, int value) {
|
|
int_builder->setValue(value);
|
|
};
|
|
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(data, ptr_builder,
|
|
save_int);
|
|
};
|
|
utils::SaveVector<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
|
|
std::unique_ptr<int>>(data, &list_builder, save);
|
|
}
|
|
std::vector<std::unique_ptr<int>> elements;
|
|
{
|
|
auto reader = message.getRoot<
|
|
::capnp::List<utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
|
|
auto load = [](const auto &ptr_reader) {
|
|
auto load_int = [](const auto &int_reader) {
|
|
return new int(int_reader.getValue());
|
|
};
|
|
return utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(ptr_reader,
|
|
load_int);
|
|
};
|
|
utils::LoadVector<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
|
|
std::unique_ptr<int>>(&elements, reader, load);
|
|
}
|
|
EXPECT_EQ(elements.size(), 2);
|
|
EXPECT_EQ(*elements[0], 5);
|
|
EXPECT_EQ(*elements[1], 10);
|
|
}
|
|
|
|
TEST(Serialization, CapnpMap) {
|
|
std::map<std::string, std::string> map{{"my_key", "my_value"},
|
|
{"other_key", "other_value"}};
|
|
::capnp::MallocMessageBuilder message;
|
|
{
|
|
auto map_builder =
|
|
message.initRoot<utils::capnp::Map<capnp::Text, capnp::Text>>();
|
|
utils::SaveMap<capnp::Text, capnp::Text>(
|
|
map, &map_builder, [](auto *entry_builder, const auto &entry) {
|
|
entry_builder->setKey(entry.first);
|
|
entry_builder->setValue(entry.second);
|
|
});
|
|
}
|
|
std::map<std::string, std::string> new_map;
|
|
{
|
|
auto map_reader =
|
|
message.getRoot<utils::capnp::Map<capnp::Text, capnp::Text>>();
|
|
utils::LoadMap<capnp::Text, capnp::Text>(
|
|
&new_map, map_reader, [](const auto &entry_reader) {
|
|
std::string key = entry_reader.getKey();
|
|
std::string value = entry_reader.getValue();
|
|
return std::make_pair(key, value);
|
|
});
|
|
}
|
|
EXPECT_EQ(new_map, map);
|
|
}
|