#include #include #include "gtest/gtest.h" #include "capnp/message.h" #include "utils/serialization.hpp" using std::experimental::optional; using std::string_literals::operator""s; void CheckOptionalInt(const std::experimental::optional &x1) { ::capnp::MallocMessageBuilder message; std::experimental::optional y1; { auto builder = message.initRoot>(); auto save = [](utils::capnp::BoxInt32::Builder *builder, int value) { builder->setValue(value); }; utils::SaveOptional(x1, &builder, save); } { auto reader = message.getRoot>(); auto load = [](const utils::capnp::BoxInt32::Reader &reader) -> int { return reader.getValue(); }; y1 = utils::LoadOptional(reader, load); } EXPECT_EQ(x1, y1); } TEST(Serialization, CapnpOptional) { std::experimental::optional x1 = {}; std::experimental::optional x2 = 42; CheckOptionalInt(x1); CheckOptionalInt(x2); } TEST(Serialization, CapnpOptionalNonCopyable) { std::experimental::optional> data = std::make_unique(5); ::capnp::MallocMessageBuilder message; { auto builder = message.initRoot>>(); auto save = [](auto *ptr_builder, const auto &data) { auto save_int = [](auto *int_builder, int value) { int_builder->setValue(value); }; utils::SaveUniquePtr(data, ptr_builder, save_int); }; utils::SaveOptional, std::unique_ptr>(data, &builder, save); } std::experimental::optional> element; { auto reader = message.getRoot>>(); auto load = [](const auto &ptr_reader) { auto load_int = [](const auto &int_reader) { return new int(int_reader.getValue()); }; return utils::LoadUniquePtr(ptr_reader, load_int); }; element = utils::LoadOptional, std::unique_ptr>(reader, load); } EXPECT_EQ(*element.value(), 5); } void CheckUniquePtrInt(const std::unique_ptr &x1) { ::capnp::MallocMessageBuilder message; std::unique_ptr y1; { auto builder = message.initRoot>(); auto save = [](utils::capnp::BoxInt32::Builder *builder, int value) { builder->setValue(value); }; utils::SaveUniquePtr(x1, &builder, save); } { auto reader = message.getRoot>(); auto load = [](const auto &int_reader) { return new int(int_reader.getValue()); }; y1 = utils::LoadUniquePtr(reader, load); } if (!x1) EXPECT_EQ(y1, nullptr); else EXPECT_EQ(*x1, *y1); } TEST(Serialization, CapnpUniquePtr) { auto x1 = std::make_unique(42); std::unique_ptr x2; CheckUniquePtrInt(x1); CheckUniquePtrInt(x2); } TEST(Serialization, CapnpUniquePtrNonCopyable) { std::unique_ptr> data = std::make_unique>(std::make_unique(5)); ::capnp::MallocMessageBuilder message; { auto builder = message.initRoot>>(); auto save = [](auto *ptr_builder, const auto &data) { auto save_int = [](auto *int_builder, int value) { int_builder->setValue(value); }; utils::SaveUniquePtr(data, ptr_builder, save_int); }; utils::SaveUniquePtr, std::unique_ptr>(data, &builder, save); } std::unique_ptr> element; { auto reader = message.getRoot>>(); auto load = [](const auto &ptr_reader) { auto load_int = [](const auto &int_reader) { return new int(int_reader.getValue()); }; return new std::unique_ptr( utils::LoadUniquePtr(ptr_reader, load_int)); }; element = utils::LoadUniquePtr, std::unique_ptr>(reader, load); } EXPECT_EQ(**element, 5); } TEST(Serialization, CapnpSharedPtr) { std::vector saved_pointers; auto p1 = std::make_shared(5); std::shared_ptr p2; std::vector> pointers{p1, p1, p2}; ::capnp::MallocMessageBuilder message; { auto builders = message.initRoot< ::capnp::List>>( 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( pointers[i], &ptr_builder, save, &saved_pointers); } } EXPECT_EQ(saved_pointers.size(), 1); std::vector>> loaded_pointers; std::vector> elements; { auto reader = message.getRoot< ::capnp::List>>(); auto load = [](const auto &int_reader) { return new int(int_reader.getValue()); }; for (const auto ptr_reader : reader) { elements.emplace_back(utils::LoadSharedPtr( 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> data = std::make_shared>(std::make_unique(5)); std::vector *> saved_pointers; ::capnp::MallocMessageBuilder message; { auto builder = message.initRoot>>(); auto save = [](auto *ptr_builder, const auto &data) { auto save_int = [](auto *int_builder, int value) { int_builder->setValue(value); }; utils::SaveUniquePtr(data, ptr_builder, save_int); }; utils::SaveSharedPtr, std::unique_ptr>(data, &builder, save, &saved_pointers); } std::shared_ptr> element; std::vector>>> loaded_pointers; { auto reader = message.getRoot>>(); auto load = [](const auto &ptr_reader) { auto load_int = [](const auto &int_reader) { return new int(int_reader.getValue()); }; return new std::unique_ptr( utils::LoadUniquePtr(ptr_reader, load_int)); }; element = utils::LoadSharedPtr, std::unique_ptr>(reader, load, &loaded_pointers); } EXPECT_EQ(**element, 5); } TEST(Serialization, CapnpVectorPrimitive) { std::vector data{1, 2, 3}; ::capnp::MallocMessageBuilder message; { auto list_builder = message.initRoot<::capnp::List>(data.size()); utils::SaveVector(data, &list_builder); } std::vector elements; { auto reader = message.getRoot<::capnp::List>(); utils::LoadVector(&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 data{1, 2, 3}; ::capnp::MallocMessageBuilder message; { auto list_builder = message.initRoot<::capnp::List>(data.size()); auto save = [](utils::capnp::BoxInt32::Builder *builder, int value) { builder->setValue(value); }; utils::SaveVector(data, &list_builder, save); } std::vector elements; { auto reader = message.getRoot<::capnp::List>(); auto load = [](const utils::capnp::BoxInt32::Reader &reader) -> int { return reader.getValue(); }; utils::LoadVector(&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> data; data.emplace_back(std::make_unique(5)); data.emplace_back(std::make_unique(10)); ::capnp::MallocMessageBuilder message; { auto list_builder = message.initRoot< ::capnp::List>>( data.size()); auto save = [](auto *ptr_builder, const auto &data) { auto save_int = [](auto *int_builder, int value) { int_builder->setValue(value); }; utils::SaveUniquePtr(data, ptr_builder, save_int); }; utils::SaveVector, std::unique_ptr>(data, &list_builder, save); } std::vector> elements; { auto reader = message.getRoot< ::capnp::List>>(); auto load = [](const auto &ptr_reader) { auto load_int = [](const auto &int_reader) { return new int(int_reader.getValue()); }; return utils::LoadUniquePtr(ptr_reader, load_int); }; utils::LoadVector, std::unique_ptr>(&elements, reader, load); } EXPECT_EQ(elements.size(), 2); EXPECT_EQ(*elements[0], 5); EXPECT_EQ(*elements[1], 10); } TEST(Serialization, CapnpMap) { std::map map{{"my_key", "my_value"}, {"other_key", "other_value"}}; ::capnp::MallocMessageBuilder message; { auto map_builder = message.initRoot>(); utils::SaveMap( map, &map_builder, [](auto *entry_builder, const auto &entry) { entry_builder->setKey(entry.first); entry_builder->setValue(entry.second); }); } std::map new_map; { auto map_reader = message.getRoot>(); utils::LoadMap( &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); }