#include #include #include "gtest/gtest.h" #include "boost/archive/binary_iarchive.hpp" #include "boost/archive/binary_oarchive.hpp" #include "capnp/message.h" #include "utils/serialization.hpp" using std::experimental::optional; using std::string_literals::operator""s; TEST(Serialization, Optional) { std::stringstream ss; optional x1 = {}; optional x2 = 42; optional y1, y2; { boost::archive::binary_oarchive ar(ss); ar << x1; ar << x2; } { boost::archive::binary_iarchive ar(ss); ar >> y1; ar >> y2; } EXPECT_EQ(x1, y1); EXPECT_EQ(x2, y2); } TEST(Serialization, Tuple) { std::stringstream ss; auto x1 = std::make_tuple("foo"s, 42, std::experimental::make_optional(3.14)); auto x2 = std::make_tuple(); auto x3 = std::make_tuple(1, 2, 3, 4, 5); decltype(x1) y1; decltype(x2) y2; decltype(x3) y3; { boost::archive::binary_oarchive ar(ss); ar << x1; ar << x2; ar << x3; } { boost::archive::binary_iarchive ar(ss); ar >> y1; ar >> y2; ar >> y3; } EXPECT_EQ(x1, y1); EXPECT_EQ(x2, y2); EXPECT_EQ(x3, y3); } 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; std::experimental::optional y1, y2; CheckOptionalInt(x1); CheckOptionalInt(x2); } TEST(Serialization, CapnpOptionalNonCopyable) { std::experimental::optional> data = std::make_unique(5); ::capnp::MallocMessageBuilder message; { auto builder = message.initRoot>>(); auto save = []( utils::capnp::UniquePtr::Builder *builder, const std::unique_ptr &data) { auto save_int = [](utils::capnp::BoxInt32::Builder *builder, int value) { builder->setValue(value); }; utils::SaveUniquePtr(data, builder, save_int); }; utils::SaveOptional, std::unique_ptr>(data, &builder, save); } std::experimental::optional> element; { auto reader = message.getRoot>>(); auto load = []( const utils::capnp::UniquePtr::Reader &reader) -> std::unique_ptr { auto load_int = [](const utils::capnp::BoxInt32::Reader &reader) -> int { return reader.getValue(); }; return utils::LoadUniquePtr(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 utils::capnp::BoxInt32::Reader &reader) -> int { return 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 = []( utils::capnp::UniquePtr::Builder *builder, const std::unique_ptr &data) { auto save_int = [](utils::capnp::BoxInt32::Builder *builder, int value) { builder->setValue(value); }; utils::SaveUniquePtr(data, builder, save_int); }; utils::SaveUniquePtr, std::unique_ptr>(data, &builder, save); } std::unique_ptr> element; { auto reader = message.getRoot>>(); auto load = []( const utils::capnp::UniquePtr::Reader &reader) -> std::unique_ptr { auto load_int = [](const utils::capnp::BoxInt32::Reader &reader) -> int { return reader.getValue(); }; return utils::LoadUniquePtr(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 utils::capnp::BoxInt32::Reader &reader) -> int { return 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 = []( utils::capnp::UniquePtr::Builder *builder, const std::unique_ptr &data) { auto save_int = [](utils::capnp::BoxInt32::Builder *builder, int value) { builder->setValue(value); }; utils::SaveUniquePtr(data, 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 utils::capnp::UniquePtr::Reader &reader) -> std::unique_ptr { auto load_int = [](const utils::capnp::BoxInt32::Reader &reader) -> int { return reader.getValue(); }; return utils::LoadUniquePtr(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 = []( utils::capnp::UniquePtr::Builder *builder, const std::unique_ptr &data) { auto save_int = [](utils::capnp::BoxInt32::Builder *builder, int value) { builder->setValue(value); }; utils::SaveUniquePtr(data, builder, save_int); }; utils::SaveVector, std::unique_ptr>(data, &list_builder, save); } std::vector> elements; { auto reader = message.getRoot< ::capnp::List>>(); auto load = []( const utils::capnp::UniquePtr::Reader &reader) -> std::unique_ptr { auto load_int = [](const utils::capnp::BoxInt32::Reader &reader) -> int { return reader.getValue(); }; return utils::LoadUniquePtr(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); }