diff --git a/components/core/CMakeLists.txt b/components/core/CMakeLists.txt index 2c3479afd8..38ba22edfe 100644 --- a/components/core/CMakeLists.txt +++ b/components/core/CMakeLists.txt @@ -448,7 +448,6 @@ set(SOURCE_FILES_unitTest src/clp/DictionaryEntry.hpp src/clp/DictionaryReader.hpp src/clp/DictionaryWriter.hpp - src/clp/error_handling/ErrorCode.hpp src/clp/EncodedVariableInterpreter.cpp src/clp/EncodedVariableInterpreter.hpp src/clp/ErrorCode.hpp @@ -644,7 +643,6 @@ set(SOURCE_FILES_unitTest tests/test-clp_s-search.cpp tests/test-EncodedVariableInterpreter.cpp tests/test-encoding_methods.cpp - tests/test-error_handling.cpp tests/test-ffi_IrUnitHandlerInterface.cpp tests/test-ffi_KeyValuePairLogEvent.cpp tests/test-ffi_SchemaTree.cpp @@ -701,6 +699,7 @@ target_link_libraries(unitTest clp::regex_utils clp::string_utils yaml-cpp::yaml-cpp + ystdlib::error_handling ${LIBLZMA_LIBRARIES} ZStd::ZStd ) diff --git a/components/core/src/clp/error_handling/ErrorCode.hpp b/components/core/src/clp/error_handling/ErrorCode.hpp deleted file mode 100644 index 230fa8cb16..0000000000 --- a/components/core/src/clp/error_handling/ErrorCode.hpp +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef CLP_ERROR_HANDLING_ERRORCODE_HPP -#define CLP_ERROR_HANDLING_ERRORCODE_HPP - -#include -#include -#include -#include - -namespace clp::error_handling { -/** - * Concept that defines a template parameter of an integer-based error code enumeration. - * @tparam Type - */ -template -concept ErrorCodeEnumType = std::is_enum_v && requires(Type type) { - { - static_cast>(type) - } -> std::convertible_to; -}; - -/** - * Template that defines a `std::error_category` of the given set of error code enumeration. - * @tparam ErrorCodeEnum - */ -template -class ErrorCategory : public std::error_category { -public: - // Methods implementing `std::error_category` - /** - * Gets the error category name. - * Note: A specialization must be explicitly implemented for each valid `ErrorCodeEnum`. - * @return The name of the error category. - */ - [[nodiscard]] auto name() const noexcept -> char const* override; - - /** - * Gets the descriptive message associated with the given error. - * @param error_num - * @return The descriptive message for the error. - */ - [[nodiscard]] auto message(int error_num) const -> std::string override { - return message(static_cast(error_num)); - } - - /** - * @param error_num - * @param condition - * @return Whether the error condition of the given error matches the given condition. - */ - [[nodiscard]] auto - equivalent(int error_num, std::error_condition const& condition) const noexcept - -> bool override { - return equivalent(static_cast(error_num), condition); - } - - // Methods - /** - * Gets the descriptive message associated with the given error. - * Note: A specialization must be explicitly implemented for each valid `ErrorCodeEnum`. - * @param error_enum. - * @return The descriptive message for the error. - */ - [[nodiscard]] auto message(ErrorCodeEnum error_enum) const -> std::string; - - /** - * Note: A specialization can be implemented to create error enum to error condition mappings. - * @param error_num - * @param condition - * @return Whether the error condition of the given error matches the given condition. - */ - [[nodiscard]] auto - equivalent(ErrorCodeEnum error_enum, std::error_condition const& condition) const noexcept - -> bool; -}; - -/** - * Template class that defines an error code. An error code is represented by a error enum value and - * the associated error category. This template class is designed to be `std::error_code` - * compatible, meaning that every instance of this class can be used to construct a corresponded - * `std::error_code` instance, or compare with a `std::error_code` instance to inspect a specific - * error. - * @tparam ErrorCodeEnum - */ -template -class ErrorCode { -public: - // Constructor - ErrorCode(ErrorCodeEnum error) : m_error{error} {} - - /** - * @return The underlying error code enum. - */ - [[nodiscard]] auto get_error() const -> ErrorCodeEnum { return m_error; } - - /** - * @return The error code as an error number. - */ - [[nodiscard]] auto get_error_num() const -> int { return static_cast(m_error); } - - /** - * @return The reference to the singleton of the corresponded error category. - */ - [[nodiscard]] static constexpr auto get_category() -> ErrorCategory const& { - return cCategory; - } - -private: - static inline ErrorCategory const cCategory; - - ErrorCodeEnum m_error; -}; - -/** - * @tparam ErrorCodeEnum - * @param error - * @return Constructed `std::error_code` from the given `ErrorCode` instance. - */ -template -[[nodiscard]] auto make_error_code(ErrorCode error) -> std::error_code; - -template -auto ErrorCategory::equivalent( - ErrorCodeEnum error_enum, - std::error_condition const& condition -) const noexcept -> bool { - return std::error_category::default_error_condition(static_cast(error_enum)) == condition; -} - -template -auto make_error_code(ErrorCode error) -> std::error_code { - return {error.get_error_num(), ErrorCode::get_category()}; -} -} // namespace clp::error_handling - -/** - * The macro to create a specialization of `std::is_error_code_enum` for a given type T. Only types - * that are marked with this macro will be considered as a valid CLP error code enum, and thus used - * to specialize `ErrorCode` and `ErrorCategory` templates. - */ -// NOLINTBEGIN(bugprone-macro-parentheses, cppcoreguidelines-macro-usage) -#define CLP_ERROR_HANDLING_MARK_AS_ERROR_CODE_ENUM(T) \ - template <> \ - struct std::is_error_code_enum> : std::true_type { \ - static_assert(std::is_enum_v); \ - }; -// NOLINTEND(bugprone-macro-parentheses, cppcoreguidelines-macro-usage) - -#endif // CLP_ERROR_HANDLING_ERRORCODE_HPP diff --git a/components/core/src/clp/ffi/ir_stream/IrErrorCode.cpp b/components/core/src/clp/ffi/ir_stream/IrErrorCode.cpp index f9a00ca1eb..f99327c856 100644 --- a/components/core/src/clp/ffi/ir_stream/IrErrorCode.cpp +++ b/components/core/src/clp/ffi/ir_stream/IrErrorCode.cpp @@ -2,8 +2,10 @@ #include -using IrErrorCategory = clp::error_handling::ErrorCategory; +#include + using clp::ffi::ir_stream::IrErrorCodeEnum; +using IrErrorCategory = ystdlib::error_handling::ErrorCategory; template <> auto IrErrorCategory::name() const noexcept -> char const* { diff --git a/components/core/src/clp/ffi/ir_stream/IrErrorCode.hpp b/components/core/src/clp/ffi/ir_stream/IrErrorCode.hpp index 8eaad4e16b..e384f369f1 100644 --- a/components/core/src/clp/ffi/ir_stream/IrErrorCode.hpp +++ b/components/core/src/clp/ffi/ir_stream/IrErrorCode.hpp @@ -3,7 +3,7 @@ #include -#include "../../error_handling/ErrorCode.hpp" +#include namespace clp::ffi::ir_stream { /** @@ -16,9 +16,9 @@ enum class IrErrorCodeEnum : uint8_t { IncompleteStream, }; -using IrErrorCode = clp::error_handling::ErrorCode; +using IrErrorCode = ystdlib::error_handling::ErrorCode; } // namespace clp::ffi::ir_stream -CLP_ERROR_HANDLING_MARK_AS_ERROR_CODE_ENUM(clp::ffi::ir_stream::IrErrorCodeEnum); +YSTDLIB_ERROR_HANDLING_MARK_AS_ERROR_CODE_ENUM(clp::ffi::ir_stream::IrErrorCodeEnum); #endif // CLP_IRERRORCODE_HPP diff --git a/components/core/tests/test-error_handling.cpp b/components/core/tests/test-error_handling.cpp deleted file mode 100644 index 44327c8332..0000000000 --- a/components/core/tests/test-error_handling.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "../src/clp/error_handling/ErrorCode.hpp" -#include "../src/clp/ffi/ir_stream/IrErrorCode.hpp" - -using clp::error_handling::ErrorCategory; -using clp::error_handling::ErrorCode; -using std::string; -using std::string_view; - -namespace { -enum class AlwaysSuccessErrorCodeEnum : uint8_t { - Success = 0 -}; - -enum class BinaryErrorCodeEnum : uint8_t { - Success = 0, - Failure -}; - -using AlwaysSuccessErrorCode = ErrorCode; -using AlwaysSuccessErrorCategory = ErrorCategory; -using BinaryErrorCode = ErrorCode; -using BinaryErrorCategory = ErrorCategory; - -constexpr string_view cAlwaysSuccessErrorCategoryName{"Always Success Error Code"}; -constexpr string_view cBinaryTestErrorCategoryName{"Binary Error Code"}; -constexpr string_view cSuccessErrorMsg{"Success"}; -constexpr string_view cFailureErrorMsg{"Failure"}; -constexpr string_view cUnrecognizedErrorCode{"Unrecognized Error Code"}; -constexpr std::array cFailureConditions{std::errc::not_connected, std::errc::timed_out}; -constexpr std::array cNoneFailureConditions{std::errc::broken_pipe, std::errc::address_in_use}; -} // namespace - -CLP_ERROR_HANDLING_MARK_AS_ERROR_CODE_ENUM(AlwaysSuccessErrorCodeEnum); -CLP_ERROR_HANDLING_MARK_AS_ERROR_CODE_ENUM(BinaryErrorCodeEnum); - -template <> -auto AlwaysSuccessErrorCategory::name() const noexcept -> char const* { - return cAlwaysSuccessErrorCategoryName.data(); -} - -template <> -auto AlwaysSuccessErrorCategory::message(AlwaysSuccessErrorCodeEnum error_enum) const -> string { - switch (error_enum) { - case AlwaysSuccessErrorCodeEnum::Success: - return string{cSuccessErrorMsg}; - default: - return string{cUnrecognizedErrorCode}; - } -} - -template <> -auto BinaryErrorCategory::name() const noexcept -> char const* { - return cBinaryTestErrorCategoryName.data(); -} - -template <> -auto BinaryErrorCategory::message(BinaryErrorCodeEnum error_enum) const -> string { - switch (error_enum) { - case BinaryErrorCodeEnum::Success: - return string{cSuccessErrorMsg}; - case BinaryErrorCodeEnum::Failure: - return string{cFailureErrorMsg}; - default: - return string{cUnrecognizedErrorCode}; - } -} - -template <> -auto BinaryErrorCategory::equivalent( - BinaryErrorCodeEnum error_enum, - std::error_condition const& condition -) const noexcept -> bool { - switch (error_enum) { - case BinaryErrorCodeEnum::Failure: - return std::any_of( - cFailureConditions.cbegin(), - cFailureConditions.cend(), - [&](auto failure_condition) -> bool { return condition == failure_condition; } - ); - default: - return false; - } -} - -TEST_CASE("test_error_code_implementation", "[error_handling][ErrorCode]") { - // Test error codes within the same error category - BinaryErrorCode const success{BinaryErrorCodeEnum::Success}; - std::error_code const success_error_code{success}; - REQUIRE((success == success_error_code)); - REQUIRE((cSuccessErrorMsg == success_error_code.message())); - REQUIRE((BinaryErrorCode::get_category() == success_error_code.category())); - REQUIRE((cBinaryTestErrorCategoryName == success_error_code.category().name())); - - BinaryErrorCode const failure{BinaryErrorCodeEnum::Failure}; - std::error_code const failure_error_code{failure}; - REQUIRE((failure == failure_error_code)); - REQUIRE((cFailureErrorMsg == failure_error_code.message())); - REQUIRE((BinaryErrorCode::get_category() == failure_error_code.category())); - REQUIRE((cBinaryTestErrorCategoryName == failure_error_code.category().name())); - std::for_each( - cFailureConditions.cbegin(), - cFailureConditions.cend(), - [&](auto failure_condition) { REQUIRE((failure_error_code == failure_condition)); } - ); - std::for_each( - cNoneFailureConditions.cbegin(), - cNoneFailureConditions.cend(), - [&](auto none_failure_condition) { - REQUIRE((failure_error_code != none_failure_condition)); - } - ); - - REQUIRE((success_error_code != failure_error_code)); - REQUIRE((success_error_code.category() == failure_error_code.category())); - - AlwaysSuccessErrorCode const always_success{AlwaysSuccessErrorCodeEnum::Success}; - std::error_code const always_success_error_code{always_success}; - REQUIRE((always_success_error_code == always_success)); - REQUIRE((cSuccessErrorMsg == always_success_error_code.message())); - REQUIRE((AlwaysSuccessErrorCode::get_category() == always_success_error_code.category())); - REQUIRE((cAlwaysSuccessErrorCategoryName == always_success_error_code.category().name())); - - // Compare error codes from different error category - // Error codes that have the same value or message won't be the same with each other if they are - // from different error categories. - REQUIRE((success_error_code.value() == always_success_error_code.value())); - REQUIRE((success_error_code.message() == always_success_error_code.message())); - REQUIRE((success_error_code.category() != always_success_error_code.category())); - REQUIRE((success_error_code != always_success_error_code)); - REQUIRE((AlwaysSuccessErrorCode{AlwaysSuccessErrorCodeEnum::Success} != success_error_code)); - REQUIRE((BinaryErrorCode{BinaryErrorCodeEnum::Success} != always_success_error_code)); -} - -TEST_CASE("test_ir_error_code", "[error_handling][ErrorCode][IrErrorCode]") { - using clp::ffi::ir_stream::IrErrorCode; - using clp::ffi::ir_stream::IrErrorCodeEnum; - - auto assert_error_code_matches_error_code_enum = [](IrErrorCodeEnum error_code_enum) -> bool { - std::error_code const error_code{IrErrorCode{error_code_enum}}; - return error_code == IrErrorCode{error_code_enum}; - }; - - REQUIRE(assert_error_code_matches_error_code_enum(IrErrorCodeEnum::DecodingMethodFailure)); - REQUIRE(assert_error_code_matches_error_code_enum(IrErrorCodeEnum::EndOfStream)); - REQUIRE(assert_error_code_matches_error_code_enum(IrErrorCodeEnum::IncompleteStream)); -} diff --git a/lint-tasks.yml b/lint-tasks.yml index fe5a87e657..88cba0a822 100644 --- a/lint-tasks.yml +++ b/lint-tasks.yml @@ -249,7 +249,6 @@ tasks: - "{{.G_CORE_COMPONENT_DIR}}/src/clp/ffi/ir_stream/encoding_methods.cpp" - "{{.G_CORE_COMPONENT_DIR}}/src/clp/ffi/ir_stream/encoding_methods.hpp" - "{{.G_CORE_COMPONENT_DIR}}/src/clp/ffi/ir_stream/ir_unit_deserialization_methods.hpp" - - "{{.G_CORE_COMPONENT_DIR}}/src/clp/ffi/ir_stream/IrErrorCode.cpp" - "{{.G_CORE_COMPONENT_DIR}}/src/clp/ffi/ir_stream/IrUnitHandlerInterface.hpp" - "{{.G_CORE_COMPONENT_DIR}}/src/clp/ffi/ir_stream/protocol_constants.hpp" - "{{.G_CORE_COMPONENT_DIR}}/src/clp/ffi/ir_stream/Serializer.cpp"