larra/tests/serialization.cpp
sha512sum 662392509f
All checks were successful
PR Check / on-push-commit-check (push) Successful in 13m30s
Add Serialization and Deserialization generation for std::optional
2024-11-12 14:36:18 +00:00

213 lines
7.7 KiB
C++

#include <gtest/gtest.h>
#include <larra/jid.hpp>
#include <larra/serialization.hpp>
#include <larra/serialization/auto.hpp>
#include <larra/serialization/error.hpp>
#include <larra/stream_error.hpp>
using namespace std::literals;
namespace larra::xmpp {
TEST(Parse, Variant) {
xmlpp::Document doc;
auto node = doc.create_root_node("stream:error");
node->add_child_element("unsupported-stanza-type");
node->set_namespace_declaration("urn:ietf:params:xml:ns:xmpp-streams");
auto streamError = Serialization<StreamError>::Parse(node);
EXPECT_TRUE(std::get_if<error::stream::UnsupportedStanzaType>(&streamError));
}
TEST(Serialize, Variant) {
using S = Serialization<StreamError>;
StreamError data = error::stream::UnsupportedStanzaType{};
xmlpp::Document doc;
auto node = doc.create_root_node("stream:error");
S::Serialize(node, data);
EXPECT_EQ(doc.write_to_string(),
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<stream:error><unsupported-stanza-type "
"xmlns=\"urn:ietf:params:xml:ns:xmpp-streams\"/></stream:error>\n"sv);
}
namespace tests::serialization {
struct SomeStruct {
static constexpr auto kDefaultName = "some";
std::string value;
[[nodiscard]] static auto Parse(xmlpp::Element* element) -> SomeStruct;
friend auto operator<<(xmlpp::Element* element, const SomeStruct& self);
constexpr auto operator==(const SomeStruct&) const -> bool = default;
};
struct SomeStruct2 {
static constexpr auto kDefaultName = "some2";
SomeStruct value;
[[nodiscard]] static auto Parse(xmlpp::Element* element) -> SomeStruct2;
friend auto operator<<(xmlpp::Element* element, const SomeStruct2& self);
};
struct SomeStruct3 {
static constexpr auto kDefaultName = "some3";
int value;
[[nodiscard]] static auto Parse(xmlpp::Element* element) -> SomeStruct3;
};
struct SomeStruct4 {
static constexpr auto kDefaultName = "some4";
SomeStruct3 value;
[[nodiscard]] static auto Parse(xmlpp::Element* element) -> SomeStruct4;
};
struct SomeStruct5 {
static constexpr auto kDefaultName = "some5";
BareJid value;
[[nodiscard]] static auto Parse(xmlpp::Element* element) -> SomeStruct5;
friend auto operator<<(xmlpp::Element* element, const SomeStruct5& self);
};
struct SomeStruct6 {
static constexpr auto kDefaultName = "some6";
std::vector<SomeStruct> some;
[[nodiscard]] static auto Parse(xmlpp::Element* element) -> SomeStruct6;
};
struct SomeStruct7 {
static constexpr auto kDefaultName = "some7";
std::optional<FullJid> value;
[[nodiscard]] static auto Parse(xmlpp::Element* element) -> SomeStruct7;
};
} // namespace tests::serialization
namespace serialization {
template <>
constexpr auto kSerializationConfig<tests::serialization::SomeStruct> = SerializationConfig<tests::serialization::SomeStruct>{};
template <>
constexpr auto kSerializationConfig<tests::serialization::SomeStruct2> = SerializationConfig<tests::serialization::SomeStruct2>{};
template <>
constexpr auto kSerializationConfig<tests::serialization::SomeStruct4> = SerializationConfig<tests::serialization::SomeStruct4>{};
template <>
constexpr auto kSerializationConfig<tests::serialization::SomeStruct5> = SerializationConfig<tests::serialization::SomeStruct5>{};
template <>
constexpr auto kSerializationConfig<tests::serialization::SomeStruct6> =
SerializationConfig<tests::serialization::SomeStruct6>{}.With<"some">({Config<std::vector<tests::serialization::SomeStruct>>{}});
template <>
constexpr auto kSerializationConfig<tests::serialization::SomeStruct7> = SerializationConfig<tests::serialization::SomeStruct7>{};
} // namespace serialization
namespace tests::serialization {
auto SomeStruct::Parse(xmlpp::Element* element) -> SomeStruct {
return ::larra::xmpp::serialization::Parse<tests::serialization::SomeStruct>(element);
}
auto SomeStruct2::Parse(xmlpp::Element* element) -> SomeStruct2 {
return ::larra::xmpp::serialization::Parse<tests::serialization::SomeStruct2>(element);
}
auto SomeStruct3::Parse(xmlpp::Element*) -> SomeStruct3 {
return {.value = 42}; // NOLINT
}
auto SomeStruct4::Parse(xmlpp::Element* element) -> SomeStruct4 {
return ::larra::xmpp::serialization::Parse<tests::serialization::SomeStruct4>(element);
}
auto SomeStruct5::Parse(xmlpp::Element* element) -> SomeStruct5 {
return ::larra::xmpp::serialization::Parse<tests::serialization::SomeStruct5>(element);
}
auto SomeStruct6::Parse(xmlpp::Element* element) -> SomeStruct6 {
return ::larra::xmpp::serialization::Parse<tests::serialization::SomeStruct6>(element);
}
auto SomeStruct7::Parse(xmlpp::Element* element) -> SomeStruct7 {
return ::larra::xmpp::serialization::Parse<tests::serialization::SomeStruct7>(element);
}
auto operator<<(xmlpp::Element* element, const SomeStruct& self) {
::larra::xmpp::serialization::Serialize(element, self);
}
auto operator<<(xmlpp::Element* element, const SomeStruct2& self) {
::larra::xmpp::serialization::Serialize(element, self);
}
auto operator<<(xmlpp::Element* element, const SomeStruct5& self) {
::larra::xmpp::serialization::Serialize(element, self);
}
} // namespace tests::serialization
TEST(AutoParse, Basic) {
xmlpp::Document doc;
auto node = doc.create_root_node("some2");
node = node->add_child_element("some");
node->set_attribute("value", "Hello");
auto a = Serialization<tests::serialization::SomeStruct>::Parse(node);
EXPECT_EQ(a.value, "Hello"sv);
auto b = Serialization<tests::serialization::SomeStruct2>::Parse(doc.get_root_node());
EXPECT_EQ(b.value.value, "Hello"sv);
EXPECT_THROW(std::ignore = tests::serialization::SomeStruct2::Parse(node), serialization::ParsingError);
auto node2 = node->add_child_element("some4");
node2->add_child_element("some3");
auto c = Serialization<tests::serialization::SomeStruct4>::Parse(node2);
EXPECT_EQ(c.value.value, 42);
}
TEST(AutoParse, Attribute) {
xmlpp::Document doc;
auto node = doc.create_root_node("some5");
node->set_attribute("value", "user@server.i2p");
auto a = Serialization<tests::serialization::SomeStruct5>::Parse(node);
EXPECT_EQ(a.value.server, "server.i2p"sv);
EXPECT_EQ(a.value.username, "user"sv);
}
TEST(AutoParse, Vector) {
xmlpp::Document doc;
auto node = doc.create_root_node("some6");
for(auto i : std::views::iota(0, 10)) {
auto child = node->add_child_element("some");
child->set_attribute("value", std::format("Hello {}", i));
}
auto value = Serialization<tests::serialization::SomeStruct6>::Parse(node);
EXPECT_EQ(value.some, std::views::iota(0, 10) | std::views::transform([](auto i) -> tests::serialization::SomeStruct {
return {.value = std::format("Hello {}", i)};
}) | std::ranges::to<std::vector<tests::serialization::SomeStruct>>());
}
TEST(AutoParse, Optional) {
xmlpp::Document doc;
auto node = doc.create_root_node("some7");
auto value = Serialization<tests::serialization::SomeStruct7>::Parse(node).value;
EXPECT_EQ(value, std::nullopt);
node->set_attribute("value", "user@server.i2p/resource");
auto value2 = Serialization<tests::serialization::SomeStruct7>::Parse(node).value;
FullJid expectData{.username = "user", .server = "server.i2p", .resource = "resource"};
EXPECT_EQ(value2, expectData);
}
TEST(AutoSerialize, Basic) {
xmlpp::Document doc;
auto node = doc.create_root_node("some2");
node << tests::serialization::SomeStruct2{.value = {.value = "testData"}};
EXPECT_EQ(doc.write_to_string(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<some2><some value=\"testData\"/></some2>\n");
}
TEST(AutoSerialize, Attribute) {
xmlpp::Document doc;
auto node = doc.create_root_node("some5");
node << tests::serialization::SomeStruct5{.value = {.username = "user", .server = "server.i2p"}};
EXPECT_EQ(doc.write_to_string(), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<some5 value=\"user@server.i2p\"/>\n");
}
} // namespace larra::xmpp