#include #include #include #include namespace { static constexpr auto kForbiddenErrorData = R"( )"; static constexpr auto kExpectedSetData = R"( 37 )"; static constexpr auto kExpectedData = R"( 37 )"; struct SomeStruct { int value; constexpr auto operator==(const SomeStruct&) const -> bool = default; static constexpr auto kDefaultName = "some"; static constexpr auto Parse(xmlpp::Element* element) -> SomeStruct { auto node = element->get_first_child_text(); if(!node) { throw std::runtime_error{"Not found value"}; } return {std::stoi(node->get_content())}; } friend constexpr auto operator<<(xmlpp::Element* element, const SomeStruct& self) { auto node = element->add_child_text(std::to_string(self.value)); node->set_name("value"); } }; } // namespace namespace larra::xmpp { TEST(IQ, Serialize) { iq::Get iq{.id = "id", .payload = SomeStruct{.value = 37}}; // NOLINT xmlpp::Document doc; Serialization>::Serialize(doc.create_root_node("iq"), iq); EXPECT_EQ(doc.write_to_string(), kExpectedData); } TEST(IQ, Parse) { iq::Get iq{.id = "id", .payload = SomeStruct{.value = 37}}; // NOLINT xmlpp::Document doc; auto node = doc.create_root_node("iq"); using S = Serialization>; S::Serialize(node, iq); EXPECT_EQ(S::Parse(node), iq); } TEST(IQ, ParseForbiddenError) { std::istringstream xml_stream(kForbiddenErrorData); xmlpp::DomParser parser; parser.parse_stream(xml_stream); using S = Serialization>; xmlpp::Document* doc = parser.get_document(); auto iqRes = S::Parse(doc->get_root_node()); ASSERT_TRUE(std::holds_alternative(iqRes)); auto errorRes = std::get(iqRes); ASSERT_TRUE(std::holds_alternative(errorRes.payload)); } TEST(IQ, IqErrThrowVisitorThrow) { std::istringstream xml_stream(kForbiddenErrorData); xmlpp::DomParser parser; parser.parse_stream(xml_stream); using S = Serialization>; xmlpp::Document* doc = parser.get_document(); auto iqRes = S::Parse(doc->get_root_node()); ASSERT_TRUE(std::holds_alternative(iqRes)); static constexpr auto visitorErrMsg = "Test Error"; static constexpr auto throwErrMsg = "Stanza IQ Error: Forbidden"; try { std::visit(utempl::Overloaded([](iq::Result r) {}, IqErrThrowVisitor{visitorErrMsg}), std::move(iqRes)); } catch(const iq::error::impl::IqBaseError& err) { ASSERT_STREQ(throwErrMsg, err.what()); return; } catch(const std::runtime_error& err) { ASSERT_TRUE(false) << "Invalid throw type throw"; } catch(...) { ASSERT_TRUE(false) << "Unexpected throw"; } ASSERT_TRUE(false) << "Expected throwing an exception due to an error in output"; } TEST(IQ, IqErrThrowVisitorThrowGet) { std::istringstream xml_stream(kExpectedData); xmlpp::DomParser parser; parser.parse_stream(xml_stream); using S = Serialization>; xmlpp::Document* doc = parser.get_document(); auto iqRes = S::Parse(doc->get_root_node()); ASSERT_TRUE(std::holds_alternative>(iqRes)) << "\tERROR: Unexpected parse result"; static constexpr auto visitorErrMsg = "Test Error"; static constexpr auto throwErrMsg = "Test Error: 'Get' is an invalid type for IQ result. Expected 'Result' or 'Error'"; try { std::visit(utempl::Overloaded([](iq::Result r) {}, IqErrThrowVisitor{"Test Error"}), std::move(iqRes)); } catch(const iq::error::impl::IqBaseError& err) { ASSERT_TRUE(false) << "\tERROR: Invalid throw type throw"; } catch(const std::runtime_error& err) { ASSERT_STREQ(throwErrMsg, err.what()); return; } catch(...) { ASSERT_TRUE(false) << "\tERROR: Unexpected throw"; } ASSERT_TRUE(false) << "\tERROR: Expected throwing an exception due to an error in output"; } TEST(IQ, IqErrThrowVisitorThrowSet) { std::istringstream xml_stream(kExpectedSetData); xmlpp::DomParser parser; parser.parse_stream(xml_stream); using S = Serialization>; xmlpp::Document* doc = parser.get_document(); auto iqRes = S::Parse(doc->get_root_node()); ASSERT_TRUE(std::holds_alternative>(iqRes)) << "\tERROR: Unexpected parse result"; static constexpr auto visitorErrMsg = "Test Error"; static constexpr auto throwErrMsg = "Test Error: 'Set' is an invalid type for IQ result. Expected 'Result' or 'Error'"; try { std::visit(utempl::Overloaded([](iq::Result r) {}, IqErrThrowVisitor{"Test Error"}), std::move(iqRes)); } catch(const iq::error::impl::IqBaseError& err) { ASSERT_TRUE(false) << "\tERROR: Invalid throw type throw"; } catch(const std::runtime_error& err) { ASSERT_STREQ(throwErrMsg, err.what()); return; } catch(...) { ASSERT_TRUE(false) << "\tERROR: Unexpected throw"; } ASSERT_TRUE(false) << "\tERROR: Expected throwing an exception due to an error in output"; } } // namespace larra::xmpp