#include #include #include #include #include #include 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::Parse(node); EXPECT_TRUE(std::get_if(&streamError)); } TEST(Serialize, Variant) { using S = Serialization; 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(), "\n\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 some; [[nodiscard]] static auto Parse(xmlpp::Element* element) -> SomeStruct6; }; struct SomeStruct7 { static constexpr auto kDefaultName = "some7"; std::optional value; [[nodiscard]] static auto Parse(xmlpp::Element* element) -> SomeStruct7; }; } // namespace tests::serialization namespace serialization { template <> constexpr auto kSerializationConfig = SerializationConfig{}; template <> constexpr auto kSerializationConfig = SerializationConfig{}; template <> constexpr auto kSerializationConfig = SerializationConfig{}; template <> constexpr auto kSerializationConfig = SerializationConfig{}; template <> constexpr auto kSerializationConfig = SerializationConfig{}.With<"some">({Config>{}}); template <> constexpr auto kSerializationConfig = SerializationConfig{}; } // namespace serialization namespace tests::serialization { auto SomeStruct::Parse(xmlpp::Element* element) -> SomeStruct { return ::larra::xmpp::serialization::Parse(element); } auto SomeStruct2::Parse(xmlpp::Element* element) -> SomeStruct2 { return ::larra::xmpp::serialization::Parse(element); } auto SomeStruct3::Parse(xmlpp::Element*) -> SomeStruct3 { return {.value = 42}; // NOLINT } auto SomeStruct4::Parse(xmlpp::Element* element) -> SomeStruct4 { return ::larra::xmpp::serialization::Parse(element); } auto SomeStruct5::Parse(xmlpp::Element* element) -> SomeStruct5 { return ::larra::xmpp::serialization::Parse(element); } auto SomeStruct6::Parse(xmlpp::Element* element) -> SomeStruct6 { return ::larra::xmpp::serialization::Parse(element); } auto SomeStruct7::Parse(xmlpp::Element* element) -> SomeStruct7 { return ::larra::xmpp::serialization::Parse(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::Parse(node); EXPECT_EQ(a.value, "Hello"sv); auto b = Serialization::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::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::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::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>()); } TEST(AutoParse, Optional) { xmlpp::Document doc; auto node = doc.create_root_node("some7"); auto value = Serialization::Parse(node).value; EXPECT_EQ(value, std::nullopt); node->set_attribute("value", "user@server.i2p/resource"); auto value2 = Serialization::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(), "\n\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(), "\n\n"); } } // namespace larra::xmpp