memgraph/tests/unit/serialization.cpp
Matej Ferencevic bb052be002 Remove serialization from utils
Reviewers: teon.banek

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1852
2019-02-13 15:41:40 +01:00

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);
}