From 284250a69fc564c4be56303c2f969c57d803246f Mon Sep 17 00:00:00 2001 From: Ivan-lis Date: Sun, 22 Dec 2024 22:39:58 +0000 Subject: [PATCH] Renamed iq to stanza error. Added log level as cmake param --- .forgejo/workflows/pr_check.yaml | 4 + .vscode/tasks.json | 5 +- CMakeLists.txt | 8 +- library/include/larra/iq.hpp | 4 +- library/include/larra/iq_error.hpp | 152 ------------------------- library/include/larra/stanza_error.hpp | 148 ++++++++++++++++++++++++ tests/iq.cpp | 8 +- 7 files changed, 166 insertions(+), 163 deletions(-) delete mode 100644 library/include/larra/iq_error.hpp create mode 100644 library/include/larra/stanza_error.hpp diff --git a/.forgejo/workflows/pr_check.yaml b/.forgejo/workflows/pr_check.yaml index b8f8f80..19355ab 100644 --- a/.forgejo/workflows/pr_check.yaml +++ b/.forgejo/workflows/pr_check.yaml @@ -134,6 +134,8 @@ jobs: -GNinja -DCMAKE_BUILD_TYPE=Release \ -DENABLE_EXAMPLES=ON \ -DENABLE_TESTS=ON \ + -DLOG_LEVEL=0 \ + -DTEST_LOG_LEVEL=0 \ -DCMAKE_CXX_FLAGS="-ftemplate-backtrace-limit=0" cmake --build ${{ github.workspace }}/build_gcc --parallel `nproc` @@ -160,6 +162,8 @@ jobs: -GNinja -DCMAKE_BUILD_TYPE=Release \ -DENABLE_EXAMPLES=ON \ -DENABLE_TESTS=ON \ + -DLOG_LEVEL=0 \ + -DTEST_LOG_LEVEL=0 \ -DCMAKE_CXX_FLAGS="-stdlib=libc++ -I/home/LLVM-${LLVM_VER}/include/c++/v1 -fno-modules" echo "::group::compile_commands.json content" diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 4720fa7..b1b88cc 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -80,7 +80,7 @@ "cd ${workspaceFolder} &&", "mkdir -p build && cd build &&", "cmake cmake -Wno-dev ", - " -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON .." + " -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON -DLOG_LEVEL=0 -DTEST_LOG_LEVEL=0 .." ], "options": { "env": { @@ -138,6 +138,7 @@ "mkdir -p build_clang && cd build_clang &&", "cmake -Wno-dev ", " -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON ", + " -DLOG_LEVEL=0 -DTEST_LOG_LEVEL=0", " -DCMAKE_CXX_FLAGS=\"-stdlib=libstdc++\"", " -DCMAKE_EXE_LINKER_FLAGS=\"-L/usr/lib/x86_64-linux-gnu -lstdc++\" .." ], @@ -160,6 +161,7 @@ "mkdir -p build_clang && cd build_clang &&", "cmake -Wno-dev ", " -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON", + " -DLOG_LEVEL=0 -DTEST_LOG_LEVEL=0" // // Uncomment for GCC standart library: libstdc++ //" -DCMAKE_CXX_FLAGS=\"-stdlib=libstdc++ -fno-omit-frame-pointer -g -fsanitize=address,undefined,leak,function,nullability,vptr\"", @@ -211,6 +213,7 @@ "mkdir -p build_clang && cd build_clang &&", "cmake -Wno-dev ", " -DCMAKE_BUILD_TYPE=Debug -DENABLE_EXAMPLES=ON -DENABLE_TESTS=ON ", + " -DLOG_LEVEL=0 -DTEST_LOG_LEVEL=0", " -DCMAKE_CXX_FLAGS=\"-stdlib=libstdc++ -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fsanitize=memory\"", " -DCMAKE_EXE_LINKER_FLAGS=\"-L/usr/lib/x86_64-linux-gnu -lstdc++ -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -fsanitize=memory\" ..", ], diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fd11ac..7c55017 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,8 @@ 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) -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(LOG_LEVEL 2 CACHE STRING "Available log levels: 0=TRACE, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=CRITICAL, 6=OFF") +set(TEST_LOG_LEVEL 2 CACHE STRING "Available log levels: 0=TRACE, 1=DEBUG, 2=INFO, 3=WARN, 4=ERROR, 5=CRITICAL, 6=OFF") set(UTEMPL_URL "https://sha512sum.xyz/git/sha512sum/utempl" CACHE STRING "utempl repository URL") @@ -260,7 +261,7 @@ if(ENABLE_TESTS) target_sources(larra_xmpp_tests PUBLIC ${SOURCES}) target_link_libraries(larra_xmpp_tests GTest::gtest_main larra_xmpp) - target_compile_definitions(larra_xmpp_tests PRIVATE SPDLOG_ACTIVE_LEVEL=0) # SPDLOG_LEVEL_TRACE=0. Check LOG_LEVEL variable and spdlog documentation for more details + target_compile_definitions(larra_xmpp_tests PRIVATE SPDLOG_ACTIVE_LEVEL=${TEST_LOG_LEVEL}) set_property(TARGET larra_xmpp_tests PROPERTY CXX_STANDARD 23) include(GoogleTest) gtest_discover_tests(larra_xmpp_tests) @@ -272,8 +273,7 @@ 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) - # TODO(unknown): Fixed 'command line' error occured and uncomment below - # target_compile_definitions(${EXAMPLE_NAME} PRIVATE SPDLOG_ACTIVE_LEVEL=${LOG_LEVEL}) + target_compile_definitions(${EXAMPLE_NAME} PRIVATE SPDLOG_ACTIVE_LEVEL=${TEST_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/library/include/larra/iq.hpp b/library/include/larra/iq.hpp index 183ec0e..20d5609 100644 --- a/library/include/larra/iq.hpp +++ b/library/include/larra/iq.hpp @@ -1,9 +1,9 @@ #pragma once #include -#include #include #include +#include #include #include #include @@ -118,7 +118,7 @@ using Error = BaseImplWithPayload; } // namespace iq -using IqError = iq::Error; +using IqError = iq::Error; template using Iq = std::variant, iq::Set, iq::Result, IqError>; diff --git a/library/include/larra/iq_error.hpp b/library/include/larra/iq_error.hpp deleted file mode 100644 index 2dfc6bd..0000000 --- a/library/include/larra/iq_error.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#pragma once -#include - -#include -#include -#include - -namespace larra::xmpp::iq::error { - -namespace impl { - -struct IqBaseError : std::exception {}; - -// DO NOT MOVE TO ANOTHER NAMESPACE(where no heirs). VIA friend A FUNCTION IS ADDED THAT VIA ADL WILL BE SEARCHED FOR HEIRS -// C++20 modules very unstable in clangd :( -template -struct IqErrorImpl : IqBaseError { - static constexpr auto kDefaultName = "error"; - static constexpr auto kDefaultNamespace = "urn:ietf:params:xml:ns:xmpp-stanzas"; - static inline const auto kKebabCaseName = static_cast(utils::ToKebabCaseName()); - - static constexpr auto kErrorMessage = [] -> std::string_view { - static constexpr auto name = nameof::nameof_short_type(); - static constexpr auto str = [] { - return std::array{std::string_view{"Stanza IQ Error: "}, std::string_view{name}, std::string_view{"\0", 1}} | std::views::join; - }; - static constexpr auto array = str() | std::ranges::to>>(); - return {array.data(), array.size() - 1}; - }(); - - std::optional by{}; - std::string type; - - // TODO(unknown): Add "optional text children" support for stanza error. Check "XML Stanzas" -> "Syntax" for more details - static constexpr auto TryParse(xmlpp::Element* element) -> std::optional { - if(not element) { - return std::nullopt; - } - - auto by = element->get_attribute("by"); - auto type = element->get_attribute("type"); - if(not type) { - return std::nullopt; - } - - auto node = element->get_first_child(kKebabCaseName); - if(not node) { - return std::nullopt; - } - - T obj; - obj.type = type->get_value(); - if(by) { - obj.by = std::optional{by->get_value()}; - } - return obj; - } - static constexpr auto Parse(xmlpp::Element* element) -> T { - return TryParse(element).value(); - } - friend constexpr auto operator<<(xmlpp::Element* element, const T& obj) -> void { - element->set_attribute("type", obj.type); - if(obj.by) { - element->set_attribute("by", *obj.by); - } - - auto node = element->add_child_element(kKebabCaseName); - node->set_namespace_declaration(kDefaultNamespace); - } - constexpr auto operator==(const IqErrorImpl&) const -> bool { - return true; - }; - [[nodiscard]] constexpr auto what() const noexcept -> const char* override { - return kErrorMessage.data(); - } -}; - -// Helper class to prevent parsing response stream into an expected return type if its name is an 'error' -struct UnknownIqError : IqBaseError { - static constexpr auto kDefaultName = "stream:error"; - static constexpr std::string_view kErrorMessage = "Unknown XMPP stream error"; - - static constexpr auto TryParse(xmlpp::Element* element) { - return std::optional{UnknownIqError{}}; - } - static constexpr auto Parse(xmlpp::Element* element) { - return TryParse(element).value(); - } - friend constexpr auto operator<<(xmlpp::Element* element, const UnknownIqError& obj) -> void { - throw std::format("'{}' must never be written into the real stream!", kErrorMessage); - } - constexpr auto operator==(const UnknownIqError&) const -> bool { - return true; - }; - [[nodiscard]] constexpr auto what() const noexcept -> const char* override { - return kErrorMessage.data(); - } -}; - -struct BadRequest : IqErrorImpl {}; -struct Conflict : IqErrorImpl {}; -struct FeatureNotImplemented : IqErrorImpl {}; -struct Forbidden : IqErrorImpl {}; -struct Gone : IqErrorImpl {}; -struct InternalServerError : IqErrorImpl {}; -struct ItemNotFound : IqErrorImpl {}; -struct JidMalformed : IqErrorImpl {}; -struct NotAcceptable : IqErrorImpl {}; -struct NotAllowed : IqErrorImpl {}; -struct NotAuthorized : IqErrorImpl {}; -struct PolicyViolation : IqErrorImpl {}; -struct RecipientUnavailable : IqErrorImpl {}; -struct Redirect : IqErrorImpl {}; -struct RegistrationRequired : IqErrorImpl {}; -struct RemoteServerNotFound : IqErrorImpl {}; -struct RemoteServerTimeout : IqErrorImpl {}; -struct ResourceConstraint : IqErrorImpl {}; -struct ServiceUnavailable : IqErrorImpl {}; -struct SubscriptionRequired : IqErrorImpl {}; -struct UndefinedCondition : IqErrorImpl {}; -struct UnexpectedRequest : IqErrorImpl {}; - -} // namespace impl - -using IqError = std::variant; - -static_assert(!std::is_same_v - 1, IqError>, IqError>, - "'UnknownIqError' must be at the end of 'IqError' variant"); - -} // namespace larra::xmpp::iq::error diff --git a/library/include/larra/stanza_error.hpp b/library/include/larra/stanza_error.hpp new file mode 100644 index 0000000..743cbfa --- /dev/null +++ b/library/include/larra/stanza_error.hpp @@ -0,0 +1,148 @@ +#pragma once +#include + +#include +#include +#include + +namespace larra::xmpp::stanza::error { + +struct StanzaBaseError : std::exception {}; + +// DO NOT MOVE TO ANOTHER NAMESPACE(where no heirs). VIA friend A FUNCTION IS ADDED THAT VIA ADL WILL BE SEARCHED FOR HEIRS +// C++20 modules very unstable in clangd :( +template +struct StanzaErrorImpl : StanzaBaseError { + static constexpr auto kDefaultName = "error"; + static constexpr auto kDefaultNamespace = "urn:ietf:params:xml:ns:xmpp-stanzas"; + static inline const auto kKebabCaseName = static_cast(utils::ToKebabCaseName()); + + static constexpr auto kErrorMessage = [] -> std::string_view { + static constexpr auto name = nameof::nameof_short_type(); + static constexpr auto str = [] { + return std::array{std::string_view{"Stanza IQ Error: "}, std::string_view{name}, std::string_view{"\0", 1}} | std::views::join; + }; + static constexpr auto array = str() | std::ranges::to>>(); + return {array.data(), array.size() - 1}; + }(); + + std::optional by{}; + std::string type; + + // TODO(unknown): Add "optional text children" support for stanza error. Check "XML Stanzas" -> "Syntax" for more details + static constexpr auto TryParse(xmlpp::Element* element) -> std::optional { + if(not element) { + return std::nullopt; + } + + auto by = element->get_attribute("by"); + auto type = element->get_attribute("type"); + if(not type) { + return std::nullopt; + } + + auto node = element->get_first_child(kKebabCaseName); + if(not node) { + return std::nullopt; + } + + T obj; + obj.type = type->get_value(); + if(by) { + obj.by = std::optional{by->get_value()}; + } + return obj; + } + static constexpr auto Parse(xmlpp::Element* element) -> T { + return TryParse(element).value(); + } + friend constexpr auto operator<<(xmlpp::Element* element, const T& obj) -> void { + element->set_attribute("type", obj.type); + if(obj.by) { + element->set_attribute("by", *obj.by); + } + + auto node = element->add_child_element(kKebabCaseName); + node->set_namespace_declaration(kDefaultNamespace); + } + constexpr auto operator==(const StanzaErrorImpl&) const -> bool { + return true; + }; + [[nodiscard]] constexpr auto what() const noexcept -> const char* override { + return kErrorMessage.data(); + } +}; + +// Helper class to prevent parsing response stream into an expected return type if its name is an 'error' +struct UnknownStanzaError : StanzaBaseError { + static constexpr auto kDefaultName = "stream:error"; + static constexpr std::string_view kErrorMessage = "Unknown XMPP stream error"; + + static constexpr auto TryParse(xmlpp::Element* element) { + return std::optional{UnknownStanzaError{}}; + } + static constexpr auto Parse(xmlpp::Element* element) { + return TryParse(element).value(); + } + friend constexpr auto operator<<(xmlpp::Element* element, const UnknownStanzaError& obj) -> void { + throw std::format("'{}' must never be written into the real stream!", kErrorMessage); + } + constexpr auto operator==(const UnknownStanzaError&) const -> bool { + return true; + }; + [[nodiscard]] constexpr auto what() const noexcept -> const char* override { + return kErrorMessage.data(); + } +}; + +struct BadRequest : StanzaErrorImpl {}; +struct Conflict : StanzaErrorImpl {}; +struct FeatureNotImplemented : StanzaErrorImpl {}; +struct Forbidden : StanzaErrorImpl {}; +struct Gone : StanzaErrorImpl {}; +struct InternalServerError : StanzaErrorImpl {}; +struct ItemNotFound : StanzaErrorImpl {}; +struct JidMalformed : StanzaErrorImpl {}; +struct NotAcceptable : StanzaErrorImpl {}; +struct NotAllowed : StanzaErrorImpl {}; +struct NotAuthorized : StanzaErrorImpl {}; +struct PolicyViolation : StanzaErrorImpl {}; +struct RecipientUnavailable : StanzaErrorImpl {}; +struct Redirect : StanzaErrorImpl {}; +struct RegistrationRequired : StanzaErrorImpl {}; +struct RemoteServerNotFound : StanzaErrorImpl {}; +struct RemoteServerTimeout : StanzaErrorImpl {}; +struct ResourceConstraint : StanzaErrorImpl {}; +struct ServiceUnavailable : StanzaErrorImpl {}; +struct SubscriptionRequired : StanzaErrorImpl {}; +struct UndefinedCondition : StanzaErrorImpl {}; +struct UnexpectedRequest : StanzaErrorImpl {}; + +using StanzaError = std::variant; + +static_assert(std::is_same_v - 1, StanzaError>, UnknownStanzaError>, + "'UnknownStanzaError' must be at the end of 'StanzaError' variant"); + +} // namespace larra::xmpp::stanza::error diff --git a/tests/iq.cpp b/tests/iq.cpp index 1dae134..833711c 100644 --- a/tests/iq.cpp +++ b/tests/iq.cpp @@ -69,7 +69,7 @@ TEST(IQ, ParseForbiddenError) { ASSERT_TRUE(std::holds_alternative(iqRes)); auto errorRes = std::get(iqRes); - ASSERT_TRUE(std::holds_alternative(errorRes.payload)); + ASSERT_TRUE(std::holds_alternative(errorRes.payload)); } TEST(IQ, IqErrThrowVisitorThrow) { @@ -87,7 +87,7 @@ TEST(IQ, IqErrThrowVisitorThrow) { 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) { + } catch(const stanza::error::StanzaBaseError& err) { ASSERT_STREQ(throwErrMsg, err.what()); return; } catch(const std::runtime_error& err) { @@ -114,7 +114,7 @@ TEST(IQ, IqErrThrowVisitorThrowGet) { 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) { + } catch(const stanza::error::StanzaBaseError& err) { ASSERT_TRUE(false) << "\tERROR: Invalid throw type throw"; } catch(const std::runtime_error& err) { ASSERT_STREQ(throwErrMsg, err.what()); @@ -141,7 +141,7 @@ TEST(IQ, IqErrThrowVisitorThrowSet) { 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) { + } catch(const stanza::error::StanzaBaseError& err) { ASSERT_TRUE(false) << "\tERROR: Invalid throw type throw"; } catch(const std::runtime_error& err) { ASSERT_STREQ(throwErrMsg, err.what());