diff --git a/.cirrus.yaml b/.cirrus.yaml index 2638c532c9..e63a2f05cd 100644 --- a/.cirrus.yaml +++ b/.cirrus.yaml @@ -125,7 +125,7 @@ ubuntu_22_04_aarch64_build_task: test_binaries_cache: folder: iox-tests-bin reupload_on_changes: true - fingerprint_key: $CIRRUS_OS_ubuntu_22_04_aarch64_test_binaries_cache + fingerprint_key: $CIRRUS_OS_ubuntu_22_04_aarch64_test_binaries_cache_$CIRRUS_BRANCH build_script: <<: *IOX_POSIX_CLEAN_BUILD_STRICT_WITH_ADDITIONAL_USER populate_test_binary_folder_script: @@ -140,7 +140,7 @@ ubuntu_22_04_aarch64_test_task: test_binaries_cache: folder: iox-tests-bin reupload_on_changes: false - fingerprint_key: $CIRRUS_OS_ubuntu_22_04_aarch64_test_binaries_cache + fingerprint_key: $CIRRUS_OS_ubuntu_22_04_aarch64_test_binaries_cache_$CIRRUS_BRANCH test_script: <<: *IOX_RUN_TESTS @@ -157,7 +157,7 @@ arch_linux_x64_gcc_8_3_aka_qnx_canary_build_task: test_binaries_cache: folder: iox-tests-bin reupload_on_changes: true - fingerprint_key: $CIRRUS_OS_archlinux_x64_gcc_8_3_aka_qnx_canary_test_binaries_cache + fingerprint_key: $CIRRUS_OS_archlinux_x64_gcc_8_3_aka_qnx_canary_test_binaries_cache_$CIRRUS_BRANCH env: # use GCC 8.3 which corresponds to QCC 8.3 on QNX 7.1 CC: gcc-8 @@ -176,7 +176,7 @@ arch_linux_x64_gcc_8_3_aka_qnx_canary_test_task: test_binaries_cache: folder: iox-tests-bin reupload_on_changes: false - fingerprint_key: $CIRRUS_OS_archlinux_x64_gcc_8_3_aka_qnx_canary_test_binaries_cache + fingerprint_key: $CIRRUS_OS_archlinux_x64_gcc_8_3_aka_qnx_canary_test_binaries_cache_$CIRRUS_BRANCH test_script: <<: *IOX_RUN_TESTS @@ -194,7 +194,7 @@ arch_linux_x64_build_task: test_binaries_cache: folder: iox-tests-bin reupload_on_changes: true - fingerprint_key: $CIRRUS_OS_archlinux_x64_test_binaries_cache + fingerprint_key: $CIRRUS_OS_archlinux_x64_test_binaries_cache_$CIRRUS_BRANCH build_script: <<: *IOX_POSIX_CLEAN_BUILD_STRICT_WITH_ADDITIONAL_USER populate_test_binary_folder_script: @@ -210,7 +210,7 @@ arch_linux_x64_test_task: test_binaries_cache: folder: iox-tests-bin reupload_on_changes: false - fingerprint_key: $CIRRUS_OS_archlinux_x64_test_binaries_cache + fingerprint_key: $CIRRUS_OS_archlinux_x64_test_binaries_cache_$CIRRUS_BRANCH test_script: <<: *IOX_RUN_TESTS @@ -227,7 +227,7 @@ freebsd_x64_build_task: test_binaries_cache: folder: iox-tests-bin reupload_on_changes: true - fingerprint_key: $CIRRUS_OS_freebsd_x64_test_binaries_cache + fingerprint_key: $CIRRUS_OS_freebsd_x64_test_binaries_cache_$CIRRUS_BRANCH setup_script: - pkg install -y cmake git ncurses bash wget - ln -s /usr/local/bin/bash /bin/bash @@ -245,7 +245,7 @@ freebsd_x64_test_task: test_binaries_cache: folder: iox-tests-bin reupload_on_changes: false - fingerprint_key: $CIRRUS_OS_freebsd_x64_test_binaries_cache + fingerprint_key: $CIRRUS_OS_freebsd_x64_test_binaries_cache_$CIRRUS_BRANCH test_script: <<: *IOX_RUN_TESTS @@ -263,7 +263,7 @@ macos_aarch64_build_task: test_binaries_cache: folder: iox-tests-bin reupload_on_changes: true - fingerprint_key: $CIRRUS_OS_macOS_aarch64_test_binaries_cache + fingerprint_key: $CIRRUS_OS_macOS_aarch64_test_binaries_cache_$CIRRUS_BRANCH setup_script: - brew install ncurses build_script: @@ -281,7 +281,7 @@ macos_aarch64_test_task: test_binaries_cache: folder: iox-tests-bin reupload_on_changes: false - fingerprint_key: $CIRRUS_OS_macOS_aarch64_test_binaries_cache + fingerprint_key: $CIRRUS_OS_macOS_aarch64_test_binaries_cache_$CIRRUS_BRANCH env: # No timing tests on macOS GTEST_FILTER: "-*TimingTest*" diff --git a/doc/aspice_swe3_4/example/iceoryx_component/test/moduletests/test_component_modules.cpp b/doc/aspice_swe3_4/example/iceoryx_component/test/moduletests/test_component_modules.cpp index 00cd62489e..49db361152 100644 --- a/doc/aspice_swe3_4/example/iceoryx_component/test/moduletests/test_component_modules.cpp +++ b/doc/aspice_swe3_4/example/iceoryx_component/test/moduletests/test_component_modules.cpp @@ -14,16 +14,19 @@ // // SPDX-License-Identifier: Apache-2.0 -#include -#include -using namespace ::testing; -using ::testing::_; +#include "iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp" +#include "iceoryx_hoofs/testing/testing_logger.hpp" +#include +#include int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); + iox::testing::TestingLogger::init(); + iox::testing::TestingErrorHandler::init(); + return RUN_ALL_TESTS(); } diff --git a/doc/design/error_reporting.md b/doc/design/error_reporting.md index bfd842e4c1..6ed521a823 100644 --- a/doc/design/error_reporting.md +++ b/doc/design/error_reporting.md @@ -157,15 +157,15 @@ Fatal errors can be conditionally reported in a similar way. IOX_REPORT_FATAL_IF(x<0, Code::OutOfBounds); ``` -### Require That a Condition Holds +### Enforce a Condition -Similarly we can conditionally check whether a condition does hold and report a fatal error in +Similarly we can conditionally enforce whether a condition does hold and report a fatal error in the case that it does not hold ```cpp int x; // ... -IOX_REQUIRE(x>=0, "required condition violation message"); +IOX_ENFORCE(x>=0, "enforce violation message"); ``` The condition is required to hold and this requirement is always checked. @@ -173,68 +173,47 @@ If the condition does not hold, panic is invoked and the execution stops. This should be used for conditions that may not hold on the correct path, e.g. for error cases. It should not be used for assumptions that have to be true in correct code -(use `IOX_ASSUME` or `IOX_PRECONDITION` for this). +(use `IOX_ASSERT` for this). Note that no condition can generally be enforced in the sense that it must be true and no checking is required. -## Using the API to Check Contracts and Assumptions +### Assert a Condition -The following checks can be disabled and are intended to increase safety during incorrect +The following check is disabled for release builds and is intended to increase safety during incorrect use, specifically detect incorrect use at runtime. -This means they should only be used for checks that are not needed in correct code (i.e. defensive +This means it should only be used for checks that are not needed in correct code (i.e. defensive programming). -If these checks are disabled, there is no overhead in the code, i.e. no checking or reporting takes place. - -### Checking Preconditions - -A precondition check +When check is disabled, there is no overhead in the code, i.e. no checking or reporting takes place. ```cpp int f(int x) { -IOX_PRECONDITION(x>=0, "precondition violation message"); + IOX_ASSERT(x>=0, "precondition violation message"); -// ... + // some computation + int y = g(x); + + IOX_ASSERT(y>=0, "assumption violation message"); + // proceed assuming that y>=0 holds } ``` -is used to verify assumptions **BEFORE** any logic in the function body is executed. Technically copy +Is can be used to verify preconditions before any logic in the function body is executed. Technically copy constructors may run before any condition can be checked, and there is also the possibility of reordering if the following code does not depend on the condition at all. This is not a problem since any reordering is not allowed to affect the observable result. Specifically it cannot affect the value of the precondition itself as this would change the observable behaviour. +When used in the middle of a function it serves as documentation of assumptions that should hold at this +point in the code before the next statement and can be used e.g. to check for out-of-bounds accesses. It can +also be used to check postconditions. + In case of violation, the violation and a (potentially empty) message are forwarded to the backend, panic is invoked and execution stops. -The verification can be optionally disabled, and hence this also documents assumptions of the -function itself. - -### Checking Assumptions - -Checking assumptions is similar to checking preconditions, but can happen anywhere in the code. - -```cpp -int f(int x) -{ - // some computation - int y = g(x); - - IOX_ASSUME(y>=0, "assumption violation message"); - // proceed assuming that y>=0 holds -} -``` - -These serve as documentation of assumptions that should hold at this point in the code before the -next statement and can be used e.g. to check for out-of-bounds accesses. It can also be used to -check postconditions. - -It should not be used at the start of a function body and instead replaced with a precondition check -in this case. - ## Marking Unreachable Code It is also possible to explicitly state that code is supposed to be unreachable. @@ -394,7 +373,7 @@ Alternatively the shorthand version can be used int algorithm(int x) { // require that the condition holds or raise a fatal error - IOX_REQUIRE(!errorCondition(x), SomeError); + IOX_REPORT_FATAL_IF(errorCondition(x), SomeError); return 42; } ``` @@ -425,7 +404,7 @@ These are 8. `errors.hpp` : supported error types and related free functions Additionally there is the `assertions.hpp` in `iceoryx_hoofs/reporting` which contains the `IOX_PANIC`, -`IOX_UNREACHABLE`, `IOX_REQUIRE`, `IOX_PRECONDITION` and `IOX_ASSUME` macros +`IOX_UNREACHABLE`, `IOX_ASSERT` and `IOX_ENFORCE` macros. All the files focus on singular aspects to allow fine-grained inclusion. All definitions have to reside in `iox::er`, which is considered a private (detail) namespace @@ -463,7 +442,7 @@ The default implementation does not depend on any code that uses the error repor ### Testing All testing related definitions are located in `iceoryx_hoofs/testing/error_reporting`. -These are the definition of `TestErrorHandler` in `testing_error_handler.hpp` and auxiliary +These are the definition of `TestingErrorHandler` in `testing_error_handler.hpp` and auxiliary functions in `testing_support.hpp` to be used in tests to verify errors. The latter can be extended as required. diff --git a/iceoryx_binding_c/test/moduletests/main.cpp b/iceoryx_binding_c/test/moduletests/main.cpp index 4f9c9369ad..079b53af00 100644 --- a/iceoryx_binding_c/test/moduletests/main.cpp +++ b/iceoryx_binding_c/test/moduletests/main.cpp @@ -15,6 +15,7 @@ // // SPDX-License-Identifier: Apache-2.0 +#include "iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp" #include "iceoryx_hoofs/testing/testing_logger.hpp" #include "test.hpp" @@ -24,9 +25,6 @@ #include "test_types_storage_size.hpp" -using namespace ::testing; -using ::testing::_; - // in case this isn't executed before the other tests, just call // 'checkIceoryxBindingCStorageSizes' directly in main TEST(SanityCheck, CheckStorageSizeAndAlingment) @@ -41,6 +39,7 @@ int main(int argc, char* argv[]) ::testing::InitGoogleTest(&argc, argv); iox::testing::TestingLogger::init(); + iox::testing::TestingErrorHandler::init(); return RUN_ALL_TESTS(); } diff --git a/iceoryx_hoofs/reporting/include/iox/assertions.hpp b/iceoryx_hoofs/reporting/include/iox/assertions.hpp index 973b277886..ce446bccf3 100644 --- a/iceoryx_hoofs/reporting/include/iox/assertions.hpp +++ b/iceoryx_hoofs/reporting/include/iox/assertions.hpp @@ -51,50 +51,35 @@ //* Instead a special internal error type is used. //************************************************************************************************ -/// @brief report fatal required condition violation if expr evaluates to false -/// @note for conditions that may actually happen during correct use +/// @brief only for debug builds: report fatal assert violation if expr evaluates to false +/// @note for conditions that should not happen with correct use /// @param expr boolean expression that must hold /// @param message message to be forwarded in case of violation -#define IOX_REQUIRE(expr, message) \ +#define IOX_ASSERT(expr, message) \ do \ { \ - if (!(expr)) \ + if (iox::er::Configuration::CHECK_ASSERT && !(expr)) \ { \ - iox::er::forwardFatalError(iox::er::Violation::createRequiredConditionViolation(), \ - iox::er::REQUIRED_CONDITION_VIOLATION, \ - CURRENT_SOURCE_LOCATION, \ - message); /* @todo iox-#1032 add strigified 'expr' as '#expr' */ \ - } \ - } while (false) - -/// @brief if enabled: report fatal precondition violation if expr evaluates to false -/// @param expr boolean expression that must hold upon entry of the function it appears in -/// @param message message to be forwarded in case of violation -#define IOX_PRECONDITION(expr, message) \ - do \ - { \ - if (iox::er::Configuration::CHECK_PRECONDITIONS && !(expr)) \ - { \ - iox::er::forwardFatalError(iox::er::Violation::createPreconditionViolation(), \ - iox::er::PRECONDITION_VIOLATION, \ + iox::er::forwardFatalError(iox::er::Violation::createAssertViolation(), \ + iox::er::ASSERT_VIOLATION, \ CURRENT_SOURCE_LOCATION, \ message); \ } \ } while (false) -/// @brief if enabled: report fatal assumption violation if expr evaluates to false -/// @note for conditions that should not happen with correct use +/// @brief report fatal enforce violation if expr evaluates to false +/// @note for conditions that may actually happen during correct use /// @param expr boolean expression that must hold /// @param message message to be forwarded in case of violation -#define IOX_ASSUME(expr, message) \ +#define IOX_ENFORCE(expr, message) \ do \ { \ - if (iox::er::Configuration::CHECK_ASSUMPTIONS && !(expr)) \ + if (!(expr)) \ { \ - iox::er::forwardFatalError(iox::er::Violation::createAssumptionViolation(), \ - iox::er::ASSUMPTION_VIOLATION, \ + iox::er::forwardFatalError(iox::er::Violation::createEnforceViolation(), \ + iox::er::ENFORCE_VIOLATION, \ CURRENT_SOURCE_LOCATION, \ - message); \ + message); /* @todo iox-#1032 add strigified 'expr' as '#expr' */ \ } \ } while (false) diff --git a/iceoryx_hoofs/reporting/include/iox/error_reporting/configuration.hpp b/iceoryx_hoofs/reporting/include/iox/error_reporting/configuration.hpp index b724470e16..92ee4a9b9e 100644 --- a/iceoryx_hoofs/reporting/include/iox/error_reporting/configuration.hpp +++ b/iceoryx_hoofs/reporting/include/iox/error_reporting/configuration.hpp @@ -39,8 +39,7 @@ struct ConfigurationParameters { static_assert(std::is_same::value, "Incorrect configuration tag type"); - static constexpr bool CHECK_PRECONDITIONS{true}; - static constexpr bool CHECK_ASSUMPTIONS{true}; + static constexpr bool CHECK_ASSERT{true}; /// @todo iox-#1032 deactive for release builds }; // used by the API to obtain the compile time parameters diff --git a/iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/configuration.hpp b/iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/configuration.hpp index bb5b2c6a3a..9e70c62e4d 100644 --- a/iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/configuration.hpp +++ b/iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/configuration.hpp @@ -30,8 +30,7 @@ namespace er template <> struct ConfigurationParameters { - static constexpr bool CHECK_PRECONDITIONS{true}; - static constexpr bool CHECK_ASSUMPTIONS{true}; + static constexpr bool CHECK_ASSERT{true}; /// @todo iox-#1032 deactive for release builds }; } // namespace er diff --git a/iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/error_handler_interface.hpp b/iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/error_handler_interface.hpp index 82c822da98..97b534718c 100644 --- a/iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/error_handler_interface.hpp +++ b/iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/error_handler_interface.hpp @@ -17,9 +17,9 @@ #ifndef IOX_HOOFS_REPORTING_ERROR_REPORTING_CUSTOM_ERROR_HANDLER_INTERFACE_HPP #define IOX_HOOFS_REPORTING_ERROR_REPORTING_CUSTOM_ERROR_HANDLER_INTERFACE_HPP -#include "iox/error_reporting/errors.hpp" #include "iox/error_reporting/source_location.hpp" #include "iox/error_reporting/types.hpp" +#include "iox/error_reporting/violation.hpp" namespace iox { diff --git a/iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/error_reporting_impl.hpp b/iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/error_reporting_impl.hpp index 4ecd253082..5cc3c64e0b 100644 --- a/iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/error_reporting_impl.hpp +++ b/iceoryx_hoofs/reporting/include/iox/error_reporting/custom/default/error_reporting_impl.hpp @@ -19,8 +19,9 @@ #include "iox/error_reporting/error_kind.hpp" #include "iox/error_reporting/error_logging.hpp" -#include "iox/error_reporting/errors.hpp" #include "iox/error_reporting/source_location.hpp" +#include "iox/error_reporting/types.hpp" +#include "iox/error_reporting/violation.hpp" #include "iox/error_reporting/custom/default/error_handler.hpp" #include "iox/error_reporting/custom/error_kind.hpp" @@ -130,40 +131,26 @@ inline void report(const SourceLocation& location, Kind kind, const Error& error } // namespace detail template -inline void report(const SourceLocation& location, iox::er::RequiredConditionViolationKind kind, const Error& error) +inline void report(const SourceLocation& location, iox::er::AssertViolationKind kind, const Error& error) { detail::report(location, kind, error, detail::NoMessage{}); } template -inline void report(const SourceLocation& location, iox::er::PreconditionViolationKind kind, const Error& error) +inline void report(const SourceLocation& location, iox::er::EnforceViolationKind kind, const Error& error) { detail::report(location, kind, error, detail::NoMessage{}); } -template -inline void report(const SourceLocation& location, iox::er::AssumptionViolationKind kind, const Error& error) -{ - detail::report(location, kind, error, detail::NoMessage{}); -} - -template -inline void -report(const SourceLocation& location, iox::er::RequiredConditionViolationKind kind, const Error& error, Message&& msg) -{ - detail::report(location, kind, error, std::forward(msg)); -} - template -inline void -report(const SourceLocation& location, iox::er::PreconditionViolationKind kind, const Error& error, Message&& msg) +inline void report(const SourceLocation& location, iox::er::AssertViolationKind kind, const Error& error, Message&& msg) { detail::report(location, kind, error, std::forward(msg)); } template inline void -report(const SourceLocation& location, iox::er::AssumptionViolationKind kind, const Error& error, Message&& msg) +report(const SourceLocation& location, iox::er::EnforceViolationKind kind, const Error& error, Message&& msg) { detail::report(location, kind, error, std::forward(msg)); } diff --git a/iceoryx_hoofs/reporting/include/iox/error_reporting/error_kind.hpp b/iceoryx_hoofs/reporting/include/iox/error_reporting/error_kind.hpp index f8fb8bd5c0..8829582dee 100644 --- a/iceoryx_hoofs/reporting/include/iox/error_reporting/error_kind.hpp +++ b/iceoryx_hoofs/reporting/include/iox/error_reporting/error_kind.hpp @@ -37,19 +37,14 @@ struct FatalKind static constexpr char const* name = "Fatal Error"; }; -struct RequiredConditionViolationKind +struct AssertViolationKind { - static constexpr char const* name = "Required Condition Violation"; + static constexpr char const* name = "Assert Violation"; }; -struct PreconditionViolationKind +struct EnforceViolationKind { - static constexpr char const* name = "Precondition Violation"; -}; - -struct AssumptionViolationKind -{ - static constexpr char const* name = "Assumption Violation"; + static constexpr char const* name = "EnforceViolation"; }; template @@ -68,17 +63,12 @@ struct IsFatal : public std::true_type }; template <> -struct IsFatal : public std::true_type -{ -}; - -template <> -struct IsFatal : public std::true_type +struct IsFatal : public std::true_type { }; template <> -struct IsFatal : public std::true_type +struct IsFatal : public std::true_type { }; @@ -97,34 +87,25 @@ bool constexpr isFatal(FatalKind) } template <> -bool constexpr isFatal(RequiredConditionViolationKind) -{ - return IsFatal::value; -} - -template <> -bool constexpr isFatal(PreconditionViolationKind) +bool constexpr isFatal(AssertViolationKind) { - return IsFatal::value; + return IsFatal::value; } template <> -bool constexpr isFatal(AssumptionViolationKind) +bool constexpr isFatal(EnforceViolationKind) { - return IsFatal::value; + return IsFatal::value; } // indicates serious condition, unable to continue constexpr FatalKind FATAL; -// indicates a bug (contract breach by caller) -constexpr RequiredConditionViolationKind REQUIRED_CONDITION_VIOLATION; - -// indicates a bug (contract breach by caller) -constexpr PreconditionViolationKind PRECONDITION_VIOLATION; +// indicates a bug (check only active in debug builds) +constexpr AssertViolationKind ASSERT_VIOLATION; -// indicates a bug (contract breach by callee) -constexpr AssumptionViolationKind ASSUMPTION_VIOLATION; +// indicates a bug (check always active) +constexpr EnforceViolationKind ENFORCE_VIOLATION; } // namespace er } // namespace iox diff --git a/iceoryx_hoofs/reporting/include/iox/error_reporting/macros.hpp b/iceoryx_hoofs/reporting/include/iox/error_reporting/macros.hpp index e2fe8d8ba7..72d9515363 100644 --- a/iceoryx_hoofs/reporting/include/iox/error_reporting/macros.hpp +++ b/iceoryx_hoofs/reporting/include/iox/error_reporting/macros.hpp @@ -19,6 +19,7 @@ #include "iox/error_reporting/configuration.hpp" #include "iox/error_reporting/error_forwarding.hpp" +#include "iox/error_reporting/types.hpp" #include "iox/error_reporting/source_location.hpp" diff --git a/iceoryx_hoofs/reporting/include/iox/error_reporting/types.hpp b/iceoryx_hoofs/reporting/include/iox/error_reporting/types.hpp index cb25d646ff..8f7a3897a2 100644 --- a/iceoryx_hoofs/reporting/include/iox/error_reporting/types.hpp +++ b/iceoryx_hoofs/reporting/include/iox/error_reporting/types.hpp @@ -18,12 +18,16 @@ #define IOX_HOOFS_REPORTING_ERROR_REPORTING_TYPES_HPP #include +#include namespace iox { namespace er { +static constexpr const char* UNKNOWN_ERROR_NAME = "unknown error"; +static constexpr const char* UNKNOWN_MODULE_NAME = "unknown module"; + // These are lightweight regular read/write types that do not require encapsulation (no invariants // can be broken). @@ -33,10 +37,6 @@ struct ErrorCode type value; - static constexpr type REQUIRED_CONDITION_VIOLATION{0}; - static constexpr type ASSUMPTION_VIOLATION{1}; - static constexpr type PRECONDITION_VIOLATION{2}; - constexpr explicit ErrorCode(uint32_t value) : value(value) { @@ -82,6 +82,44 @@ struct ModuleId } }; +// primary template is the identity +// this can be overriden by modules to handle specific errors +template +auto toError(ErrorLike&& value) +{ + return std::forward(value); +} + +template +inline ErrorCode toCode(const Error& error) +{ + return error.code(); +} + +template <> +inline ErrorCode toCode(const ErrorCode& error) +{ + return error; +} + +template +inline ModuleId toModule(const Error& error) +{ + return error.module(); +} + +template +inline const char* toModuleName(const Error&) +{ + return UNKNOWN_MODULE_NAME; +} + +template +inline const char* toErrorName(const Error&) +{ + return UNKNOWN_ERROR_NAME; +} + } // namespace er } // namespace iox diff --git a/iceoryx_hoofs/reporting/include/iox/error_reporting/errors.hpp b/iceoryx_hoofs/reporting/include/iox/error_reporting/violation.hpp similarity index 55% rename from iceoryx_hoofs/reporting/include/iox/error_reporting/errors.hpp rename to iceoryx_hoofs/reporting/include/iox/error_reporting/violation.hpp index b730c708cf..0b4d31857b 100644 --- a/iceoryx_hoofs/reporting/include/iox/error_reporting/errors.hpp +++ b/iceoryx_hoofs/reporting/include/iox/error_reporting/violation.hpp @@ -14,8 +14,8 @@ // // SPDX-License-Identifier: Apache-2.0 -#ifndef IOX_HOOFS_REPORTING_ERROR_REPORTING_ERRORS_HPP -#define IOX_HOOFS_REPORTING_ERROR_REPORTING_ERRORS_HPP +#ifndef IOX_HOOFS_ERROR_REPORTING_VIOLATION_HPP +#define IOX_HOOFS_ERROR_REPORTING_VIOLATION_HPP #include @@ -26,9 +26,6 @@ namespace iox namespace er { -static constexpr const char* UNKNOWN_MODULE_NAME = "unknown module"; -static constexpr const char* UNKNOWN_ERROR_NAME = "unknown error"; - // We expect an error to have the following interface // 1. ErrorCode code() const // 2. ModuleId module() const @@ -36,9 +33,20 @@ static constexpr const char* UNKNOWN_ERROR_NAME = "unknown error"; // By default, there are only error codes and violations. // Custom errors can be added but must satisfy the minimal interface. +enum class ViolationErrorCode : uint32_t +{ + ASSERT_VIOLATION, + ENFORCE_VIOLATION +}; + class Violation { public: + explicit Violation(ViolationErrorCode code) + : m_code(static_cast(code)) + { + } + explicit Violation(ErrorCode code) : m_code(code) { @@ -70,19 +78,14 @@ class Violation return !(*this == rhs); } - static Violation createRequiredConditionViolation() + static Violation createAssertViolation() { - return Violation(ErrorCode(ErrorCode::REQUIRED_CONDITION_VIOLATION)); + return Violation(ViolationErrorCode::ASSERT_VIOLATION); } - static Violation createPreconditionViolation() + static Violation createEnforceViolation() { - return Violation(ErrorCode(ErrorCode::PRECONDITION_VIOLATION)); - } - - static Violation createAssumptionViolation() - { - return Violation(ErrorCode(ErrorCode::ASSUMPTION_VIOLATION)); + return Violation(ViolationErrorCode::ENFORCE_VIOLATION); } private: @@ -90,45 +93,7 @@ class Violation ModuleId m_module{ModuleId::ANY}; }; -// primary template is the identity -// this can be overriden by modules to handle specific errors -template -auto toError(ErrorLike&& value) -{ - return std::forward(value); -} - -template -inline ErrorCode toCode(const Error& error) -{ - return error.code(); -} - -template <> -inline ErrorCode toCode(const ErrorCode& error) -{ - return error; -} - -template -inline ModuleId toModule(const Error& error) -{ - return error.module(); -} - -template -inline const char* toModuleName(const Error&) -{ - return UNKNOWN_MODULE_NAME; -} - -template -inline const char* toErrorName(const Error&) -{ - return UNKNOWN_ERROR_NAME; -} - } // namespace er } // namespace iox -#endif // IOX_HOOFS_ERROR_REPORTING_ERRORS_HPP +#endif // IOX_HOOFS_ERROR_REPORTING_VIOLATION_HPP diff --git a/iceoryx_hoofs/reporting/include/iox/iceoryx_hoofs_errors.hpp b/iceoryx_hoofs/reporting/include/iox/iceoryx_hoofs_errors.hpp index fd8bf1d9b3..a541533d2e 100644 --- a/iceoryx_hoofs/reporting/include/iox/iceoryx_hoofs_errors.hpp +++ b/iceoryx_hoofs/reporting/include/iox/iceoryx_hoofs_errors.hpp @@ -17,8 +17,8 @@ #ifndef IOX_HOOFS_REPORTING_ICEORYX_HOOFS_ERRORS_HPP #define IOX_HOOFS_REPORTING_ICEORYX_HOOFS_ERRORS_HPP -#include "iox/error_reporting/errors.hpp" #include "iox/error_reporting/types.hpp" +#include "iox/error_reporting/violation.hpp" /// @todo iox-#1032 Incomplete and not used yet, will be used in integration or error reporting into /// iceoryx_hoofs. This is just a sketch/proof of concept. diff --git a/iceoryx_hoofs/test/integrationtests/test_hoofs_integration.cpp b/iceoryx_hoofs/test/integrationtests/test_hoofs_integration.cpp index 1091df15b9..e3b751e3cb 100644 --- a/iceoryx_hoofs/test/integrationtests/test_hoofs_integration.cpp +++ b/iceoryx_hoofs/test/integrationtests/test_hoofs_integration.cpp @@ -15,18 +15,17 @@ // // SPDX-License-Identifier: Apache-2.0 +#include "iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp" #include "iceoryx_hoofs/testing/testing_logger.hpp" #include "test.hpp" -using namespace ::testing; -using ::testing::_; - int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); iox::testing::TestingLogger::init(); + iox::testing::TestingErrorHandler::init(); return RUN_ALL_TESTS(); } diff --git a/iceoryx_hoofs/test/mocktests/test_hoofs_mock.cpp b/iceoryx_hoofs/test/mocktests/test_hoofs_mock.cpp index 2ec14def32..e3b751e3cb 100644 --- a/iceoryx_hoofs/test/mocktests/test_hoofs_mock.cpp +++ b/iceoryx_hoofs/test/mocktests/test_hoofs_mock.cpp @@ -15,17 +15,17 @@ // // SPDX-License-Identifier: Apache-2.0 +#include "iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp" #include "iceoryx_hoofs/testing/testing_logger.hpp" #include "test.hpp" -using ::testing::_; - int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); iox::testing::TestingLogger::init(); + iox::testing::TestingErrorHandler::init(); return RUN_ALL_TESTS(); } diff --git a/iceoryx_hoofs/test/moduletests/error_reporting/module_a/errors.hpp b/iceoryx_hoofs/test/moduletests/error_reporting/module_a/errors.hpp index 91d1e3900d..9addfeb0d7 100644 --- a/iceoryx_hoofs/test/moduletests/error_reporting/module_a/errors.hpp +++ b/iceoryx_hoofs/test/moduletests/error_reporting/module_a/errors.hpp @@ -17,8 +17,8 @@ #ifndef IOX_HOOFS_MODULETESTS_ERROR_REPORTING_MODULE_A_ERRORS_HPP #define IOX_HOOFS_MODULETESTS_ERROR_REPORTING_MODULE_A_ERRORS_HPP -#include "iox/error_reporting/errors.hpp" #include "iox/error_reporting/types.hpp" +#include "iox/error_reporting/violation.hpp" namespace module_a { diff --git a/iceoryx_hoofs/test/moduletests/error_reporting/module_b/errors.hpp b/iceoryx_hoofs/test/moduletests/error_reporting/module_b/errors.hpp index 5933f6a804..c50f7bf3a9 100644 --- a/iceoryx_hoofs/test/moduletests/error_reporting/module_b/errors.hpp +++ b/iceoryx_hoofs/test/moduletests/error_reporting/module_b/errors.hpp @@ -17,8 +17,8 @@ #ifndef IOX_HOOFS_MODULETESTS_ERROR_REPORTING_MODULE_B_ERRORS_HPP #define IOX_HOOFS_MODULETESTS_ERROR_REPORTING_MODULE_B_ERRORS_HPP -#include "iox/error_reporting/errors.hpp" #include "iox/error_reporting/types.hpp" +#include "iox/error_reporting/violation.hpp" namespace module_b { diff --git a/iceoryx_hoofs/test/moduletests/error_reporting/test_custom_error_reporting.cpp b/iceoryx_hoofs/test/moduletests/error_reporting/test_custom_error_reporting.cpp index 496dd04bd8..1c7cf62fd3 100644 --- a/iceoryx_hoofs/test/moduletests/error_reporting/test_custom_error_reporting.cpp +++ b/iceoryx_hoofs/test/moduletests/error_reporting/test_custom_error_reporting.cpp @@ -16,8 +16,8 @@ #include "iox/error_reporting/custom/error_kind.hpp" #include "iox/error_reporting/error_kind.hpp" -#include "iox/error_reporting/errors.hpp" #include "iox/error_reporting/source_location.hpp" +#include "iox/error_reporting/violation.hpp" #include "moduletests/error_reporting/module_a/errors.hpp" #include "test.hpp" #include @@ -37,15 +37,13 @@ constexpr auto CODE{module_a::errors::Code::OutOfBounds}; constexpr module_a::errors::Error ERROR{CODE}; // Here we test the custom API that the public API forwards to. -// To observe the side effects, this requires using the TestErrorHandler (similar to the public API). +// To observe the side effects, this requires using the TestingErrorHandler (similar to the public API). class ErrorReporting_test : public Test { public: void SetUp() override { - /// @todo iox-#1032 this should be done for all tests (using Gtest hooks) in integration - iox::testing::ErrorHandler::instance().reset(); } void TearDown() override @@ -112,62 +110,62 @@ TEST_F(ErrorReporting_test, reportFatalErrorWorks) IOX_TESTING_EXPECT_ERROR(CODE); } -TEST_F(ErrorReporting_test, reportPreconditionViolatonWorks) +TEST_F(ErrorReporting_test, reportAssertViolatonWorks) { ::testing::Test::RecordProperty("TEST_ID", "feb63aa0-1921-408a-a887-abbb99522b31"); auto f = []() { - auto v = Violation::createPreconditionViolation(); - report(CURRENT_SOURCE_LOCATION, PRECONDITION_VIOLATION, v); + auto v = Violation::createAssertViolation(); + report(CURRENT_SOURCE_LOCATION, ASSERT_VIOLATION, v); }; iox::testing::runInTestThread(f); - IOX_TESTING_EXPECT_PRECONDITION_VIOLATION(); + IOX_TESTING_EXPECT_ASSERT_VIOLATION(); } // the message is printed but otherwise lost, so we cannot check for it -TEST_F(ErrorReporting_test, reportPreconditionViolatonWithMessageWorks) +TEST_F(ErrorReporting_test, reportAssertViolatonWithMessageWorks) { ::testing::Test::RecordProperty("TEST_ID", "9228c696-d555-49c5-ade1-b65d16159e8c"); auto f = []() { - auto v = Violation::createPreconditionViolation(); - report(CURRENT_SOURCE_LOCATION, PRECONDITION_VIOLATION, v, "message"); + auto v = Violation::createAssertViolation(); + report(CURRENT_SOURCE_LOCATION, ASSERT_VIOLATION, v, "message"); }; iox::testing::runInTestThread(f); - IOX_TESTING_EXPECT_PRECONDITION_VIOLATION(); + IOX_TESTING_EXPECT_ASSERT_VIOLATION(); } -TEST_F(ErrorReporting_test, reportAssumptionViolatonWorks) +TEST_F(ErrorReporting_test, reportEnforceViolatonWorks) { ::testing::Test::RecordProperty("TEST_ID", "f866b43a-3a88-4097-adde-4704fc1a5e8f"); auto f = []() { - auto v = Violation::createAssumptionViolation(); - report(CURRENT_SOURCE_LOCATION, ASSUMPTION_VIOLATION, v); + auto v = Violation::createEnforceViolation(); + report(CURRENT_SOURCE_LOCATION, ENFORCE_VIOLATION, v); }; iox::testing::runInTestThread(f); - IOX_TESTING_EXPECT_ASSUMPTION_VIOLATION(); + IOX_TESTING_EXPECT_ENFORCE_VIOLATION(); } // the message is printed but otherwise lost, so we cannot check for it -TEST_F(ErrorReporting_test, reportAssumptionViolatonWithMessageWorks) +TEST_F(ErrorReporting_test, reportEnforceViolatonWithMessageWorks) { ::testing::Test::RecordProperty("TEST_ID", "1cccd0f7-c944-4904-bf64-6f575ea13b85"); auto f = []() { - auto v = Violation::createAssumptionViolation(); - report(CURRENT_SOURCE_LOCATION, ASSUMPTION_VIOLATION, v, "message"); + auto v = Violation::createEnforceViolation(); + report(CURRENT_SOURCE_LOCATION, ENFORCE_VIOLATION, v, "message"); }; iox::testing::runInTestThread(f); - IOX_TESTING_EXPECT_ASSUMPTION_VIOLATION(); + IOX_TESTING_EXPECT_ENFORCE_VIOLATION(); } } // namespace diff --git a/iceoryx_hoofs/test/moduletests/error_reporting/test_error_kind.cpp b/iceoryx_hoofs/test/moduletests/error_reporting/test_error_kind.cpp index 660630ba1b..689aec8b6f 100644 --- a/iceoryx_hoofs/test/moduletests/error_reporting/test_error_kind.cpp +++ b/iceoryx_hoofs/test/moduletests/error_reporting/test_error_kind.cpp @@ -38,24 +38,24 @@ TEST(ErrorKind_test, fatalErrorsAreFatal) EXPECT_TRUE(isFatal(sut)); } -TEST(ErrorKind_test, preconditionViolationsAreFatal) +TEST(ErrorKind_test, enforceViolationsAreFatal) { ::testing::Test::RecordProperty("TEST_ID", "21b79757-e46b-44fe-854a-7579b7f2243b"); - PreconditionViolationKind sut; - EXPECT_TRUE(IsFatal::value); + EnforceViolationKind sut; + EXPECT_TRUE(IsFatal::value); EXPECT_TRUE(isFatal(sut)); - EXPECT_TRUE(isFatal(PRECONDITION_VIOLATION)); + EXPECT_TRUE(isFatal(ENFORCE_VIOLATION)); } -TEST(ErrorKind_test, assumptionViolationsAreFatal) +TEST(ErrorKind_test, assertViolationsAreFatal) { ::testing::Test::RecordProperty("TEST_ID", "b502e70e-157d-45a0-9654-61ada213531d"); - AssumptionViolationKind sut; - EXPECT_TRUE(IsFatal::value); + AssertViolationKind sut; + EXPECT_TRUE(IsFatal::value); EXPECT_TRUE(isFatal(sut)); - EXPECT_TRUE(isFatal(ASSUMPTION_VIOLATION)); + EXPECT_TRUE(isFatal(ASSERT_VIOLATION)); } TEST(ErrorKind_test, runtimeErrorsAreNotFatal) diff --git a/iceoryx_hoofs/test/moduletests/error_reporting/test_error_reporting_macros.cpp b/iceoryx_hoofs/test/moduletests/error_reporting/test_error_reporting_macros.cpp index c3330f2b9f..9ad94f8faf 100644 --- a/iceoryx_hoofs/test/moduletests/error_reporting/test_error_reporting_macros.cpp +++ b/iceoryx_hoofs/test/moduletests/error_reporting/test_error_reporting_macros.cpp @@ -46,8 +46,6 @@ class ErrorReportingMacroApi_test : public Test public: void SetUp() override { - /// @todo iox-#1032 this should be done for all tests (using Gtest hooks) in integration - iox::testing::ErrorHandler::instance().reset(); } void TearDown() override @@ -128,92 +126,69 @@ TEST_F(ErrorReportingMacroApi_test, reportConditionalNoError) IOX_TESTING_EXPECT_OK(); } -TEST_F(ErrorReportingMacroApi_test, checkRequireConditionSatisfied) +TEST_F(ErrorReportingMacroApi_test, checkEnforceConditionSatisfied) { ::testing::Test::RecordProperty("TEST_ID", "3c684878-20f8-426f-bb8b-7576b567d04f"); - auto f = []() { IOX_REQUIRE(true, ""); }; + auto f = []() { IOX_ENFORCE(true, ""); }; runInTestThread(f); IOX_TESTING_EXPECT_OK(); } -TEST_F(ErrorReportingMacroApi_test, checkRequireConditionViolate) +TEST_F(ErrorReportingMacroApi_test, checkEnforceConditionViolate) { ::testing::Test::RecordProperty("TEST_ID", "fb62d315-8854-401b-82af-6161ae45a34e"); - auto f = []() { IOX_REQUIRE(false, ""); }; + auto f = []() { IOX_ENFORCE(false, ""); }; runInTestThread(f); IOX_TESTING_EXPECT_PANIC(); - IOX_TESTING_EXPECT_REQUIRED_CONDITION_VIOLATION(); + IOX_TESTING_EXPECT_ENFORCE_VIOLATION(); } -TEST_F(ErrorReportingMacroApi_test, checkPreconditionSatisfied) -{ - ::testing::Test::RecordProperty("TEST_ID", "bb6e2122-7c57-4657-9567-ecb63e26a3ed"); - auto f = [](int x) { IOX_PRECONDITION(x > 0, ""); }; - - runInTestThread(f, 1); - - IOX_TESTING_EXPECT_OK(); -} - -TEST_F(ErrorReportingMacroApi_test, checkPreconditionViolated) -{ - ::testing::Test::RecordProperty("TEST_ID", "b2d27f6d-d0c7-405a-afbf-bf8a72661b20"); - auto f = [](int x) { IOX_PRECONDITION(x > 0, ""); }; - - runInTestThread([&]() { f(0); }); - - runInTestThread(f, 0); - - IOX_TESTING_EXPECT_PANIC(); - IOX_TESTING_EXPECT_PRECONDITION_VIOLATION(); -} - -TEST_F(ErrorReportingMacroApi_test, checkAssumptionSatisfied) +TEST_F(ErrorReportingMacroApi_test, checkAssertConditionSatisfied) { ::testing::Test::RecordProperty("TEST_ID", "a76ce780-3387-4ae8-8e4c-c96bdb8aa753"); - auto f = [](int x) { IOX_ASSUME(x > 0, ""); }; + auto f = [](int x) { IOX_ASSERT(x > 0, ""); }; runInTestThread(f, 1); IOX_TESTING_EXPECT_OK(); } -TEST_F(ErrorReportingMacroApi_test, checkAssumptionNotSatisfied) +TEST_F(ErrorReportingMacroApi_test, checkAssertConditionNotSatisfied) { ::testing::Test::RecordProperty("TEST_ID", "9ee71bd3-9004-4950-8441-25e98cf8409c"); - auto f = [](int x) { IOX_ASSUME(x > 0, ""); }; + auto f = [](int x) { IOX_ASSERT(x > 0, ""); }; runInTestThread(f, 0); IOX_TESTING_EXPECT_PANIC(); - IOX_TESTING_EXPECT_ASSUMPTION_VIOLATION(); + IOX_TESTING_EXPECT_ASSERT_VIOLATION(); } -TEST_F(ErrorReportingMacroApi_test, checkPreconditionNotSatisfiedWithMessage) +TEST_F(ErrorReportingMacroApi_test, checkEnforceConditionNotSatisfiedWithMessage) { ::testing::Test::RecordProperty("TEST_ID", "18d5b9a6-2d60-478e-8c50-d044a3672290"); - auto f = [](int x) { IOX_PRECONDITION(x > 0, "some message"); }; + auto f = [](int x) { IOX_ENFORCE(x > 0, "some message"); }; runInTestThread(f, 0); IOX_TESTING_EXPECT_PANIC(); - IOX_TESTING_EXPECT_PRECONDITION_VIOLATION(); + IOX_TESTING_EXPECT_ENFORCE_VIOLATION(); } -TEST_F(ErrorReportingMacroApi_test, checkAssumptionNotSatisfiedWithMessage) +TEST_F(ErrorReportingMacroApi_test, checkAssertNotSatisfiedWithMessage) { ::testing::Test::RecordProperty("TEST_ID", "b416674a-5861-4ab7-947b-0bd0af2f627b"); - auto f = [](int x) { IOX_ASSUME(x > 0, "some message"); }; + auto f = [](int x) { IOX_ASSERT(x > 0, "some message"); }; runInTestThread(f, 0); IOX_TESTING_EXPECT_PANIC(); - IOX_TESTING_EXPECT_ASSUMPTION_VIOLATION(); + IOX_TESTING_EXPECT_ASSERT_VIOLATION(); } TEST_F(ErrorReportingMacroApi_test, reportErrorsFromDifferentModules) @@ -252,7 +227,7 @@ TEST_F(ErrorReportingMacroApi_test, reportErrorsAndViolations) auto f = []() { IOX_REPORT(MyCodeA::OutOfBounds, RUNTIME_ERROR); IOX_REPORT(MyCodeB::OutOfMemory, RUNTIME_ERROR); - IOX_ASSUME(false, ""); + IOX_ENFORCE(false, ""); }; runInTestThread(f); diff --git a/iceoryx_hoofs/test/moduletests/error_reporting/test_errors.cpp b/iceoryx_hoofs/test/moduletests/error_reporting/test_error_reporting_violation.cpp similarity index 93% rename from iceoryx_hoofs/test/moduletests/error_reporting/test_errors.cpp rename to iceoryx_hoofs/test/moduletests/error_reporting/test_error_reporting_violation.cpp index e87cdbd646..1eb72a4417 100644 --- a/iceoryx_hoofs/test/moduletests/error_reporting/test_errors.cpp +++ b/iceoryx_hoofs/test/moduletests/error_reporting/test_error_reporting_violation.cpp @@ -17,8 +17,8 @@ #include "test.hpp" #include -#include "iox/error_reporting/errors.hpp" #include "iox/error_reporting/types.hpp" +#include "iox/error_reporting/violation.hpp" #include "module_a/errors.hpp" #include "module_b/errors.hpp" @@ -200,22 +200,22 @@ TYPED_TEST(ErrorType_test, toErrorPreservesCodeAndModule) EXPECT_EQ(err.module(), this->sut.module()); } -TEST(Violation_test, createPreconditionWorks) +TEST(Violation_test, createEnforceViolationWorks) { - ::testing::Test::RecordProperty("TEST_ID", "cc535c67-0003-4a6f-842e-6c5477aae108"); + ::testing::Test::RecordProperty("TEST_ID", "9a2f9d1c-41dc-4a7e-a0dc-aa40047ae9a0"); - auto sut = Violation::createPreconditionViolation(); - auto exp = Violation{ErrorCode{ErrorCode::PRECONDITION_VIOLATION}, ANY_ID}; + auto sut = Violation::createEnforceViolation(); + auto exp = Violation{iox::er::ViolationErrorCode::ENFORCE_VIOLATION}; EXPECT_EQ(sut, exp); } -TEST(Violation_test, createAssumptionWorks) +TEST(Violation_test, createAssertViolationWorks) { ::testing::Test::RecordProperty("TEST_ID", "2a5f24a7-4d82-4c27-bc45-57d9f1c759fa"); - auto sut = Violation::createAssumptionViolation(); - auto exp = Violation{ErrorCode{ErrorCode::ASSUMPTION_VIOLATION}, ANY_ID}; + auto sut = Violation::createAssertViolation(); + auto exp = Violation{iox::er::ViolationErrorCode::ASSERT_VIOLATION}; EXPECT_EQ(sut, exp); } diff --git a/iceoryx_hoofs/test/moduletests/error_reporting/test_test_error_handler.cpp b/iceoryx_hoofs/test/moduletests/error_reporting/test_testing_error_handler.cpp similarity index 85% rename from iceoryx_hoofs/test/moduletests/error_reporting/test_test_error_handler.cpp rename to iceoryx_hoofs/test/moduletests/error_reporting/test_testing_error_handler.cpp index bbeeadfaf1..2a440d8b40 100644 --- a/iceoryx_hoofs/test/moduletests/error_reporting/test_test_error_handler.cpp +++ b/iceoryx_hoofs/test/moduletests/error_reporting/test_testing_error_handler.cpp @@ -40,7 +40,7 @@ constexpr ErrorCode VIOLATION{12}; constexpr ModuleId MODULE{66}; -class TestErrorHandler_test : public Test +class TestingErrorHandler_test : public Test { public: void SetUp() override @@ -51,7 +51,7 @@ class TestErrorHandler_test : public Test { } - TestErrorHandler sut; + TestingErrorHandler sut; bool hasPanicked() const { @@ -79,13 +79,13 @@ class TestErrorHandler_test : public Test } }; -TEST_F(TestErrorHandler_test, constructionAndDestructionWorks) +TEST_F(TestingErrorHandler_test, constructionAndDestructionWorks) { ::testing::Test::RecordProperty("TEST_ID", "09f24453-aea1-4128-83f3-929337b9892a"); EXPECT_FALSE(hasAnyError()); } -TEST_F(TestErrorHandler_test, panicWorks) +TEST_F(TestingErrorHandler_test, panicWorks) { ::testing::Test::RecordProperty("TEST_ID", "e2c5e639-722f-4bab-85c7-98268345b033"); sut.onPanic(); @@ -96,7 +96,7 @@ TEST_F(TestErrorHandler_test, panicWorks) EXPECT_FALSE(hasAnyError()); } -TEST_F(TestErrorHandler_test, reportErrorWorks) +TEST_F(TestingErrorHandler_test, reportErrorWorks) { ::testing::Test::RecordProperty("TEST_ID", "90bd13cf-ece2-4221-8cce-7b2a99568a6a"); sut.onReportError(ErrorDescriptor{CURRENT_SOURCE_LOCATION, CODE1, MODULE}); @@ -109,7 +109,7 @@ TEST_F(TestErrorHandler_test, reportErrorWorks) EXPECT_FALSE(hasError(CODE1)); // checked for consistency } -TEST_F(TestErrorHandler_test, reportViolationWorks) +TEST_F(TestingErrorHandler_test, reportViolationWorks) { ::testing::Test::RecordProperty("TEST_ID", "5746886e-7309-4435-9e0a-2e6856a318f5"); sut.onReportViolation(ErrorDescriptor{CURRENT_SOURCE_LOCATION, VIOLATION, MODULE}); @@ -120,7 +120,7 @@ TEST_F(TestErrorHandler_test, reportViolationWorks) EXPECT_FALSE(hasAnyError()); } -TEST_F(TestErrorHandler_test, hasErrorDetectsOnlyreportErroredErrors) +TEST_F(TestingErrorHandler_test, hasErrorDetectsOnlyreportErroredErrors) { ::testing::Test::RecordProperty("TEST_ID", "0ee52915-88b7-4041-9f63-93ec5c882e95"); sut.onReportError(ErrorDescriptor{CURRENT_SOURCE_LOCATION, CODE1, MODULE}); @@ -137,7 +137,7 @@ TEST_F(TestErrorHandler_test, hasErrorDetectsOnlyreportErroredErrors) EXPECT_FALSE(sut.hasError(CODE3, MODULE)); } -TEST_F(TestErrorHandler_test, resettingMultipleErrorsWorks) +TEST_F(TestingErrorHandler_test, resettingMultipleErrorsWorks) { ::testing::Test::RecordProperty("TEST_ID", "9715c394-5576-4fd8-a0f6-24560f60c161"); sut.onReportError(ErrorDescriptor{CURRENT_SOURCE_LOCATION, CODE1, MODULE}); @@ -150,14 +150,14 @@ TEST_F(TestErrorHandler_test, resettingMultipleErrorsWorks) EXPECT_FALSE(hasAnyError()); } -TEST_F(TestErrorHandler_test, prepareJumpWorks) +TEST_F(TestingErrorHandler_test, prepareJumpWorks) { ::testing::Test::RecordProperty("TEST_ID", "df6356a6-9e9e-4ee3-8a7c-7eb68cfe2516"); auto* buf = sut.prepareJump(); EXPECT_NE(buf, nullptr); } -TEST_F(TestErrorHandler_test, onlyOneJumpCanBePrepared) +TEST_F(TestingErrorHandler_test, onlyOneJumpCanBePrepared) { ::testing::Test::RecordProperty("TEST_ID", "45ad9ab9-0f79-4b7c-8e36-76da3067c0fd"); auto* buf1 = sut.prepareJump(); @@ -166,7 +166,7 @@ TEST_F(TestErrorHandler_test, onlyOneJumpCanBePrepared) EXPECT_EQ(buf2, nullptr); } -void jump(TestErrorHandler& handler, int& jmpValue) +void jump(TestingErrorHandler& handler, int& jmpValue) { auto* buf = handler.prepareJump(); // setjmp must be used in a control flow construct like if, while (UB otherwise) @@ -183,7 +183,7 @@ void jump(TestErrorHandler& handler, int& jmpValue) } } -TEST_F(TestErrorHandler_test, panicTriggersPreparedJump) +TEST_F(TestingErrorHandler_test, panicTriggersPreparedJump) { ::testing::Test::RecordProperty("TEST_ID", "2d99e382-ed43-4357-86f2-ef8d70c6acd8"); int jmpValue{0}; @@ -198,11 +198,11 @@ TEST_F(TestErrorHandler_test, panicTriggersPreparedJump) EXPECT_TRUE(sut.hasPanicked()); // jumpIndicator() is consistent with value of setjmp after onPanic - EXPECT_EQ(jmpValue, TestErrorHandler::jumpIndicator()); + EXPECT_EQ(jmpValue, TestingErrorHandler::jumpIndicator()); EXPECT_NE(jmpValue, 0); } -void noJump(TestErrorHandler& handler, int& jmpValue) +void noJump(TestingErrorHandler& handler, int& jmpValue) { jmp_buf buf; // setjmp must be used in a control flow construct like if, while (UB otherwise) @@ -220,9 +220,9 @@ void noJump(TestErrorHandler& handler, int& jmpValue) } // This checks that onPanic will not jump without proper setup by test code -// Note that this must happen outside of the TestErrorHandler implementation due to +// Note that this must happen outside of the TestingErrorHandler implementation due to // limitations of setjmp. -TEST_F(TestErrorHandler_test, panicDoesNotTriggerUnpreparedJump) +TEST_F(TestingErrorHandler_test, panicDoesNotTriggerUnpreparedJump) { ::testing::Test::RecordProperty("TEST_ID", "23004b9e-4ec9-4fe5-9312-54907ad05967"); int jmpValue{0}; @@ -236,7 +236,7 @@ TEST_F(TestErrorHandler_test, panicDoesNotTriggerUnpreparedJump) t.join(); EXPECT_TRUE(sut.hasPanicked()); - EXPECT_NE(jmpValue, TestErrorHandler::jumpIndicator()); + EXPECT_NE(jmpValue, TestingErrorHandler::jumpIndicator()); EXPECT_EQ(jmpValue, 0); } diff --git a/iceoryx_hoofs/test/moduletests/test_hoofs_modules.cpp b/iceoryx_hoofs/test/moduletests/test_hoofs_modules.cpp index 79d6142262..e3b751e3cb 100644 --- a/iceoryx_hoofs/test/moduletests/test_hoofs_modules.cpp +++ b/iceoryx_hoofs/test/moduletests/test_hoofs_modules.cpp @@ -15,23 +15,17 @@ // // SPDX-License-Identifier: Apache-2.0 +#include "iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp" #include "iceoryx_hoofs/testing/testing_logger.hpp" -#include "iceoryx_hoofs/testing/error_reporting/testing_support.hpp" - #include "test.hpp" -using namespace ::testing; -using ::testing::_; - int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); iox::testing::TestingLogger::init(); - - iox::testing::ErrorHandler handler; - iox::er::ErrorHandler::set(handler); + iox::testing::TestingErrorHandler::init(); return RUN_ALL_TESTS(); } diff --git a/iceoryx_hoofs/test/moduletests/test_utility_convert.cpp b/iceoryx_hoofs/test/moduletests/test_utility_convert.cpp index 0d17481ca4..78eed23260 100644 --- a/iceoryx_hoofs/test/moduletests/test_utility_convert.cpp +++ b/iceoryx_hoofs/test/moduletests/test_utility_convert.cpp @@ -682,6 +682,8 @@ TEST_F(convert_test, fromString_Double_EdgeCase_InRange_Success) { ::testing::Test::RecordProperty("TEST_ID", "d5e5e5ad-92ed-4229-8128-4ee82059fbf7"); + GTEST_SKIP() << "iox-#2055 Temporarily skipped due to issues in aarch64"; + std::string source = fp_to_string(std::numeric_limits::min()); auto double_min = iox::convert::from_string(source.c_str()); ASSERT_THAT(double_min.has_value(), Eq(true)); diff --git a/iceoryx_hoofs/testing/error_reporting/testing_error_handler.cpp b/iceoryx_hoofs/testing/error_reporting/testing_error_handler.cpp index c4aa7b36b5..2c959de12b 100644 --- a/iceoryx_hoofs/testing/error_reporting/testing_error_handler.cpp +++ b/iceoryx_hoofs/testing/error_reporting/testing_error_handler.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2023 by Apex.AI Inc. All rights reserved. +// Copyright (c) 2024 by Mathias Kraus . All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,6 +16,7 @@ // SPDX-License-Identifier: Apache-2.0 #include "iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp" +#include "iox/error_reporting/custom/default/error_handler.hpp" #include "iox/error_reporting/custom/default/error_handler_interface.hpp" #include "iox/error_reporting/types.hpp" @@ -30,35 +32,45 @@ namespace testing using namespace iox::er; -TestErrorHandler::TestErrorHandler() +void TestingErrorHandler::init() noexcept +{ + iox::testing::ErrorHandler handler; + iox::er::ErrorHandler::set(handler); + + auto& listeners = ::testing::UnitTest::GetInstance()->listeners(); + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) required by the callee + listeners.Append(new (std::nothrow) ErrorHandlerSetup); +} + +TestingErrorHandler::TestingErrorHandler() noexcept : m_jump(&m_jumpBuffer) { } -void TestErrorHandler::onPanic() +void TestingErrorHandler::onPanic() { m_panicked = true; jump(); } -void TestErrorHandler::onReportError(er::ErrorDescriptor desc) +void TestingErrorHandler::onReportError(er::ErrorDescriptor desc) { std::lock_guard g(m_mutex); m_errors.push_back(desc); } -void TestErrorHandler::onReportViolation(er::ErrorDescriptor desc) +void TestingErrorHandler::onReportViolation(er::ErrorDescriptor desc) { std::lock_guard g(m_mutex); m_violations.push_back(desc); } -bool TestErrorHandler::hasPanicked() const +bool TestingErrorHandler::hasPanicked() const noexcept { return m_panicked; } -void TestErrorHandler::reset() +void TestingErrorHandler::reset() noexcept { std::lock_guard g(m_mutex); m_panicked = false; @@ -67,13 +79,13 @@ void TestErrorHandler::reset() m_jump.store(&m_jumpBuffer); } -bool TestErrorHandler::hasError() const +bool TestingErrorHandler::hasError() const noexcept { std::lock_guard g(m_mutex); return !m_errors.empty(); } -bool TestErrorHandler::hasError(ErrorCode code, iox::er::ModuleId module) const +bool TestingErrorHandler::hasError(ErrorCode code, iox::er::ModuleId module) const noexcept { constexpr iox::er::ModuleId ANY_MODULE{iox::er::ModuleId::ANY}; std::lock_guard g(m_mutex); @@ -91,7 +103,7 @@ bool TestErrorHandler::hasError(ErrorCode code, iox::er::ModuleId module) const return false; } -bool TestErrorHandler::hasViolation(ErrorCode code) const +bool TestingErrorHandler::hasViolation(ErrorCode code) const noexcept { std::lock_guard g(m_mutex); for (auto desc : m_violations) @@ -104,13 +116,13 @@ bool TestErrorHandler::hasViolation(ErrorCode code) const return false; } -jmp_buf* TestErrorHandler::prepareJump() +jmp_buf* TestingErrorHandler::prepareJump() noexcept { // winner can prepare the jump return m_jump.exchange(nullptr); } -void TestErrorHandler::jump() +void TestingErrorHandler::jump() noexcept { jmp_buf* exp = nullptr; // if it is a nullptr, somebody (and only one) has prepared jump @@ -123,10 +135,15 @@ void TestErrorHandler::jump() } } -int TestErrorHandler::jumpIndicator() +int TestingErrorHandler::jumpIndicator() noexcept { return JUMPED; } +void ErrorHandlerSetup::OnTestStart(const ::testing::TestInfo&) +{ + ErrorHandler::instance().reset(); +} + } // namespace testing } // namespace iox diff --git a/iceoryx_hoofs/testing/error_reporting/testing_support.cpp b/iceoryx_hoofs/testing/error_reporting/testing_support.cpp index b5c1fe8216..990c622231 100644 --- a/iceoryx_hoofs/testing/error_reporting/testing_support.cpp +++ b/iceoryx_hoofs/testing/error_reporting/testing_support.cpp @@ -31,27 +31,21 @@ bool hasError() return ErrorHandler::instance().hasError(); } -bool hasRequiredConditionViolation() +bool hasAssertViolation() { - auto code = iox::er::ErrorCode{iox::er::ErrorCode::REQUIRED_CONDITION_VIOLATION}; + auto code = iox::er::Violation(iox::er::ViolationErrorCode::ASSERT_VIOLATION).code(); return ErrorHandler::instance().hasViolation(code); } -bool hasPreconditionViolation() +bool hasEnforceViolation() { - auto code = iox::er::ErrorCode{iox::er::ErrorCode::PRECONDITION_VIOLATION}; - return ErrorHandler::instance().hasViolation(code); -} - -bool hasAssumptionViolation() -{ - auto code = iox::er::ErrorCode{iox::er::ErrorCode::ASSUMPTION_VIOLATION}; + auto code = iox::er::Violation(iox::er::ViolationErrorCode::ENFORCE_VIOLATION).code(); return ErrorHandler::instance().hasViolation(code); } bool hasViolation() { - return hasRequiredConditionViolation() || hasPreconditionViolation() || hasAssumptionViolation(); + return hasEnforceViolation() || hasAssertViolation(); } bool isInNormalState() diff --git a/iceoryx_hoofs/testing/include/iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp b/iceoryx_hoofs/testing/include/iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp index 9b72971ee7..c01f778213 100644 --- a/iceoryx_hoofs/testing/include/iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp +++ b/iceoryx_hoofs/testing/include/iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp @@ -1,4 +1,5 @@ // Copyright (c) 2023 by Apex.AI Inc. All rights reserved. +// Copyright (c) 2024 by Mathias Kraus . All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,9 +20,12 @@ #include "iox/error_reporting/custom/default/error_handler_interface.hpp" #include "iox/error_reporting/error_logging.hpp" -#include "iox/error_reporting/errors.hpp" #include "iox/error_reporting/source_location.hpp" #include "iox/error_reporting/types.hpp" +#include "iox/error_reporting/violation.hpp" +#include "iox/static_lifetime_guard.hpp" + +#include "iceoryx_hoofs/testing/test.hpp" #include #include @@ -38,16 +42,32 @@ namespace testing { /// @brief Defines the test reaction of dynamic error handling. -class TestErrorHandler : public iox::er::ErrorHandlerInterface +class TestingErrorHandler : public iox::er::ErrorHandlerInterface { public: - TestErrorHandler(); - - ~TestErrorHandler() override = default; - TestErrorHandler(const TestErrorHandler&) = delete; - TestErrorHandler(TestErrorHandler&&) = delete; - TestErrorHandler& operator=(const TestErrorHandler&) = delete; - TestErrorHandler operator=(TestErrorHandler&&) = delete; + TestingErrorHandler() noexcept; + ~TestingErrorHandler() noexcept override = default; + TestingErrorHandler(const TestingErrorHandler&) noexcept = delete; + TestingErrorHandler(TestingErrorHandler&&) noexcept = delete; + TestingErrorHandler& operator=(const TestingErrorHandler&) noexcept = delete; + TestingErrorHandler operator=(TestingErrorHandler&&) noexcept = delete; + + /// @brief Initialized the error handler. This should be called in the main function of the test binary + /// @code + /// #include "iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp" + /// + /// #include "test.hpp" + /// + /// int main(int argc, char* argv[]) + /// { + /// ::testing::InitGoogleTest(&argc, argv); + /// + /// iox::testing::ErrorHandler::init(); + /// + /// return RUN_ALL_TESTS(); + /// } + /// @endcode + static void init() noexcept; /// @brief Defines the reaction on panic. void onPanic() override; @@ -62,28 +82,28 @@ class TestErrorHandler : public iox::er::ErrorHandlerInterface /// @brief Indicates whether there was a panic call previously. /// @return true if there was a panic call, false otherwise - bool hasPanicked() const; + bool hasPanicked() const noexcept; /// @brief Reset panic state and clears all errors that occurred previously. - void reset(); + void reset() noexcept; /// @brief Indicates whether any error occurred previously. - bool hasError() const; + bool hasError() const noexcept; /// @brief Indicates whether a specific error occurred previously. - bool hasError(iox::er::ErrorCode code, iox::er::ModuleId module = iox::er::ModuleId()) const; + bool hasError(iox::er::ErrorCode code, iox::er::ModuleId module = iox::er::ModuleId()) const noexcept; /// @brief Indicates whether a assumption violation occurred previously. /// @note We do not track module id for violations. - bool hasViolation(iox::er::ErrorCode code) const; + bool hasViolation(iox::er::ErrorCode code) const noexcept; /// @brief Prepare a jump and return jump buffer /// @return pointer to jump buffer if successful, nullptr otherwise - jmp_buf* prepareJump(); + jmp_buf* prepareJump() noexcept; /// @brief Returns the value that is set by longjmp in case of a jump. /// @return the jump indicator value - static int jumpIndicator(); + static int jumpIndicator() noexcept; private: static constexpr int JUMPED{1}; @@ -105,9 +125,17 @@ class TestErrorHandler : public iox::er::ErrorHandlerInterface // ownership of the buffer is one way to accomplish that. std::atomic m_jump{nullptr}; - void jump(); + void jump() noexcept; +}; + +/// @brief This class hooks into gTest to automatically resets the error handler on the start of a test +class ErrorHandlerSetup : public ::testing::EmptyTestEventListener +{ + void OnTestStart(const ::testing::TestInfo&) override; }; +using ErrorHandler = iox::StaticLifetimeGuard; + } // namespace testing } // namespace iox diff --git a/iceoryx_hoofs/testing/include/iceoryx_hoofs/testing/error_reporting/testing_support.hpp b/iceoryx_hoofs/testing/include/iceoryx_hoofs/testing/error_reporting/testing_support.hpp index a9ec7f7c62..320f28265e 100644 --- a/iceoryx_hoofs/testing/include/iceoryx_hoofs/testing/error_reporting/testing_support.hpp +++ b/iceoryx_hoofs/testing/include/iceoryx_hoofs/testing/error_reporting/testing_support.hpp @@ -20,8 +20,6 @@ #include #include "iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp" -#include "iox/error_reporting/custom/default/error_handler.hpp" -#include "iox/static_lifetime_guard.hpp" #include #include @@ -34,8 +32,6 @@ namespace iox namespace testing { -using ErrorHandler = iox::StaticLifetimeGuard; - /// @brief indicates whether the test error handler registered a specific error template inline bool hasError(Code&& code) @@ -50,14 +46,11 @@ bool hasPanicked(); /// @brief indicates whether the test error handler registered any error bool hasError(); -/// @brief indicates whether the test error handler registered a required condition violation -bool hasRequiredConditionViolation(); - -/// @brief indicates whether the test error handler registered a precondition violation -bool hasPreconditionViolation(); +/// @brief indicates whether the test error handler registered an enforce violation +bool hasEnforceViolation(); -/// @brief indicates whether the test error handler registered an assumption violation -bool hasAssumptionViolation(); +/// @brief indicates whether the test error handler registered an assert violation +bool hasAssertViolation(); /// @brief indicates whether the test error handler registered violation (there are only two kinds). bool hasViolation(); @@ -127,11 +120,9 @@ inline void runInTestThread(Function&& testFunction, Args&&... args) #define IOX_TESTING_ASSERT_NO_VIOLATION() ASSERT_FALSE(iox::testing::hasViolation()) -#define IOX_TESTING_ASSERT_REQUIRED_CONDITION_VIOLATION() ASSERT_TRUE(iox::testing::hasRequiredConditionViolation()) +#define IOX_TESTING_ASSERT_ASSERT_VIOLATION() ASSERT_TRUE(iox::testing::hasAssertViolation()) -#define IOX_TESTING_ASSERT_PRECONDITION_VIOLATION() ASSERT_TRUE(iox::testing::hasPreconditionViolation()) - -#define IOX_TESTING_ASSERT_ASSUMPTION_VIOLATION() ASSERT_TRUE(iox::testing::hasAssumptionViolation()) +#define IOX_TESTING_ASSERT_ENFORCE_VIOLATION() ASSERT_TRUE(iox::testing::hasEnforceViolation()) // EXPECT_* continues with test if the check fails. @@ -149,11 +140,9 @@ inline void runInTestThread(Function&& testFunction, Args&&... args) #define IOX_TESTING_EXPECT_NO_VIOLATION() EXPECT_FALSE(iox::testing::hasViolation()) -#define IOX_TESTING_EXPECT_REQUIRED_CONDITION_VIOLATION() EXPECT_TRUE(iox::testing::hasRequiredConditionViolation()) - -#define IOX_TESTING_EXPECT_PRECONDITION_VIOLATION() EXPECT_TRUE(iox::testing::hasPreconditionViolation()) +#define IOX_TESTING_EXPECT_ASSERT_VIOLATION() EXPECT_TRUE(iox::testing::hasAssertViolation()) -#define IOX_TESTING_EXPECT_ASSUMPTION_VIOLATION() EXPECT_TRUE(iox::testing::hasAssumptionViolation()) +#define IOX_TESTING_EXPECT_ENFORCE_VIOLATION() EXPECT_TRUE(iox::testing::hasEnforceViolation()) // NOLINTEND(cppcoreguidelines-macro-usage) diff --git a/iceoryx_posh/test/integrationtests/test_posh_integration.cpp b/iceoryx_posh/test/integrationtests/test_posh_integration.cpp index 65e2e3be2c..e3b751e3cb 100644 --- a/iceoryx_posh/test/integrationtests/test_posh_integration.cpp +++ b/iceoryx_posh/test/integrationtests/test_posh_integration.cpp @@ -15,20 +15,17 @@ // // SPDX-License-Identifier: Apache-2.0 +#include "iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp" #include "iceoryx_hoofs/testing/testing_logger.hpp" -#include "iceoryx_platform/resource.hpp" -#include "iceoryx_posh/iceoryx_posh_types.hpp" #include "test.hpp" -using namespace ::testing; -using ::testing::_; - int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); iox::testing::TestingLogger::init(); + iox::testing::TestingErrorHandler::init(); return RUN_ALL_TESTS(); } diff --git a/iceoryx_posh/test/moduletests/test_posh_modules.cpp b/iceoryx_posh/test/moduletests/test_posh_modules.cpp index ba0507c87a..e3b751e3cb 100644 --- a/iceoryx_posh/test/moduletests/test_posh_modules.cpp +++ b/iceoryx_posh/test/moduletests/test_posh_modules.cpp @@ -15,19 +15,17 @@ // // SPDX-License-Identifier: Apache-2.0 +#include "iceoryx_hoofs/testing/error_reporting/testing_error_handler.hpp" #include "iceoryx_hoofs/testing/testing_logger.hpp" #include "test.hpp" -using namespace ::testing; -using ::testing::_; - - int main(int argc, char* argv[]) { ::testing::InitGoogleTest(&argc, argv); iox::testing::TestingLogger::init(); + iox::testing::TestingErrorHandler::init(); return RUN_ALL_TESTS(); }