diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 6a027c3c..04dfa84f 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -90,6 +90,7 @@ jobs: matrix: platform: - { name: Ubuntu GCC, os: ubuntu-latest, publish: true, compiler: g++, arch: "64", build: "ubuntu64-libstdc++-static", cmakepp: "", flags: "-DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS='--coverage' --warn-uninitialized -Wdev -Wno-deprecated -Werror=dev"} + - { name: Ubuntu GCC disabled, os: ubuntu-latest, publish: false, compiler: g++, arch: "64", build: "ubuntu64-libstdc++-static-disabled", cmakepp: "", flags: "-DCMAKE_CXX_COMPILER=g++ --warn-uninitialized -Wdev -Wno-deprecated -Werror=dev -DSNITCH_ENABLE=OFF"} - { name: Ubuntu GCC noexcept, os: ubuntu-latest, publish: false, compiler: g++, arch: "64", build: "ubuntu64-libstdc++-static-noexcept", cmakepp: "", flags: "-DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS='-fno-exceptions' --warn-uninitialized -Wdev -Wno-deprecated -Werror=dev"} - { name: Ubuntu GCC notime, os: ubuntu-latest, publish: false, compiler: g++, arch: "64", build: "ubuntu64-libstdc++-static-notime", cmakepp: "", flags: "-DCMAKE_CXX_COMPILER=g++ -DSNITCH_WITH_TIMINGS=0 --warn-uninitialized -Wdev -Wno-deprecated -Werror=dev"} - { name: Ubuntu GCC nounity, os: ubuntu-latest, publish: false, compiler: g++, arch: "64", build: "ubuntu64-libstdc++-static-nounity", cmakepp: "", flags: "-DCMAKE_CXX_COMPILER=g++ -DSNITCH_UNITY_BUILD=0 --warn-uninitialized -Wdev -Wno-deprecated -Werror=dev"} @@ -161,19 +162,20 @@ jobs: - name: Test (with doctest) # A bug in Node.js/V8 prevents these tests from running in Debug config for WebAssembly. # https://bugs.chromium.org/p/v8/issues/detail?id=13961 - if: ${{!(matrix.platform.compiler == 'em++' && matrix.build-type == 'Debug')}} + if: ${{!(matrix.platform.compiler == 'em++' && matrix.build-type == 'Debug') && !contains(matrix.platform.flags, '-DSNITCH_ENABLE=OFF')}} shell: bash working-directory: ${{github.workspace}}/build run: cmake --build . --config ${{matrix.build-type}} --target snitch_runtime_tests_run - name: Test (with snitch) + if: ${{!contains(matrix.platform.flags, '-DSNITCH_ENABLE=OFF')}} shell: bash working-directory: ${{github.workspace}}/build run: cmake --build . --config ${{matrix.build-type}} --target snitch_runtime_tests_self_run - name: Approval tests (with doctest) # Approval tests only run on "default" library configuration, which happens to be the published one - if: matrix.platform.publish + if: ${{matrix.platform.publish && !contains(matrix.platform.flags, '-DSNITCH_ENABLE=OFF')}} shell: bash working-directory: ${{github.workspace}}/build run: cmake --build . --config ${{matrix.build-type}} --target snitch_approval_tests_run diff --git a/CMakeLists.txt b/CMakeLists.txt index 36033218..ecde2825 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ set(SNITCH_MAX_PATH_LENGTH 1024 CACHE STRING "Maximum length of a file set(SNITCH_MAX_REPORTER_SIZE_BYTES 128 CACHE STRING "Maximum size (in bytes) of a reporter object.") # Feature toggles. +set(SNITCH_ENABLE ON CACHE BOOL "Enable/disable snitch at build time.") set(SNITCH_DEFINE_MAIN ON CACHE BOOL "Define main() in snitch -- disable to provide your own main() function.") set(SNITCH_WITH_EXCEPTIONS ON CACHE BOOL "Use exceptions in snitch implementation -- will be forced OFF if exceptions are not available.") set(SNITCH_WITH_MULTITHREADING ON CACHE BOOL "Make the testing framework thread-safe -- disable if multithreading is not needed.") @@ -115,10 +116,14 @@ set(SNITCH_SOURCES_INDIVIDUAL ${PROJECT_SOURCE_DIR}/src/snitch_test_data.cpp ${PROJECT_SOURCE_DIR}/src/snitch_time.cpp) -if (SNITCH_UNITY_BUILD) - set(SNITCH_SOURCES ${PROJECT_SOURCE_DIR}/src/snitch.cpp) +if (SNITCH_ENABLE) + if (SNITCH_UNITY_BUILD) + set(SNITCH_SOURCES ${PROJECT_SOURCE_DIR}/src/snitch.cpp) + else() + set(SNITCH_SOURCES ${SNITCH_SOURCES_INDIVIDUAL}) + endif() else() - set(SNITCH_SOURCES ${SNITCH_SOURCES_INDIVIDUAL}) + set(SNITCH_SOURCES ${PROJECT_SOURCE_DIR}/src/snitch_main.cpp) endif() function(configure_snitch_exports TARGET) @@ -211,7 +216,7 @@ install(FILES DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/cmake/snitch COMPONENT Development) # Setup tests -if (SNITCH_DO_TEST) +if (SNITCH_DO_TEST AND SNITCH_ENABLE) enable_testing() # We need to use a different snitch configuration for tests, so we can't reuse diff --git a/README.md b/README.md index 43816f77..d37fcdc5 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ The goal of _snitch_ is to be a simple, cheap, non-invasive, and user-friendly t - Additional API not in _Catch2_, or different from _Catch2_: - Matchers use a different API (see [Matchers](#matchers) below). - Additional macros for testing [`constexpr`](#run-time-and-compile-time) and [`consteval`](#compile-time) expressions. +- Can be disabled at build time, to allow mixing code and tests in the same file with minimal overheads. If you need features that are not in the list above, please use _Catch2_ or _doctest_. diff --git a/include/snitch/snitch.hpp b/include/snitch/snitch.hpp index 3fdbf709..b6cd6cd6 100644 --- a/include/snitch/snitch.hpp +++ b/include/snitch/snitch.hpp @@ -23,6 +23,7 @@ #include "snitch/snitch_macros_test_case.hpp" #include "snitch/snitch_macros_utility.hpp" #include "snitch/snitch_macros_warnings.hpp" +#include "snitch/snitch_main.hpp" #include "snitch/snitch_matcher.hpp" #include "snitch/snitch_registry.hpp" #include "snitch/snitch_reporter_catch2_xml.hpp" diff --git a/include/snitch/snitch_config.hpp.config b/include/snitch/snitch_config.hpp.config index 337ef072..fdbbcef4 100644 --- a/include/snitch/snitch_config.hpp.config +++ b/include/snitch/snitch_config.hpp.config @@ -89,6 +89,9 @@ #if !defined(SNITCH_SHARED_LIBRARY) #cmakedefine01 SNITCH_SHARED_LIBRARY #endif +#if !defined(SNITCH_ENABLE) +#cmakedefine01 SNITCH_ENABLE +#endif // clang-format on #if defined(_MSC_VER) diff --git a/include/snitch/snitch_macros_check.hpp b/include/snitch/snitch_macros_check.hpp index d9817839..0c638b72 100644 --- a/include/snitch/snitch_macros_check.hpp +++ b/include/snitch/snitch_macros_check.hpp @@ -4,97 +4,119 @@ #include "snitch/snitch_config.hpp" #include "snitch/snitch_expression.hpp" #include "snitch/snitch_macros_check_base.hpp" +#include "snitch/snitch_macros_utility.hpp" #include "snitch/snitch_macros_warnings.hpp" #include "snitch/snitch_matcher.hpp" #include "snitch/snitch_registry.hpp" #include "snitch/snitch_test_data.hpp" -#define SNITCH_REQUIRE_IMPL(CHECK, EXPECTED, MAYBE_ABORT, ...) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - SNITCH_WARNING_PUSH \ - SNITCH_WARNING_DISABLE_PARENTHESES \ - SNITCH_WARNING_DISABLE_CONSTANT_COMPARISON \ - if constexpr (SNITCH_IS_DECOMPOSABLE(__VA_ARGS__)) { \ - SNITCH_EXPR(CHECK, EXPECTED, __VA_ARGS__); \ - SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ - } else { \ - const auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ - CHECK, #__VA_ARGS__, {}, static_cast(__VA_ARGS__) == EXPECTED}; \ - SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ - } \ - SNITCH_WARNING_POP \ - } while (0) +#if SNITCH_ENABLE + +# define SNITCH_REQUIRE_IMPL(CHECK, EXPECTED, MAYBE_ABORT, ...) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ + SNITCH_WARNING_PUSH \ + SNITCH_WARNING_DISABLE_PARENTHESES \ + SNITCH_WARNING_DISABLE_CONSTANT_COMPARISON \ + if constexpr (SNITCH_IS_DECOMPOSABLE(__VA_ARGS__)) { \ + SNITCH_EXPR(CHECK, EXPECTED, __VA_ARGS__); \ + SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ + } else { \ + const auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ + CHECK, #__VA_ARGS__, {}, static_cast(__VA_ARGS__) == EXPECTED}; \ + SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ + } \ + SNITCH_WARNING_POP \ + } while (0) // clang-format off -#define SNITCH_REQUIRE(...) SNITCH_REQUIRE_IMPL("REQUIRE", true, SNITCH_TESTING_ABORT, __VA_ARGS__) -#define SNITCH_CHECK(...) SNITCH_REQUIRE_IMPL("CHECK", true, (void)0, __VA_ARGS__) -#define SNITCH_REQUIRE_FALSE(...) SNITCH_REQUIRE_IMPL("REQUIRE_FALSE", false, SNITCH_TESTING_ABORT, __VA_ARGS__) -#define SNITCH_CHECK_FALSE(...) SNITCH_REQUIRE_IMPL("CHECK_FALSE", false, (void)0, __VA_ARGS__) +# define SNITCH_REQUIRE(...) SNITCH_REQUIRE_IMPL("REQUIRE", true, SNITCH_TESTING_ABORT, __VA_ARGS__) +# define SNITCH_CHECK(...) SNITCH_REQUIRE_IMPL("CHECK", true, (void)0, __VA_ARGS__) +# define SNITCH_REQUIRE_FALSE(...) SNITCH_REQUIRE_IMPL("REQUIRE_FALSE", false, SNITCH_TESTING_ABORT, __VA_ARGS__) +# define SNITCH_CHECK_FALSE(...) SNITCH_REQUIRE_IMPL("CHECK_FALSE", false, (void)0, __VA_ARGS__) // clang-format on -#define SNITCH_SUCCEED(MESSAGE) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - snitch::registry::report_assertion(true, (MESSAGE)); \ - } while (0) - -#define SNITCH_FAIL(MESSAGE) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - snitch::registry::report_assertion(false, (MESSAGE)); \ - SNITCH_TESTING_ABORT; \ - } while (0) - -#define SNITCH_FAIL_CHECK(MESSAGE) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - snitch::registry::report_assertion(false, (MESSAGE)); \ - } while (0) - -#define SNITCH_SKIP(MESSAGE) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - snitch::registry::report_skipped((MESSAGE)); \ - SNITCH_TESTING_ABORT; \ - } while (0) - -#define SNITCH_SKIP_CHECK(MESSAGE) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - snitch::registry::report_skipped((MESSAGE)); \ - } while (0) - -#define SNITCH_REQUIRE_THAT_IMPL(CHECK, MAYBE_ABORT, EXPR, ...) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - const auto SNITCH_TEMP_RESULT = snitch::impl::match(EXPR, __VA_ARGS__); \ - const auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ - CHECK, #EXPR ", " #__VA_ARGS__, \ - snitch::resize_or_truncate(SNITCH_TEMP_RESULT.second), \ - SNITCH_TEMP_RESULT.first}; \ - SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ - } while (0) +# define SNITCH_SUCCEED(MESSAGE) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ + snitch::registry::report_assertion(true, (MESSAGE)); \ + } while (0) + +# define SNITCH_FAIL(MESSAGE) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ + snitch::registry::report_assertion(false, (MESSAGE)); \ + SNITCH_TESTING_ABORT; \ + } while (0) + +# define SNITCH_FAIL_CHECK(MESSAGE) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ + snitch::registry::report_assertion(false, (MESSAGE)); \ + } while (0) + +# define SNITCH_SKIP(MESSAGE) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ + snitch::registry::report_skipped((MESSAGE)); \ + SNITCH_TESTING_ABORT; \ + } while (0) + +# define SNITCH_SKIP_CHECK(MESSAGE) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ + snitch::registry::report_skipped((MESSAGE)); \ + } while (0) + +# define SNITCH_REQUIRE_THAT_IMPL(CHECK, MAYBE_ABORT, EXPR, ...) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ + const auto SNITCH_TEMP_RESULT = snitch::impl::match(EXPR, __VA_ARGS__); \ + const auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ + CHECK, #EXPR ", " #__VA_ARGS__, \ + snitch::resize_or_truncate(SNITCH_TEMP_RESULT.second), \ + SNITCH_TEMP_RESULT.first}; \ + SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ + } while (0) // clang-format off -#define SNITCH_REQUIRE_THAT(EXPR, ...) SNITCH_REQUIRE_THAT_IMPL("REQUIRE_THAT", SNITCH_TESTING_ABORT, EXPR, __VA_ARGS__) -#define SNITCH_CHECK_THAT(EXPR, ...) SNITCH_REQUIRE_THAT_IMPL("CHECK_THAT", (void)0, EXPR, __VA_ARGS__) +# define SNITCH_REQUIRE_THAT(EXPR, ...) SNITCH_REQUIRE_THAT_IMPL("REQUIRE_THAT", SNITCH_TESTING_ABORT, EXPR, __VA_ARGS__) +# define SNITCH_CHECK_THAT(EXPR, ...) SNITCH_REQUIRE_THAT_IMPL("CHECK_THAT", (void)0, EXPR, __VA_ARGS__) // clang-format on +#else // SNITCH_ENABLE // clang-format off +# define SNITCH_REQUIRE(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_CHECK(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_REQUIRE_FALSE(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_CHECK_FALSE(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) + +# define SNITCH_SUCCEED(MESSAGE) SNITCH_VOID_STATEMENT +# define SNITCH_FAIL(MESSAGE) SNITCH_VOID_STATEMENT +# define SNITCH_FAIL_CHECK(MESSAGE) SNITCH_VOID_STATEMENT +# define SNITCH_SKIP(MESSAGE) SNITCH_VOID_STATEMENT +# define SNITCH_SKIP_CHECK(MESSAGE) SNITCH_VOID_STATEMENT + +# define SNITCH_REQUIRE_THAT(EXPR, ...) SNITCH_DISCARD_ARGS(EXPR, __VA_ARGS__) +# define SNITCH_CHECK_THAT(EXPR, ...) SNITCH_DISCARD_ARGS(EXPR, __VA_ARGS__) +// clang-format on + +#endif // SNITCH_ENABLE + +// clang-format on #if SNITCH_WITH_SHORTHAND_MACROS -# define SUCCEED(MESSAGE) SNITCH_SUCCEED(MESSAGE) -# define FAIL(MESSAGE) SNITCH_FAIL(MESSAGE) +# define SUCCEED(MESSAGE) SNITCH_SUCCEED(MESSAGE) +# define FAIL(MESSAGE) SNITCH_FAIL(MESSAGE) # define FAIL_CHECK(MESSAGE) SNITCH_FAIL_CHECK(MESSAGE) -# define SKIP(MESSAGE) SNITCH_SKIP(MESSAGE) +# define SKIP(MESSAGE) SNITCH_SKIP(MESSAGE) # define SKIP_CHECK(MESSAGE) SNITCH_SKIP_CHECK(MESSAGE) -# define REQUIRE(...) SNITCH_REQUIRE(__VA_ARGS__) -# define CHECK(...) SNITCH_CHECK(__VA_ARGS__) -# define REQUIRE_FALSE(...) SNITCH_REQUIRE_FALSE(__VA_ARGS__) -# define CHECK_FALSE(...) SNITCH_CHECK_FALSE(__VA_ARGS__) +# define REQUIRE(...) SNITCH_REQUIRE(__VA_ARGS__) +# define CHECK(...) SNITCH_CHECK(__VA_ARGS__) +# define REQUIRE_FALSE(...) SNITCH_REQUIRE_FALSE(__VA_ARGS__) +# define CHECK_FALSE(...) SNITCH_CHECK_FALSE(__VA_ARGS__) # define REQUIRE_THAT(EXP, ...) SNITCH_REQUIRE_THAT(EXP, __VA_ARGS__) -# define CHECK_THAT(EXP, ...) SNITCH_CHECK_THAT(EXP, __VA_ARGS__) +# define CHECK_THAT(EXP, ...) SNITCH_CHECK_THAT(EXP, __VA_ARGS__) #endif // clang-format on diff --git a/include/snitch/snitch_macros_check_base.hpp b/include/snitch/snitch_macros_check_base.hpp index 43201282..0ae78ebd 100644 --- a/include/snitch/snitch_macros_check_base.hpp +++ b/include/snitch/snitch_macros_check_base.hpp @@ -15,7 +15,9 @@ #endif #define SNITCH_NEW_CHECK \ - snitch::impl::scoped_test_check { SNITCH_CURRENT_LOCATION } + snitch::impl::scoped_test_check { \ + SNITCH_CURRENT_LOCATION \ + } #define SNITCH_EXPR(TYPE, EXPECTED, ...) \ auto SNITCH_CURRENT_EXPRESSION = \ diff --git a/include/snitch/snitch_macros_consteval.hpp b/include/snitch/snitch_macros_consteval.hpp index 8e52e340..d0c09163 100644 --- a/include/snitch/snitch_macros_consteval.hpp +++ b/include/snitch/snitch_macros_consteval.hpp @@ -4,51 +4,67 @@ #include "snitch/snitch_config.hpp" #include "snitch/snitch_expression.hpp" #include "snitch/snitch_macros_check_base.hpp" +#include "snitch/snitch_macros_utility.hpp" #include "snitch/snitch_macros_warnings.hpp" #include "snitch/snitch_matcher.hpp" #include "snitch/snitch_registry.hpp" #include "snitch/snitch_test_data.hpp" -#define SNITCH_CONSTEVAL_REQUIRE_IMPL(CHECK, EXPECTED, MAYBE_ABORT, ...) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - SNITCH_WARNING_PUSH \ - SNITCH_WARNING_DISABLE_PARENTHESES \ - SNITCH_WARNING_DISABLE_CONSTANT_COMPARISON \ - if constexpr (SNITCH_IS_DECOMPOSABLE(__VA_ARGS__)) { \ - constexpr SNITCH_EXPR(CHECK, EXPECTED, __VA_ARGS__); \ - SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ - } else { \ +#if SNITCH_ENABLE + +# define SNITCH_CONSTEVAL_REQUIRE_IMPL(CHECK, EXPECTED, MAYBE_ABORT, ...) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ + SNITCH_WARNING_PUSH \ + SNITCH_WARNING_DISABLE_PARENTHESES \ + SNITCH_WARNING_DISABLE_CONSTANT_COMPARISON \ + if constexpr (SNITCH_IS_DECOMPOSABLE(__VA_ARGS__)) { \ + constexpr SNITCH_EXPR(CHECK, EXPECTED, __VA_ARGS__); \ + SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ + } else { \ + constexpr auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ + CHECK, #__VA_ARGS__, {}, static_cast(__VA_ARGS__) == EXPECTED}; \ + SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ + } \ + SNITCH_WARNING_POP \ + } while (0) + +// clang-format off +# define SNITCH_CONSTEVAL_REQUIRE(...) SNITCH_CONSTEVAL_REQUIRE_IMPL("CONSTEVAL_REQUIRE", true, SNITCH_TESTING_ABORT, __VA_ARGS__) +# define SNITCH_CONSTEVAL_CHECK(...) SNITCH_CONSTEVAL_REQUIRE_IMPL("CONSTEVAL_CHECK", true, (void)0, __VA_ARGS__) +# define SNITCH_CONSTEVAL_REQUIRE_FALSE(...) SNITCH_CONSTEVAL_REQUIRE_IMPL("CONSTEVAL_REQUIRE_FALSE", false, SNITCH_TESTING_ABORT, __VA_ARGS__) +# define SNITCH_CONSTEVAL_CHECK_FALSE(...) SNITCH_CONSTEVAL_REQUIRE_IMPL("CONSTEVAL_CHECK_FALSE", false, (void)0, __VA_ARGS__) +// clang-format on + +# define SNITCH_CONSTEVAL_REQUIRE_THAT_IMPL(CHECK, MAYBE_ABORT, EXPR, ...) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ + constexpr auto SNITCH_TEMP_RESULT = snitch::impl::match(EXPR, __VA_ARGS__); \ constexpr auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ - CHECK, #__VA_ARGS__, {}, static_cast(__VA_ARGS__) == EXPECTED}; \ + CHECK, #EXPR ", " #__VA_ARGS__, \ + snitch::resize_or_truncate(SNITCH_TEMP_RESULT.second), \ + SNITCH_TEMP_RESULT.first}; \ SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ - } \ - SNITCH_WARNING_POP \ - } while (0) + } while (0) // clang-format off -#define SNITCH_CONSTEVAL_REQUIRE(...) SNITCH_CONSTEVAL_REQUIRE_IMPL("CONSTEVAL_REQUIRE", true, SNITCH_TESTING_ABORT, __VA_ARGS__) -#define SNITCH_CONSTEVAL_CHECK(...) SNITCH_CONSTEVAL_REQUIRE_IMPL("CONSTEVAL_CHECK", true, (void)0, __VA_ARGS__) -#define SNITCH_CONSTEVAL_REQUIRE_FALSE(...) SNITCH_CONSTEVAL_REQUIRE_IMPL("CONSTEVAL_REQUIRE_FALSE", false, SNITCH_TESTING_ABORT, __VA_ARGS__) -#define SNITCH_CONSTEVAL_CHECK_FALSE(...) SNITCH_CONSTEVAL_REQUIRE_IMPL("CONSTEVAL_CHECK_FALSE", false, (void)0, __VA_ARGS__) +# define SNITCH_CONSTEVAL_REQUIRE_THAT(EXPR, ...) SNITCH_CONSTEVAL_REQUIRE_THAT_IMPL("CONSTEVAL_REQUIRE_THAT", SNITCH_TESTING_ABORT, EXPR, __VA_ARGS__) +# define SNITCH_CONSTEVAL_CHECK_THAT(EXPR, ...) SNITCH_CONSTEVAL_REQUIRE_THAT_IMPL("CONSTEVAL_CHECK_THAT", (void)0, EXPR, __VA_ARGS__) // clang-format on -#define SNITCH_CONSTEVAL_REQUIRE_THAT_IMPL(CHECK, MAYBE_ABORT, EXPR, ...) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - constexpr auto SNITCH_TEMP_RESULT = snitch::impl::match(EXPR, __VA_ARGS__); \ - constexpr auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ - CHECK, #EXPR ", " #__VA_ARGS__, \ - snitch::resize_or_truncate(SNITCH_TEMP_RESULT.second), \ - SNITCH_TEMP_RESULT.first}; \ - SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ - } while (0) +#else // SNITCH_ENABLE // clang-format off -#define SNITCH_CONSTEVAL_REQUIRE_THAT(EXPR, ...) SNITCH_CONSTEVAL_REQUIRE_THAT_IMPL("CONSTEVAL_REQUIRE_THAT", SNITCH_TESTING_ABORT, EXPR, __VA_ARGS__) -#define SNITCH_CONSTEVAL_CHECK_THAT(EXPR, ...) SNITCH_CONSTEVAL_REQUIRE_THAT_IMPL("CONSTEVAL_CHECK_THAT", (void)0, EXPR, __VA_ARGS__) +# define SNITCH_CONSTEVAL_REQUIRE(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_CONSTEVAL_CHECK(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_CONSTEVAL_REQUIRE_FALSE(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_CONSTEVAL_CHECK_FALSE(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_CONSTEVAL_REQUIRE_THAT(EXPR, ...) SNITCH_DISCARD_ARGS(EXPR, __VA_ARGS__) +# define SNITCH_CONSTEVAL_CHECK_THAT(EXPR, ...) SNITCH_DISCARD_ARGS(EXPR, __VA_ARGS__) // clang-format on +#endif // SNITCH_ENABLE + // clang-format off #if SNITCH_WITH_SHORTHAND_MACROS # define CONSTEVAL_REQUIRE(...) SNITCH_CONSTEVAL_REQUIRE(__VA_ARGS__) diff --git a/include/snitch/snitch_macros_constexpr.hpp b/include/snitch/snitch_macros_constexpr.hpp index b67d6e95..94f53d7f 100644 --- a/include/snitch/snitch_macros_constexpr.hpp +++ b/include/snitch/snitch_macros_constexpr.hpp @@ -4,79 +4,96 @@ #include "snitch/snitch_config.hpp" #include "snitch/snitch_expression.hpp" #include "snitch/snitch_macros_check_base.hpp" +#include "snitch/snitch_macros_utility.hpp" #include "snitch/snitch_macros_warnings.hpp" #include "snitch/snitch_matcher.hpp" #include "snitch/snitch_registry.hpp" #include "snitch/snitch_test_data.hpp" -#define SNITCH_CONSTEXPR_REQUIRE_IMPL(CHECK, EXPECTED, MAYBE_ABORT, ...) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - SNITCH_WARNING_PUSH \ - SNITCH_WARNING_DISABLE_PARENTHESES \ - SNITCH_WARNING_DISABLE_CONSTANT_COMPARISON \ - if constexpr (SNITCH_IS_DECOMPOSABLE(__VA_ARGS__)) { \ - { \ - constexpr SNITCH_EXPR(CHECK "[compile-time]", EXPECTED, __VA_ARGS__); \ - SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ - } \ - { \ - SNITCH_EXPR(CHECK "[run-time]", EXPECTED, __VA_ARGS__); \ - SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ +#if SNITCH_ENABLE + +# define SNITCH_CONSTEXPR_REQUIRE_IMPL(CHECK, EXPECTED, MAYBE_ABORT, ...) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ + SNITCH_WARNING_PUSH \ + SNITCH_WARNING_DISABLE_PARENTHESES \ + SNITCH_WARNING_DISABLE_CONSTANT_COMPARISON \ + if constexpr (SNITCH_IS_DECOMPOSABLE(__VA_ARGS__)) { \ + { \ + constexpr SNITCH_EXPR(CHECK "[compile-time]", EXPECTED, __VA_ARGS__); \ + SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ + } \ + { \ + SNITCH_EXPR(CHECK "[run-time]", EXPECTED, __VA_ARGS__); \ + SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ + } \ + } else { \ + { \ + constexpr auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ + CHECK "[compile-time]", \ + #__VA_ARGS__, \ + {}, \ + static_cast(__VA_ARGS__) == EXPECTED}; \ + SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ + } \ + { \ + const auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ + CHECK "[run-time]", \ + #__VA_ARGS__, \ + {}, \ + static_cast(__VA_ARGS__) == EXPECTED}; \ + SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ + } \ } \ - } else { \ + SNITCH_WARNING_POP \ + } while (0) + +// clang-format off +# define SNITCH_CONSTEXPR_REQUIRE(...) SNITCH_CONSTEXPR_REQUIRE_IMPL("CONSTEXPR_REQUIRE", true, SNITCH_TESTING_ABORT, __VA_ARGS__) +# define SNITCH_CONSTEXPR_CHECK(...) SNITCH_CONSTEXPR_REQUIRE_IMPL("CONSTEXPR_CHECK", true, (void)0, __VA_ARGS__) +# define SNITCH_CONSTEXPR_REQUIRE_FALSE(...) SNITCH_CONSTEXPR_REQUIRE_IMPL("CONSTEXPR_REQUIRE_FALSE", false, SNITCH_TESTING_ABORT, __VA_ARGS__) +# define SNITCH_CONSTEXPR_CHECK_FALSE(...) SNITCH_CONSTEXPR_REQUIRE_IMPL("CONSTEXPR_CHECK_FALSE", false, (void)0, __VA_ARGS__) +// clang-format on + +# define SNITCH_CONSTEXPR_REQUIRE_THAT_IMPL(CHECK, MAYBE_ABORT, EXPR, ...) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ { \ + constexpr auto SNITCH_TEMP_RESULT = snitch::impl::match(EXPR, __VA_ARGS__); \ constexpr auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ - CHECK "[compile-time]", \ - #__VA_ARGS__, \ - {}, \ - static_cast(__VA_ARGS__) == EXPECTED}; \ + CHECK "[compile-time]", #EXPR ", " #__VA_ARGS__, \ + snitch::resize_or_truncate( \ + SNITCH_TEMP_RESULT.second), \ + SNITCH_TEMP_RESULT.first}; \ SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ } \ { \ + const auto SNITCH_TEMP_RESULT = snitch::impl::match(EXPR, __VA_ARGS__); \ const auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ - CHECK "[run-time]", \ - #__VA_ARGS__, \ - {}, \ - static_cast(__VA_ARGS__) == EXPECTED}; \ + CHECK "[run-time]", #EXPR ", " #__VA_ARGS__, \ + snitch::resize_or_truncate( \ + SNITCH_TEMP_RESULT.second), \ + SNITCH_TEMP_RESULT.first}; \ SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ } \ - } \ - SNITCH_WARNING_POP \ - } while (0) + } while (0) // clang-format off -#define SNITCH_CONSTEXPR_REQUIRE(...) SNITCH_CONSTEXPR_REQUIRE_IMPL("CONSTEXPR_REQUIRE", true, SNITCH_TESTING_ABORT, __VA_ARGS__) -#define SNITCH_CONSTEXPR_CHECK(...) SNITCH_CONSTEXPR_REQUIRE_IMPL("CONSTEXPR_CHECK", true, (void)0, __VA_ARGS__) -#define SNITCH_CONSTEXPR_REQUIRE_FALSE(...) SNITCH_CONSTEXPR_REQUIRE_IMPL("CONSTEXPR_REQUIRE_FALSE", false, SNITCH_TESTING_ABORT, __VA_ARGS__) -#define SNITCH_CONSTEXPR_CHECK_FALSE(...) SNITCH_CONSTEXPR_REQUIRE_IMPL("CONSTEXPR_CHECK_FALSE", false, (void)0, __VA_ARGS__) +# define SNITCH_CONSTEXPR_REQUIRE_THAT(EXPR, ...) SNITCH_CONSTEXPR_REQUIRE_THAT_IMPL("CONSTEXPR_REQUIRE_THAT", SNITCH_TESTING_ABORT, EXPR, __VA_ARGS__) +# define SNITCH_CONSTEXPR_CHECK_THAT(EXPR, ...) SNITCH_CONSTEXPR_REQUIRE_THAT_IMPL("CONSTEXPR_CHECK_THAT", (void)0, EXPR, __VA_ARGS__) // clang-format on -#define SNITCH_CONSTEXPR_REQUIRE_THAT_IMPL(CHECK, MAYBE_ABORT, EXPR, ...) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - { \ - constexpr auto SNITCH_TEMP_RESULT = snitch::impl::match(EXPR, __VA_ARGS__); \ - constexpr auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ - CHECK "[compile-time]", #EXPR ", " #__VA_ARGS__, \ - snitch::resize_or_truncate(SNITCH_TEMP_RESULT.second), \ - SNITCH_TEMP_RESULT.first}; \ - SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ - } \ - { \ - const auto SNITCH_TEMP_RESULT = snitch::impl::match(EXPR, __VA_ARGS__); \ - const auto SNITCH_CURRENT_EXPRESSION = snitch::impl::expression{ \ - CHECK "[run-time]", #EXPR ", " #__VA_ARGS__, \ - snitch::resize_or_truncate(SNITCH_TEMP_RESULT.second), \ - SNITCH_TEMP_RESULT.first}; \ - SNITCH_REPORT_EXPRESSION(MAYBE_ABORT); \ - } \ - } while (0) +#else // SNITCH_ENABLE // clang-format off -#define SNITCH_CONSTEXPR_REQUIRE_THAT(EXPR, ...) SNITCH_CONSTEXPR_REQUIRE_THAT_IMPL("CONSTEXPR_REQUIRE_THAT", SNITCH_TESTING_ABORT, EXPR, __VA_ARGS__) -#define SNITCH_CONSTEXPR_CHECK_THAT(EXPR, ...) SNITCH_CONSTEXPR_REQUIRE_THAT_IMPL("CONSTEXPR_CHECK_THAT", (void)0, EXPR, __VA_ARGS__) +# define SNITCH_CONSTEXPR_REQUIRE(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_CONSTEXPR_CHECK(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_CONSTEXPR_REQUIRE_FALSE(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_CONSTEXPR_CHECK_FALSE(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_CONSTEXPR_REQUIRE_THAT(EXPR, ...) SNITCH_DISCARD_ARGS(EXPR, __VA_ARGS__) +# define SNITCH_CONSTEXPR_CHECK_THAT(EXPR, ...) SNITCH_DISCARD_ARGS(EXPR, __VA_ARGS__) // clang-format on +#endif // SNITCH_ENABLE // clang-format off #if SNITCH_WITH_SHORTHAND_MACROS diff --git a/include/snitch/snitch_macros_exceptions.hpp b/include/snitch/snitch_macros_exceptions.hpp index 883e20e9..339b8640 100644 --- a/include/snitch/snitch_macros_exceptions.hpp +++ b/include/snitch/snitch_macros_exceptions.hpp @@ -3,125 +3,144 @@ #if SNITCH_WITH_EXCEPTIONS # include "snitch/snitch_config.hpp" +# include "snitch/snitch_macros_utility.hpp" # include "snitch/snitch_matcher.hpp" # include "snitch/snitch_registry.hpp" # include -# define SNITCH_REQUIRE_THROWS_AS_IMPL(MAYBE_ABORT, EXPRESSION, ...) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - bool SNITCH_NO_EXCEPTION_THROWN = false; \ - try { \ - static_cast(EXPRESSION); \ - SNITCH_NO_EXCEPTION_THROWN = true; \ - } catch (const __VA_ARGS__&) { \ - snitch::registry::report_assertion(true, #__VA_ARGS__ " was thrown as expected"); \ - snitch::notify_exception_handled(); \ - } catch (...) { \ +# if SNITCH_ENABLE +# define SNITCH_REQUIRE_THROWS_AS_IMPL(MAYBE_ABORT, EXPRESSION, ...) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ + bool SNITCH_NO_EXCEPTION_THROWN = false; \ try { \ - throw; \ - } catch (const std::exception& e) { \ + static_cast(EXPRESSION); \ + SNITCH_NO_EXCEPTION_THROWN = true; \ + } catch (const __VA_ARGS__&) { \ snitch::registry::report_assertion( \ - false, \ - #__VA_ARGS__ " expected but other std::exception thrown; message: ", \ - e.what()); \ + true, #__VA_ARGS__ " was thrown as expected"); \ + snitch::notify_exception_handled(); \ } catch (...) { \ + try { \ + throw; \ + } catch (const std::exception& e) { \ + snitch::registry::report_assertion( \ + false, \ + #__VA_ARGS__ " expected but other std::exception thrown; message: ", \ + e.what()); \ + } catch (...) { \ + snitch::registry::report_assertion( \ + false, #__VA_ARGS__ " expected but other unknown exception thrown"); \ + } \ + snitch::notify_exception_handled(); \ + MAYBE_ABORT; \ + } \ + if (SNITCH_NO_EXCEPTION_THROWN) { \ snitch::registry::report_assertion( \ - false, #__VA_ARGS__ " expected but other unknown exception thrown"); \ + false, #__VA_ARGS__ " expected but no exception thrown"); \ + MAYBE_ABORT; \ } \ - snitch::notify_exception_handled(); \ - MAYBE_ABORT; \ - } \ - if (SNITCH_NO_EXCEPTION_THROWN) { \ - snitch::registry::report_assertion( \ - false, #__VA_ARGS__ " expected but no exception thrown"); \ - MAYBE_ABORT; \ - } \ - } while (0) + } while (0) -# define SNITCH_REQUIRE_THROWS_AS(EXPRESSION, ...) \ - SNITCH_REQUIRE_THROWS_AS_IMPL(SNITCH_TESTING_ABORT, EXPRESSION, __VA_ARGS__) -# define SNITCH_CHECK_THROWS_AS(EXPRESSION, ...) \ - SNITCH_REQUIRE_THROWS_AS_IMPL((void)0, EXPRESSION, __VA_ARGS__) +# define SNITCH_REQUIRE_THROWS_AS(EXPRESSION, ...) \ + SNITCH_REQUIRE_THROWS_AS_IMPL(SNITCH_TESTING_ABORT, EXPRESSION, __VA_ARGS__) +# define SNITCH_CHECK_THROWS_AS(EXPRESSION, ...) \ + SNITCH_REQUIRE_THROWS_AS_IMPL((void)0, EXPRESSION, __VA_ARGS__) -# define SNITCH_REQUIRE_THROWS_MATCHES_IMPL(MAYBE_ABORT, EXPRESSION, EXCEPTION, ...) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - bool SNITCH_NO_EXCEPTION_THROWN = false; \ - try { \ - static_cast(EXPRESSION); \ - SNITCH_NO_EXCEPTION_THROWN = true; \ - } catch (const EXCEPTION& e) { \ - auto&& SNITCH_TEMP_MATCHER = __VA_ARGS__; \ - if (!SNITCH_TEMP_MATCHER.match(e)) { \ - snitch::registry::report_assertion( \ - false, "could not match caught " #EXCEPTION " with expected content: ", \ - SNITCH_TEMP_MATCHER.describe_match( \ - e, snitch::matchers::match_status::failed)); \ +# define SNITCH_REQUIRE_THROWS_MATCHES_IMPL(MAYBE_ABORT, EXPRESSION, EXCEPTION, ...) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ + bool SNITCH_NO_EXCEPTION_THROWN = false; \ + try { \ + static_cast(EXPRESSION); \ + SNITCH_NO_EXCEPTION_THROWN = true; \ + } catch (const EXCEPTION& e) { \ + auto&& SNITCH_TEMP_MATCHER = __VA_ARGS__; \ + if (!SNITCH_TEMP_MATCHER.match(e)) { \ + snitch::registry::report_assertion( \ + false, \ + "could not match caught " #EXCEPTION " with expected content: ", \ + SNITCH_TEMP_MATCHER.describe_match( \ + e, snitch::matchers::match_status::failed)); \ + snitch::notify_exception_handled(); \ + MAYBE_ABORT; \ + } else { \ + snitch::registry::report_assertion( \ + true, "caught " #EXCEPTION " matched expected content: ", \ + SNITCH_TEMP_MATCHER.describe_match( \ + e, snitch::matchers::match_status::matched)); \ + snitch::notify_exception_handled(); \ + } \ + } catch (...) { \ + try { \ + throw; \ + } catch (const std::exception& e) { \ + snitch::registry::report_assertion( \ + false, \ + #EXCEPTION " expected but other std::exception thrown; message: ", \ + e.what()); \ + } catch (...) { \ + snitch::registry::report_assertion( \ + false, #EXCEPTION " expected but other unknown exception thrown"); \ + } \ snitch::notify_exception_handled(); \ MAYBE_ABORT; \ - } else { \ - snitch::registry::report_assertion( \ - true, "caught " #EXCEPTION " matched expected content: ", \ - SNITCH_TEMP_MATCHER.describe_match( \ - e, snitch::matchers::match_status::matched)); \ - snitch::notify_exception_handled(); \ } \ - } catch (...) { \ - try { \ - throw; \ - } catch (const std::exception& e) { \ + if (SNITCH_NO_EXCEPTION_THROWN) { \ snitch::registry::report_assertion( \ - false, #EXCEPTION " expected but other std::exception thrown; message: ", \ - e.what()); \ - } catch (...) { \ - snitch::registry::report_assertion( \ - false, #EXCEPTION " expected but other unknown exception thrown"); \ + false, #EXCEPTION " expected but no exception thrown"); \ + MAYBE_ABORT; \ } \ - snitch::notify_exception_handled(); \ - MAYBE_ABORT; \ - } \ - if (SNITCH_NO_EXCEPTION_THROWN) { \ - snitch::registry::report_assertion( \ - false, #EXCEPTION " expected but no exception thrown"); \ - MAYBE_ABORT; \ - } \ - } while (0) + } while (0) -# define SNITCH_REQUIRE_THROWS_MATCHES(EXPRESSION, EXCEPTION, ...) \ - SNITCH_REQUIRE_THROWS_MATCHES_IMPL(SNITCH_TESTING_ABORT, EXPRESSION, EXCEPTION, __VA_ARGS__) -# define SNITCH_CHECK_THROWS_MATCHES(EXPRESSION, EXCEPTION, ...) \ - SNITCH_REQUIRE_THROWS_MATCHES_IMPL((void)0, EXPRESSION, EXCEPTION, __VA_ARGS__) +# define SNITCH_REQUIRE_THROWS_MATCHES(EXPRESSION, EXCEPTION, ...) \ + SNITCH_REQUIRE_THROWS_MATCHES_IMPL( \ + SNITCH_TESTING_ABORT, EXPRESSION, EXCEPTION, __VA_ARGS__) +# define SNITCH_CHECK_THROWS_MATCHES(EXPRESSION, EXCEPTION, ...) \ + SNITCH_REQUIRE_THROWS_MATCHES_IMPL((void)0, EXPRESSION, EXCEPTION, __VA_ARGS__) -# define SNITCH_REQUIRE_NOTHROW_IMPL(MAYBE_ABORT, ...) \ - do { \ - auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ - try { \ - static_cast(__VA_ARGS__); \ - snitch::registry::report_assertion(true, #__VA_ARGS__ " did not throw"); \ - } catch (...) { \ +# define SNITCH_REQUIRE_NOTHROW_IMPL(MAYBE_ABORT, ...) \ + do { \ + auto SNITCH_CURRENT_CHECK = SNITCH_NEW_CHECK; \ try { \ - throw; \ - } catch (const std::exception& e) { \ - snitch::registry::report_assertion( \ - false, \ - "expected " #__VA_ARGS__ \ - " not to throw but it threw a std::exception; message: ", \ - e.what()); \ + static_cast(__VA_ARGS__); \ + snitch::registry::report_assertion(true, #__VA_ARGS__ " did not throw"); \ } catch (...) { \ - snitch::registry::report_assertion( \ - false, "expected " #__VA_ARGS__ \ - " not to throw but it threw an unknown exception"); \ + try { \ + throw; \ + } catch (const std::exception& e) { \ + snitch::registry::report_assertion( \ + false, \ + "expected " #__VA_ARGS__ \ + " not to throw but it threw a std::exception; message: ", \ + e.what()); \ + } catch (...) { \ + snitch::registry::report_assertion( \ + false, "expected " #__VA_ARGS__ \ + " not to throw but it threw an unknown exception"); \ + } \ + snitch::notify_exception_handled(); \ + MAYBE_ABORT; \ } \ - snitch::notify_exception_handled(); \ - MAYBE_ABORT; \ - } \ - } while (0) + } while (0) + +# define SNITCH_REQUIRE_NOTHROW(...) \ + SNITCH_REQUIRE_NOTHROW_IMPL(SNITCH_TESTING_ABORT, __VA_ARGS__) +# define SNITCH_CHECK_NOTHROW(...) SNITCH_REQUIRE_NOTHROW_IMPL((void)0, __VA_ARGS__) + +# else // SNITCH_ENABLE + +// clang-format off +# define SNITCH_REQUIRE_THROWS_AS(EXPRESSION, ...) SNITCH_DISCARD_ARGS(EXPRESSION, sizeof(__VA_ARGS__)) +# define SNITCH_CHECK_THROWS_AS(EXPRESSION, ...) SNITCH_DISCARD_ARGS(EXPRESSION, sizeof(__VA_ARGS__)) +# define SNITCH_REQUIRE_THROWS_MATCHES(EXPRESSION, EXCEPTION, ...) SNITCH_DISCARD_ARGS(EXPRESSION, sizeof(EXCEPTION), __VA_ARGS__) +# define SNITCH_CHECK_THROWS_MATCHES(EXPRESSION, EXCEPTION, ...) SNITCH_DISCARD_ARGS(EXPRESSION, sizeof(EXCEPTION), __VA_ARGS__) +# define SNITCH_REQUIRE_NOTHROW(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_CHECK_NOTHROW(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +// clang-format on -# define SNITCH_REQUIRE_NOTHROW(...) \ - SNITCH_REQUIRE_NOTHROW_IMPL(SNITCH_TESTING_ABORT, __VA_ARGS__) -# define SNITCH_CHECK_NOTHROW(...) SNITCH_REQUIRE_NOTHROW_IMPL((void)0, __VA_ARGS__) +# endif // SNITCH_ENABLE // clang-format off #if SNITCH_WITH_SHORTHAND_MACROS diff --git a/include/snitch/snitch_macros_misc.hpp b/include/snitch/snitch_macros_misc.hpp index 74a5fd4d..878d1088 100644 --- a/include/snitch/snitch_macros_misc.hpp +++ b/include/snitch/snitch_macros_misc.hpp @@ -7,17 +7,25 @@ #include "snitch/snitch_section.hpp" #include "snitch/snitch_test_data.hpp" -#define SNITCH_SECTION(...) \ - if (snitch::impl::section_entry_checker SNITCH_MACRO_CONCAT(section_id_, __COUNTER__){ \ - {__VA_ARGS__}, SNITCH_CURRENT_LOCATION, snitch::impl::get_current_test()}) +#if SNITCH_ENABLE +# define SNITCH_SECTION(...) \ + if (snitch::impl::section_entry_checker SNITCH_MACRO_CONCAT(section_id_, __COUNTER__){ \ + {__VA_ARGS__}, SNITCH_CURRENT_LOCATION, snitch::impl::get_current_test()}) -#define SNITCH_CAPTURE(...) \ - auto SNITCH_MACRO_CONCAT(capture_id_, __COUNTER__) = \ - snitch::impl::add_captures(snitch::impl::get_current_test(), #__VA_ARGS__, __VA_ARGS__) +# define SNITCH_CAPTURE(...) \ + auto SNITCH_MACRO_CONCAT(capture_id_, __COUNTER__) = snitch::impl::add_captures( \ + snitch::impl::get_current_test(), #__VA_ARGS__, __VA_ARGS__) -#define SNITCH_INFO(...) \ - auto SNITCH_MACRO_CONCAT(capture_id_, __COUNTER__) = \ - snitch::impl::add_info(snitch::impl::get_current_test(), __VA_ARGS__) +# define SNITCH_INFO(...) \ + auto SNITCH_MACRO_CONCAT(capture_id_, __COUNTER__) = \ + snitch::impl::add_info(snitch::impl::get_current_test(), __VA_ARGS__) +#else // SNITCH_ENABLE +// clang-format off +# define SNITCH_SECTION(NAME, ...) if constexpr (false) +# define SNITCH_CAPTURE(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +# define SNITCH_INFO(...) SNITCH_DISCARD_ARGS(__VA_ARGS__) +// clang-format on +#endif // SNITCH_ENABLE // clang-format off #if SNITCH_WITH_SHORTHAND_MACROS diff --git a/include/snitch/snitch_macros_reporter.hpp b/include/snitch/snitch_macros_reporter.hpp index 91934758..22f73cf6 100644 --- a/include/snitch/snitch_macros_reporter.hpp +++ b/include/snitch/snitch_macros_reporter.hpp @@ -5,13 +5,18 @@ #include "snitch/snitch_macros_utility.hpp" #include "snitch/snitch_registry.hpp" -#define SNITCH_REGISTER_REPORTER_CALLBACKS(NAME, ...) \ - static const std::string_view SNITCH_MACRO_CONCAT(reporter_id_, __COUNTER__) \ - [[maybe_unused]] = snitch::tests.add_reporter(NAME, __VA_ARGS__) +#if SNITCH_ENABLE +# define SNITCH_REGISTER_REPORTER_CALLBACKS(NAME, ...) \ + static const std::string_view SNITCH_MACRO_CONCAT(reporter_id_, __COUNTER__) \ + [[maybe_unused]] = snitch::tests.add_reporter(NAME, __VA_ARGS__) -#define SNITCH_REGISTER_REPORTER(NAME, TYPE) \ - static const std::string_view SNITCH_MACRO_CONCAT(reporter_id_, __COUNTER__) \ - [[maybe_unused]] = snitch::tests.add_reporter(NAME) +# define SNITCH_REGISTER_REPORTER(NAME, TYPE) \ + static const std::string_view SNITCH_MACRO_CONCAT(reporter_id_, __COUNTER__) \ + [[maybe_unused]] = snitch::tests.add_reporter(NAME) +#else // SNITCH_ENABLE +# define SNITCH_REGISTER_REPORTER_CALLBACKS(NAME, ...) /* nothing */ +# define SNITCH_REGISTER_REPORTER(NAME, TYPE) static_assert(NAME) +#endif // SNITCH_ENABLE // clang-format off #if SNITCH_WITH_SHORTHAND_MACROS diff --git a/include/snitch/snitch_macros_test_case.hpp b/include/snitch/snitch_macros_test_case.hpp index 1fc42654..a0fbaec1 100644 --- a/include/snitch/snitch_macros_test_case.hpp +++ b/include/snitch/snitch_macros_test_case.hpp @@ -5,91 +5,121 @@ #include "snitch/snitch_macros_utility.hpp" #include "snitch/snitch_registry.hpp" -#define SNITCH_TEST_CASE_IMPL(ID, ...) \ - static void ID(); \ - static const char* SNITCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ - snitch::tests.add({__VA_ARGS__}, SNITCH_CURRENT_LOCATION, &ID); \ - void ID() - -#define SNITCH_TEST_CASE(...) \ - SNITCH_TEST_CASE_IMPL(SNITCH_MACRO_CONCAT(test_fun_, __COUNTER__), __VA_ARGS__) - -#define SNITCH_TEMPLATE_LIST_TEST_CASE_IMPL(ID, NAME, TAGS, TYPES) \ - template \ - static void ID(); \ - static const char* SNITCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ - snitch::tests.add_with_type_list( \ - {NAME, TAGS}, SNITCH_CURRENT_LOCATION, []() { ID(); }); \ - template \ - void ID() - -#define SNITCH_TEMPLATE_LIST_TEST_CASE(NAME, TAGS, TYPES) \ - SNITCH_TEMPLATE_LIST_TEST_CASE_IMPL( \ - SNITCH_MACRO_CONCAT(test_fun_, __COUNTER__), NAME, TAGS, TYPES) - -#define SNITCH_TEMPLATE_TEST_CASE_IMPL(ID, NAME, TAGS, ...) \ - template \ - static void ID(); \ - static const char* SNITCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ - snitch::tests.add_with_types<__VA_ARGS__>( \ - {NAME, TAGS}, SNITCH_CURRENT_LOCATION, []() { ID(); }); \ - template \ - void ID() - -#define SNITCH_TEMPLATE_TEST_CASE(NAME, TAGS, ...) \ - SNITCH_TEMPLATE_TEST_CASE_IMPL( \ - SNITCH_MACRO_CONCAT(test_fun_, __COUNTER__), NAME, TAGS, __VA_ARGS__) - -#define SNITCH_TEST_CASE_METHOD_IMPL(ID, FIXTURE, ...) \ - namespace { \ - struct ID : FIXTURE { \ - void test_fun(); \ - }; \ - } \ - static const char* SNITCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ - snitch::tests.add_fixture( \ - {#FIXTURE, __VA_ARGS__}, SNITCH_CURRENT_LOCATION, []() { ID{}.test_fun(); }); \ - void ID::test_fun() - -#define SNITCH_TEST_CASE_METHOD(FIXTURE, ...) \ - SNITCH_TEST_CASE_METHOD_IMPL( \ - SNITCH_MACRO_CONCAT(test_fixture_, __COUNTER__), FIXTURE, __VA_ARGS__) - -#define SNITCH_TEMPLATE_LIST_TEST_CASE_METHOD_IMPL(ID, FIXTURE, NAME, TAGS, TYPES) \ - namespace { \ - template \ - struct ID : FIXTURE { \ - void test_fun(); \ - }; \ - } \ - static const char* SNITCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ - snitch::tests.add_fixture_with_type_list( \ - {#FIXTURE, NAME, TAGS}, SNITCH_CURRENT_LOCATION, \ - []() < typename TestType > { ID{}.test_fun(); }); \ - template \ - void ID::test_fun() - -#define SNITCH_TEMPLATE_LIST_TEST_CASE_METHOD(FIXTURE, NAME, TAGS, TYPES) \ - SNITCH_TEMPLATE_LIST_TEST_CASE_METHOD_IMPL( \ - SNITCH_MACRO_CONCAT(test_fixture_, __COUNTER__), FIXTURE, NAME, TAGS, TYPES) - -#define SNITCH_TEMPLATE_TEST_CASE_METHOD_IMPL(ID, FIXTURE, NAME, TAGS, ...) \ - namespace { \ - template \ - struct ID : FIXTURE { \ - void test_fun(); \ - }; \ - } \ - static const char* SNITCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ - snitch::tests.add_fixture_with_types<__VA_ARGS__>( \ - {#FIXTURE, NAME, TAGS}, SNITCH_CURRENT_LOCATION, \ - []() < typename TestType > { ID{}.test_fun(); }); \ - template \ - void ID::test_fun() - -#define SNITCH_TEMPLATE_TEST_CASE_METHOD(FIXTURE, NAME, TAGS, ...) \ - SNITCH_TEMPLATE_TEST_CASE_METHOD_IMPL( \ - SNITCH_MACRO_CONCAT(test_fixture_, __COUNTER__), FIXTURE, NAME, TAGS, __VA_ARGS__) +#if SNITCH_ENABLE +# define SNITCH_TEST_CASE_IMPL(ID, ...) \ + static void ID(); \ + static const char* SNITCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ + snitch::tests.add({__VA_ARGS__}, SNITCH_CURRENT_LOCATION, &ID); \ + void ID() + +# define SNITCH_TEST_CASE(...) \ + SNITCH_TEST_CASE_IMPL(SNITCH_MACRO_CONCAT(test_fun_, __COUNTER__), __VA_ARGS__) + +# define SNITCH_TEMPLATE_LIST_TEST_CASE_IMPL(ID, NAME, TAGS, TYPES) \ + template \ + static void ID(); \ + static const char* SNITCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ + snitch::tests.add_with_type_list( \ + {NAME, TAGS}, SNITCH_CURRENT_LOCATION, \ + []() { ID(); }); \ + template \ + void ID() + +# define SNITCH_TEMPLATE_LIST_TEST_CASE(NAME, TAGS, TYPES) \ + SNITCH_TEMPLATE_LIST_TEST_CASE_IMPL( \ + SNITCH_MACRO_CONCAT(test_fun_, __COUNTER__), NAME, TAGS, TYPES) + +# define SNITCH_TEMPLATE_TEST_CASE_IMPL(ID, NAME, TAGS, ...) \ + template \ + static void ID(); \ + static const char* SNITCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ + snitch::tests.add_with_types<__VA_ARGS__>( \ + {NAME, TAGS}, SNITCH_CURRENT_LOCATION, \ + []() { ID(); }); \ + template \ + void ID() + +# define SNITCH_TEMPLATE_TEST_CASE(NAME, TAGS, ...) \ + SNITCH_TEMPLATE_TEST_CASE_IMPL( \ + SNITCH_MACRO_CONCAT(test_fun_, __COUNTER__), NAME, TAGS, __VA_ARGS__) + +# define SNITCH_TEST_CASE_METHOD_IMPL(ID, FIXTURE, ...) \ + namespace { \ + struct ID : FIXTURE { \ + void test_fun(); \ + }; \ + } \ + static const char* SNITCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ + snitch::tests.add_fixture( \ + {#FIXTURE, __VA_ARGS__}, SNITCH_CURRENT_LOCATION, []() { ID{}.test_fun(); }); \ + void ID::test_fun() + +# define SNITCH_TEST_CASE_METHOD(FIXTURE, ...) \ + SNITCH_TEST_CASE_METHOD_IMPL( \ + SNITCH_MACRO_CONCAT(test_fixture_, __COUNTER__), FIXTURE, __VA_ARGS__) + +# define SNITCH_TEMPLATE_LIST_TEST_CASE_METHOD_IMPL(ID, FIXTURE, NAME, TAGS, TYPES) \ + namespace { \ + template \ + struct ID : FIXTURE { \ + void test_fun(); \ + }; \ + } \ + static const char* SNITCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ + snitch::tests.add_fixture_with_type_list( \ + {#FIXTURE, NAME, TAGS}, SNITCH_CURRENT_LOCATION, \ + []() < typename TestType > { ID{}.test_fun(); }); \ + template \ + void ID::test_fun() + +# define SNITCH_TEMPLATE_LIST_TEST_CASE_METHOD(FIXTURE, NAME, TAGS, TYPES) \ + SNITCH_TEMPLATE_LIST_TEST_CASE_METHOD_IMPL( \ + SNITCH_MACRO_CONCAT(test_fixture_, __COUNTER__), FIXTURE, NAME, TAGS, TYPES) + +# define SNITCH_TEMPLATE_TEST_CASE_METHOD_IMPL(ID, FIXTURE, NAME, TAGS, ...) \ + namespace { \ + template \ + struct ID : FIXTURE { \ + void test_fun(); \ + }; \ + } \ + static const char* SNITCH_MACRO_CONCAT(test_id_, __COUNTER__) [[maybe_unused]] = \ + snitch::tests.add_fixture_with_types<__VA_ARGS__>( \ + {#FIXTURE, NAME, TAGS}, SNITCH_CURRENT_LOCATION, \ + []() < typename TestType > { ID{}.test_fun(); }); \ + template \ + void ID::test_fun() + +# define SNITCH_TEMPLATE_TEST_CASE_METHOD(FIXTURE, NAME, TAGS, ...) \ + SNITCH_TEMPLATE_TEST_CASE_METHOD_IMPL( \ + SNITCH_MACRO_CONCAT(test_fixture_, __COUNTER__), FIXTURE, NAME, TAGS, __VA_ARGS__) + +#else // SNITCH_ENABLE + +# define SNITCH_TEST_CASE(...) \ + [[maybe_unused]] static void SNITCH_MACRO_CONCAT(test_id_, __COUNTER__)() + +# define SNITCH_TEMPLATE_LIST_TEST_CASE(NAME, TAGS, TYPES) SNITCH_VOID_STATEMENT + +# define SNITCH_TEMPLATE_TEST_CASE(NAME, TAGS, ...) \ + template \ + [[maybe_unused]] static void SNITCH_MACRO_CONCAT(test_id_, __COUNTER__)() + +# define SNITCH_TEST_CASE_METHOD_IMPL(ID, FIXTURE, ...) \ + namespace { \ + struct ID : FIXTURE { \ + void test_fun(); \ + }; \ + } \ + [[maybe_unused]] void ID::test_fun() + +# define SNITCH_TEST_CASE_METHOD(FIXTURE, ...) \ + SNITCH_TEST_CASE_METHOD_IMPL(SNITCH_MACRO_CONCAT(test_id_, __COUNTER__), FIXTURE) + +# define SNITCH_TEMPLATE_LIST_TEST_CASE_METHOD(FIXTURE, NAME, TAGS, TYPES) SNITCH_VOID_STATEMENT + +# define SNITCH_TEMPLATE_TEST_CASE_METHOD(FIXTURE, NAME, TAGS, ...) SNITCH_VOID_STATEMENT +#endif // SNITCH_ENABLE // clang-format off #if SNITCH_WITH_SHORTHAND_MACROS diff --git a/include/snitch/snitch_macros_utility.hpp b/include/snitch/snitch_macros_utility.hpp index 038fd854..869a1652 100644 --- a/include/snitch/snitch_macros_utility.hpp +++ b/include/snitch/snitch_macros_utility.hpp @@ -2,11 +2,25 @@ #define SNITCH_MACROS_UTILITY_HPP #include "snitch/snitch_config.hpp" +#include "snitch/snitch_macros_warnings.hpp" #define SNITCH_CONCAT_IMPL(x, y) x##y #define SNITCH_MACRO_CONCAT(x, y) SNITCH_CONCAT_IMPL(x, y) #define SNITCH_CURRENT_LOCATION \ - snitch::source_location { std::string_view{__FILE__}, static_cast(__LINE__) } + snitch::source_location { \ + std::string_view{__FILE__}, static_cast(__LINE__) \ + } + +#define SNITCH_DISCARD_ARGS(...) \ + do { \ + SNITCH_WARNING_PUSH \ + SNITCH_WARNING_DISABLE_PARENTHESES \ + SNITCH_WARNING_DISABLE_CONSTANT_COMPARISON \ + static_cast(sizeof(__VA_ARGS__, 0)); \ + SNITCH_WARNING_POP \ + } while (0) + +#define SNITCH_VOID_STATEMENT static_cast(0) #endif diff --git a/include/snitch/snitch_main.hpp b/include/snitch/snitch_main.hpp new file mode 100644 index 00000000..4225ffe7 --- /dev/null +++ b/include/snitch/snitch_main.hpp @@ -0,0 +1,10 @@ +#ifndef SNITCH_MAIN_HPP +#define SNITCH_MAIN_HPP + +#include "snitch/snitch_config.hpp" + +namespace snitch { +SNITCH_EXPORT int main(int argc, char* argv[]); +} // namespace snitch + +#endif diff --git a/include/snitch/snitch_matcher.hpp b/include/snitch/snitch_matcher.hpp index 34631514..afeb3337 100644 --- a/include/snitch/snitch_matcher.hpp +++ b/include/snitch/snitch_matcher.hpp @@ -16,18 +16,16 @@ enum class match_status { failed, matched }; namespace snitch { template concept matcher_for = requires(const T& m, const U& value) { - { m.match(value) } -> convertible_to; - { - m.describe_match(value, matchers::match_status{}) - } -> convertible_to; - }; + { m.match(value) } -> convertible_to; + { m.describe_match(value, matchers::match_status{}) } -> convertible_to; +}; } // namespace snitch namespace snitch::impl { template concept exception_with_what = requires(const T& e) { - { e.what() } -> convertible_to; - }; + { e.what() } -> convertible_to; +}; template [[nodiscard]] constexpr auto match(T&& value, M&& matcher) noexcept { diff --git a/include/snitch/snitch_registry.hpp b/include/snitch/snitch_registry.hpp index 051f9da0..81b8c49a 100644 --- a/include/snitch/snitch_registry.hpp +++ b/include/snitch/snitch_registry.hpp @@ -37,6 +37,8 @@ constexpr std::size_t max_unique_tags = SNITCH_MAX_UNIQUE_TAGS; constexpr std::size_t max_registered_reporters = SNITCH_MAX_REGISTERED_REPORTERS; // Maximum size of a reporter instance, in bytes. constexpr std::size_t max_reporter_size_bytes = SNITCH_MAX_REPORTER_SIZE_BYTES; +// Is snitch disabled? +constexpr bool is_enabled = SNITCH_ENABLE; } // namespace snitch namespace snitch::impl { @@ -106,11 +108,11 @@ struct registered_reporter { }; template -concept reporter_type = - requires(registry& reg) { T{reg}; } && - requires(T& rep, registry& reg, std::string_view k, std::string_view v) { - { rep.configure(reg, k, v) } -> convertible_to; - } && requires(T& rep, const registry& reg, const event::data& e) { rep.report(reg, e); }; +concept reporter_type = requires(registry& reg) { + T{reg}; +} && requires(T& rep, registry& reg, std::string_view k, std::string_view v) { + { rep.configure(reg, k, v) } -> convertible_to; +} && requires(T& rep, const registry& reg, const event::data& e) { rep.report(reg, e); }; class registry { // Contains all registered test cases. diff --git a/meson.build b/meson.build index 4188a5e7..e3ff3fa3 100644 --- a/meson.build +++ b/meson.build @@ -78,14 +78,14 @@ sources = files('src/snitch_append.cpp', 'src/snitch_string_utility.cpp', 'src/snitch_test_data.cpp') -if get_option('unity_build') - - main = files('src/snitch.cpp') - +if get_option('enable') + if get_option('unity_build') + main = files('src/snitch.cpp') + else + main = sources + endif else - - main = sources - + main = files('src/snitch_main.cpp') endif make_snitch_all = files('make_snitch_all.py') @@ -95,7 +95,6 @@ subdir('snitch') install_headers(headers, subdir: 'snitch') if get_option('create_library') - snitch = library('snitch', conf_file, main, headers, include_directories: include_dirs, @@ -113,21 +112,20 @@ if get_option('create_library') description: 'Lightweight C++20 testing framework.', url: 'https://github.com/cschreib/snitch', ) - else - snitch_dep = declare_dependency(include_directories: include_dirs) - endif if meson.version().version_compare('>=0.54.0') meson.override_dependency('snitch', snitch_dep) endif -test('snitch_all_test', - executable('snitch_all_test', - [snitch_all, 'tests/testing.cpp'], - cpp_args: ['-DSNITCH_TEST_WITH_SNITCH', '-DSNITCH_TEST_HEADER_ONLY'], - dependencies: [snitch_dep] +if get_option('enable') + test('snitch_all_test', + executable('snitch_all_test', + [snitch_all, 'tests/testing.cpp'], + cpp_args: ['-DSNITCH_TEST_WITH_SNITCH', '-DSNITCH_TEST_HEADER_ONLY'], + dependencies: [snitch_dep] + ) ) -) +endif diff --git a/meson_options.txt b/meson_options.txt index 18aad8d0..28c91230 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,33 +1,34 @@ # Maximum lengths. -option('max_test_cases' ,type: 'integer' ,value: 5000, description: 'Maximum number of test cases in a test application.') -option('max_nested_sections' ,type: 'integer' ,value: 8 , description: 'Maximum depth of nested sections in a test case.') -option('max_expr_length' ,type: 'integer' ,value: 1024, description: 'Maximum length of a printed expression when reporting failure.') -option('max_message_length' ,type: 'integer' ,value: 1024, description: 'Maximum length of error or status messages.') -option('max_test_name_length' ,type: 'integer' ,value: 1024, description: 'Maximum length of a test case name.') -option('max_tag_length' ,type: 'integer' ,value: 256 , description: 'Maximum length of a test tag.') -option('max_captures' ,type: 'integer' ,value: 8 , description: 'Maximum number of captured expressions in a test case.') -option('max_capture_length' ,type: 'integer' ,value: 256 , description: 'Maximum length of a captured expression.') -option('max_unique_tags' ,type: 'integer' ,value: 1024, description: 'Maximum number of unique tags in a test application.') -option('max_command_line_args' ,type: 'integer' ,value: 1024, description: 'Maximum number of command line arguments to a test application.') -option('max_registered_reporters' ,type: 'integer' ,value: 8 , description: 'Maximum number of registered reporter that can be selected from the command line.') -option('max_path_length' ,type: 'integer' ,value: 1024, description: 'Maximum length of a file path when writing output to file.') -option('max_reporter_size_bytes' ,type: 'integer' ,value: 128, description: 'Maximum size (in bytes) of a reporter object.') +option('max_test_cases' , type: 'integer', value: 5000, description: 'Maximum number of test cases in a test application.') +option('max_nested_sections' , type: 'integer', value: 8 , description: 'Maximum depth of nested sections in a test case.') +option('max_expr_length' , type: 'integer', value: 1024, description: 'Maximum length of a printed expression when reporting failure.') +option('max_message_length' , type: 'integer', value: 1024, description: 'Maximum length of error or status messages.') +option('max_test_name_length' , type: 'integer', value: 1024, description: 'Maximum length of a test case name.') +option('max_tag_length' , type: 'integer', value: 256 , description: 'Maximum length of a test tag.') +option('max_captures' , type: 'integer', value: 8 , description: 'Maximum number of captured expressions in a test case.') +option('max_capture_length' , type: 'integer', value: 256 , description: 'Maximum length of a captured expression.') +option('max_unique_tags' , type: 'integer', value: 1024, description: 'Maximum number of unique tags in a test application.') +option('max_command_line_args' , type: 'integer', value: 1024, description: 'Maximum number of command line arguments to a test application.') +option('max_registered_reporters', type: 'integer', value: 8 , description: 'Maximum number of registered reporter that can be selected from the command line.') +option('max_path_length' , type: 'integer', value: 1024, description: 'Maximum length of a file path when writing output to file.') +option('max_reporter_size_bytes' , type: 'integer', value: 128, description: 'Maximum size (in bytes) of a reporter object.') # Feature toggles. -option('define_main' ,type: 'boolean' ,value: true, description: 'Define main() in snitch -- disable to provide your own main() function.') -option('with_exceptions' ,type: 'boolean' ,value: true, description: 'Use exceptions in snitch implementation -- will be forced OFF if exceptions are not available.') -option('with_multithreading' ,type: 'boolean', value: true, description: 'Make the testing framework thread-safe -- disable if multithreading is not needed.') -option('with_timings' ,type: 'boolean' ,value: true, description: 'Measure the time taken by each test case -- disable to speed up tests.') -option('with_shorthand_macros' ,type: 'boolean' ,value: true, description: 'Use short names for test macros -- disable if this causes conflicts.') -option('constexpr_float_use_bitcast' ,type: 'boolean' ,value: true, description: 'Use std::bit_cast if available to implement exact constexpr float-to-string conversion.') -option('snitch_append_to_chars' ,type: 'boolean' ,value: true, description: 'Use std::to_chars for string conversions -- disable for greater compatability with a slight performance cost.') -option('default_with_color' ,type: 'boolean' ,value: true, description: 'Enable terminal colors by default -- can also be controlled by command line interface.') -option('decompose_successful_assertions' ,type: 'boolean' ,value: true, description: 'Enable expression decomposition even for successful assertions -- more expensive.') -option('with_all_reporters' ,type: 'boolean' ,value: true, description: 'Allow all built-in reporters to be selected from the command line -- disable for faster compilation.') -option('with_teamcity_reporter' ,type: 'boolean' ,value: true, description: 'Allow the TeamCity reporter to be selected from the command line -- enable if needed.') -option('with_catch2_xml_reporter' ,type: 'boolean' ,value: true, description: 'Allow the Catch2 XML reporter to be selected from the command line -- enable if needed.') +option('enable' , type: 'boolean', value: true, description: 'Enable/disable snitch at build time.') +option('define_main' , type: 'boolean', value: true, description: 'Define main() in snitch -- disable to provide your own main() function.') +option('with_exceptions' , type: 'boolean', value: true, description: 'Use exceptions in snitch implementation -- will be forced OFF if exceptions are not available.') +option('with_multithreading' , type: 'boolean', value: true, description: 'Make the testing framework thread-safe -- disable if multithreading is not needed.') +option('with_timings' , type: 'boolean', value: true, description: 'Measure the time taken by each test case -- disable to speed up tests.') +option('with_shorthand_macros' , type: 'boolean', value: true, description: 'Use short names for test macros -- disable if this causes conflicts.') +option('constexpr_float_use_bitcast' , type: 'boolean', value: true, description: 'Use std::bit_cast if available to implement exact constexpr float-to-string conversion.') +option('snitch_append_to_chars' , type: 'boolean', value: true, description: 'Use std::to_chars for string conversions -- disable for greater compatability with a slight performance cost.') +option('default_with_color' , type: 'boolean', value: true, description: 'Enable terminal colors by default -- can also be controlled by command line interface.') +option('decompose_successful_assertions', type: 'boolean', value: true, description: 'Enable expression decomposition even for successful assertions -- more expensive.') +option('with_all_reporters' , type: 'boolean', value: true, description: 'Allow all built-in reporters to be selected from the command line -- disable for faster compilation.') +option('with_teamcity_reporter' , type: 'boolean', value: true, description: 'Allow the TeamCity reporter to be selected from the command line -- enable if needed.') +option('with_catch2_xml_reporter' , type: 'boolean', value: true, description: 'Allow the Catch2 XML reporter to be selected from the command line -- enable if needed.') # Building and packaging options; not part of the library API. -option('create_header_only' ,type: 'boolean' ,value: true, description: 'Create a single-header header-only version of snitch.') -option('create_library' ,type: 'boolean' ,value: true, description: 'Build a compiled library version of snitch.') -option('unity_build' ,type: 'boolean' ,value: true, description: 'Build sources as single file instead of separate files (faster full build).') +option('create_header_only' , type: 'boolean', value: true, description: 'Create a single-header header-only version of snitch.') +option('create_library' , type: 'boolean', value: true, description: 'Build a compiled library version of snitch.') +option('unity_build' , type: 'boolean', value: true, description: 'Build sources as single file instead of separate files (faster full build).') diff --git a/snitch/meson.build b/snitch/meson.build index 078b40bc..54a3848e 100644 --- a/snitch/meson.build +++ b/snitch/meson.build @@ -33,6 +33,7 @@ conf_data = configuration_data({ 'SNITCH_MAX_PATH_LENGTH' : get_option('max_path_length'), 'SNITCH_MAX_REPORTER_SIZE_BYTES' : get_option('max_reporter_size_bytes'), + 'SNITCH_ENABLE' : get_option('enable').to_int(), 'SNITCH_DEFINE_MAIN' : get_option('define_main').to_int(), 'SNITCH_WITH_EXCEPTIONS' : get_option('with_exceptions').to_int(), 'SNITCH_WITH_MULTITHREADING' : get_option('with_multithreading').to_int(), diff --git a/src/snitch_main.cpp b/src/snitch_main.cpp index 8b066c36..295bcde4 100644 --- a/src/snitch_main.cpp +++ b/src/snitch_main.cpp @@ -1,15 +1,25 @@ +#include "snitch/snitch_main.hpp" + #include "snitch/snitch_cli.hpp" #include "snitch/snitch_registry.hpp" -#if SNITCH_DEFINE_MAIN +namespace snitch { SNITCH_EXPORT int main(int argc, char* argv[]) { - std::optional args = snitch::cli::parse_arguments(argc, argv); - if (!args) { - return 1; + if constexpr (snitch::is_enabled) { + std::optional args = snitch::cli::parse_arguments(argc, argv); + if (!args) { + return 1; + } + snitch::tests.configure(*args); + return snitch::tests.run_tests(*args) ? 0 : 1; + } else { + return 0; } +} +} // namespace snitch - snitch::tests.configure(*args); - - return snitch::tests.run_tests(*args) ? 0 : 1; +#if SNITCH_DEFINE_MAIN +SNITCH_EXPORT int main(int argc, char* argv[]) { + return snitch::main(argc, argv); } #endif diff --git a/src/snitch_registry.cpp b/src/snitch_registry.cpp index 36a74562..b16f33fb 100644 --- a/src/snitch_registry.cpp +++ b/src/snitch_registry.cpp @@ -1132,5 +1132,7 @@ small_vector_span registry::reporters() const noexcep return registered_reporters; } +#if SNITCH_ENABLE constinit registry tests; +#endif // SNITCH_ENABLE } // namespace snitch diff --git a/src/snitch_reporter_catch2_xml.cpp b/src/snitch_reporter_catch2_xml.cpp index bcca9727..4b64fa46 100644 --- a/src/snitch_reporter_catch2_xml.cpp +++ b/src/snitch_reporter_catch2_xml.cpp @@ -243,7 +243,7 @@ void reporter::report(const registry& r, const snitch::event::data& event) noexc e.allowed_assertion_failure_count)}, {"failures", make_string(e.assertion_failure_count)}, {"expectedFailures", make_string(e.allowed_assertion_failure_count)}, - {"skipped", e.skipped?"true":"false"} + {"skipped", e.skipped ? "true" : "false"} # if SNITCH_WITH_TIMINGS , {"durationInSeconds", make_string(e.duration)} diff --git a/tests/testing.cpp b/tests/testing.cpp index b430bbb8..ca43c54f 100644 --- a/tests/testing.cpp +++ b/tests/testing.cpp @@ -8,9 +8,9 @@ #include "testing.hpp" #if defined(SNITCH_TEST_WITH_SNITCH) && !defined(SNITCH_TEST_HEADER_ONLY) -# undef SNITCH_EXPORT -# define SNITCH_EXPORT -# include "snitch_main.cpp" +int main(int argc, char* argv[]) { + return snitch::main(argc, argv); +} #endif bool contains_color_codes(std::string_view msg) noexcept { diff --git a/tests/testing.hpp b/tests/testing.hpp index dcb2f1fa..a5fb55dc 100644 --- a/tests/testing.hpp +++ b/tests/testing.hpp @@ -52,11 +52,11 @@ struct any_arg { template concept matcher = requires(const T& m) { - { m.match(any_arg{}) } -> snitch::convertible_to; - { - m.describe_match(any_arg{}, snitch::matchers::match_status{}) - } -> snitch::convertible_to; - }; + { m.match(any_arg{}) } -> snitch::convertible_to; + { + m.describe_match(any_arg{}, snitch::matchers::match_status{}) + } -> snitch::convertible_to; +}; template concept function = std::is_function_v;