diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ed51f5..8fd11ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ set(BOOST_INCLUDE_LIBRARIES "pfr;asio;serialization") option(CPM_USE_LOCAL_PACKAGES "Use local packages" ON) option(UTEMPL_USE_LOCAL_PACKAGE "Use utempl local package" OFF) option(BUILD_EXECUTABLE ON) -option(LOG_LEVEL 0 "Available log levels: 0=TRACE, 1=DEBUG,2= INFO,3= WARN, 4=ERROR, 5=CRITICAL, 6=OFF") # Compile program with highest available log levle to trace everything +set(LOG_LEVEL 0 "Available log levels: 0=TRACE, 1=DEBUG,2= INFO,3= WARN, 4=ERROR, 5=CRITICAL, 6=OFF") # Compile program with highest available log levle to trace everything set(UTEMPL_URL "https://sha512sum.xyz/git/sha512sum/utempl" CACHE STRING "utempl repository URL") @@ -272,7 +272,8 @@ if(ENABLE_EXAMPLES) get_filename_component(EXAMPLE_NAME ${EXAMPLE_SRC} NAME_WE) add_executable(${EXAMPLE_NAME} ${EXAMPLE_SRC}) target_link_libraries(${EXAMPLE_NAME} larra_xmpp) - target_compile_definitions(${EXAMPLE_NAME} PRIVATE SPDLOG_ACTIVE_LEVEL=${LOG_LEVEL}) + # TODO(unknown): Fixed 'command line' error occured and uncomment below + # target_compile_definitions(${EXAMPLE_NAME} PRIVATE SPDLOG_ACTIVE_LEVEL=${LOG_LEVEL}) set_property(TARGET ${EXAMPLE_NAME} PROPERTY CXX_STANDARD 23) set_target_properties(${EXAMPLE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/examples/output") diff --git a/examples/src/connect.cpp b/examples/src/connect.cpp index 9f24137..b1085a7 100644 --- a/examples/src/connect.cpp +++ b/examples/src/connect.cpp @@ -52,6 +52,15 @@ auto Coroutine() -> boost::asio::awaitable { auto main() -> int { spdlog::set_level(spdlog::level::trace); + +#ifdef SPDLOG_ACTIVE_LEVEL + std::println("\n\tCompiled max available log level: {}\n\tCurrently set log level: {}", + SPDLOG_ACTIVE_LEVEL, + std::to_underlying(spdlog::get_level())); +#else + std::println("\n\tCurrently set log level: {}", std::to_underlying(spdlog::get_level())); +#endif + boost::asio::io_context io_context; boost::asio::co_spawn(io_context, Coroutine(), boost::asio::detached); io_context.run(); diff --git a/tests/iq.cpp b/tests/iq.cpp index 4638ffe..1dae134 100644 --- a/tests/iq.cpp +++ b/tests/iq.cpp @@ -1,10 +1,23 @@ #include +#include #include +#include namespace { -static constexpr auto kExpectedData = "\n37\n"; +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; @@ -43,4 +56,101 @@ TEST(IQ, Parse) { 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