diff --git a/docs/Readme.md b/docs/Readme.md index f4230506de..176f19e9d0 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -10,6 +10,7 @@ Once you're up and running consider the following reference material. * [Comparing floating point numbers](comparing-floating-point-numbers.md#top) * [Logging macros](logging.md#top) * [Test cases and sections](test-cases-and-sections.md#top) +* [Compile time testing](./compile-time-testing.md#top) * [Test fixtures](test-fixtures.md#top) * [Explicitly skipping, passing, and failing tests at runtime](skipping-passing-failing.md#top) * [Reporters (output customization)](reporters.md#top) diff --git a/docs/compile-time-testing.md b/docs/compile-time-testing.md new file mode 100644 index 0000000000..9d41ba2490 --- /dev/null +++ b/docs/compile-time-testing.md @@ -0,0 +1,153 @@ + + +# Compile-time testing + +Catch2 provides a way to test code during compilation. This is +useful for ensuring the code does not lead to undefined behavior. + +> [!IMPORTANT] +> This feature is only available with **C++17** + +## Why should I test code at compile-time ? + +Testing code during compilation is the only way for ensuring the code does +not lead to [undefined behavior](https://en.cppreference.com/w/cpp/language/ub.html). +This is critical to make your program safe, prevent unexpected crashes and worse +consequences of undefined behavior. + +## How ? + +Catch2 made it easy to test code at compile-time. + +The usage is pretty similar to testing at runtime: + +| Runtime macro | Compile time macro | +|-----------------|---------------------------| +| `SECTION` | `CONSTEXPR_SECTION` | +| `REQUIRE` | `CONSTEXPR_REQUIRE` | +| `REQUIRE_FALSE` | `CONSTEXPR_REQUIRE_FALSE` | +| `CHECK` | - | +| `CHECK_FALSE` | - | + +```c++ +TEST_CASE("My compile time test") +{ + CONSTEXPR_SECTION("std::array subscript and size") + { + std::array v = {1, 2, 3, 4, 5}; + CONSTEXPR_REQUIRE( v.size() == 5 ); + CONSTEXPR_REQUIRE( v[2] == 3 ); + + }; // <-- Don't forget the semicolon here! +} +``` + +All code inside the `CONSTEXPR_SECTION` will be evaluated during compilation. +If any of the `CONSTEXPR_REQUIRE` or `CONSTEXPR_REQUIRE_FALSE` fails, +it will cause a **compilation error**. + +> [!WARNING] +> You cannot use `REQUIRE` or `CHECK` inside a `CONSTEXPR_SECTION`. +> Be careful not to mistake `CONSTEXPR_REQUIRE` with `STATIC_REQUIRE`. +> They both concern compilation-time testing, but they do not have the same +> purpose. + +> [!WARNING] +> You cannot nest `CONSTEXPR_SECTION`s or put a `SECTION` inside a +> `CONSTEXPR_SECTION` + +> [!NOTE] +> The code inside the `CONSTEXPR_SECTION` is also evaluated at +> runtime. This way, it remains debuggable, and it contributes to the code +> coverage analysis. + +## What can I test ? + +You can test anything that can be evaluated in a `constexpr` function. +This will depend on your compiler and the C++ standard you are using. +C++20, C++23 and C++26 improved a lot the support for `constexpr`. + +Take a look at the C++ compiler support on [cppreference](https://en.cppreference.com/w/cpp/compiler_support.html) +to see what you can use. + +## Debug failing compile-time tests + +### Investigate from the compiler output + +You can check the output of your compiler to find the failing assertion. +The failing line should be highlighted somewhere. If you cannot see any +line: + +- Ensure the `CONSTEXPR_SECTION` runs only code that can be evaluated +at compile-time. This will depend on your compiler and the C++ standard you +are using. +- Ensure you did not use unsupported Catch2 macros inside the `CONSTEXPR_SECTION`. +The only supported macros are `CONSTEXPR_REQUIRE` and `CONSTEXPR_REQUIRE_FALSE`. +- Ensure the code you wrote doesn't produce undefined behavior (UB cannot +compile). Reading a range outside its bounds, dereferencing an invalid pointer, +reading a variable after it has been destroyed, are widespread undefined +behaviors. They will be all caught by these tests. + +### Investigate at runtime + +> [!TIP] +> If you want to debug the code in a `CONSTEXPR_SECTION`, you can simply replace +> the `CONSTEXPR_SECTION` with a `SECTION` and the code will be evaluated at runtime +> only instead. Remember to come back to the `CONSTEXPR_SECTION` once you are +> done ! + +## Compile time test report + +At runtime, a `CONSTEXPR_SECTION` will add a section in the test report. These sections +provide a way to see what was tested during compilation in the test report. + +For instance, given the following test case: + +```C++ +TEST_CASE("My other compile time test") +{ + SECTION("Any runtime section") + { + SECTION("Nested section") + { + CONSTEXPR_SECTION("First constexpr section") + { + // ... + }; + }; + + CONSTEXPR_SECTION("Second constexpr section") + { + // ... + }; + CONSTEXPR_SECTION("Third constexpr section") + { + // ... + }; + CONSTEXPR_SECTION("Fourth section") + { + // ... + }; + } + + SECTION("Another runtime section") + { + SECTION("Nested runtime section") + { + // ... + } + } +} +``` + +The report would look like this: + +- ✅ My other compile time test + - ✅ Any runtime section + - ✅ Nested section + - ✅ [Passed during compilation] First constexpr section + - ✅ [Passed during compilation] Second constexpr section + - ✅ [Passed during compilation] Third constexpr section + - ✅ [Passed during compilation] Fourth constexpr section + - ✅ Another runtime section + - ✅ Nested runtime section diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1e3af147a8..806fe4814d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -80,6 +80,8 @@ set(IMPL_HEADERS ${SOURCES_DIR}/internal/catch_config_wchar.hpp ${SOURCES_DIR}/internal/catch_console_colour.hpp ${SOURCES_DIR}/internal/catch_console_width.hpp + ${SOURCES_DIR}/internal/catch_constexpr_asserts.hpp + ${SOURCES_DIR}/internal/catch_constexpr_section.hpp ${SOURCES_DIR}/internal/catch_container_nonmembers.hpp ${SOURCES_DIR}/internal/catch_context.hpp ${SOURCES_DIR}/internal/catch_debug_console.hpp @@ -173,6 +175,7 @@ set(IMPL_SOURCES ${SOURCES_DIR}/internal/catch_clara.cpp ${SOURCES_DIR}/internal/catch_commandline.cpp ${SOURCES_DIR}/internal/catch_console_colour.cpp + ${SOURCES_DIR}/internal/catch_constexpr_section.cpp ${SOURCES_DIR}/internal/catch_context.cpp ${SOURCES_DIR}/internal/catch_debug_console.cpp ${SOURCES_DIR}/internal/catch_debugger.cpp diff --git a/src/catch2/catch_all.hpp b/src/catch2/catch_all.hpp index 2417d8567e..719ac27356 100644 --- a/src/catch2/catch_all.hpp +++ b/src/catch2/catch_all.hpp @@ -61,6 +61,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/src/catch2/catch_test_macros.hpp b/src/catch2/catch_test_macros.hpp index 97708557f9..f78f4fa2c1 100644 --- a/src/catch2/catch_test_macros.hpp +++ b/src/catch2/catch_test_macros.hpp @@ -8,15 +8,16 @@ #ifndef CATCH_TEST_MACROS_HPP_INCLUDED #define CATCH_TEST_MACROS_HPP_INCLUDED -#include #include #include +#include +#include #include +#include #include #include #include - // All of our user-facing macros support configuration toggle, that // forces them to be defined prefixed with CATCH_. We also like to // support another toggle that can minimize (disable) their implementation. @@ -48,6 +49,7 @@ #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) + #define CATCH_CONSTEXPR_SECTION( ... ) INTERNAL_CATCH_CONSTEXPR_SECTION( __VA_ARGS__ ) #define CATCH_FAIL( ... ) do { \ INTERNAL_CATCH_MSG("CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \ Catch::Detail::Unreachable(); \ @@ -72,6 +74,8 @@ #define CATCH_STATIC_CHECK_FALSE( ... ) CATCH_CHECK_FALSE( __VA_ARGS__ ) #endif + #define CATCH_CONSTEXPR_REQUIRE( ... ) INTERNAL_CATCH_CONSTEXPR_ASSERT( "CONSTEXPR_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define CATCH_CONSTEXPR_REQUIRE_FALSE( ... ) INTERNAL_CATCH_CONSTEXPR_ASSERT( "CONSTEXPR_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) // "BDD-style" convenience wrappers #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) @@ -109,6 +113,7 @@ #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) #define CATCH_SECTION( ... ) #define CATCH_DYNAMIC_SECTION( ... ) + #define CATCH_CONSTEXPR_SECTION( ... ) #define CATCH_FAIL( ... ) (void)(0) #define CATCH_FAIL_CHECK( ... ) (void)(0) #define CATCH_SUCCEED( ... ) (void)(0) @@ -119,6 +124,9 @@ #define CATCH_STATIC_CHECK( ... ) (void)(0) #define CATCH_STATIC_CHECK_FALSE( ... ) (void)(0) + #define CATCH_CONSTEXPR_REQUIRE( ... ) (void)(0) + #define CATCH_CONSTEXPR_REQUIRE_FALSE( ... ) (void)(0) + // "BDD-style" convenience wrappers #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ )) #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ), className ) @@ -155,6 +163,8 @@ #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) + #define CONSTEXPR_SECTION( ... ) INTERNAL_CATCH_CONSTEXPR_SECTION( __VA_ARGS__ ) + #define SILENT_CONSTEXPR_SECTION( ... ) INTERNAL_CATCH_SILENT_CONSTEXPR_SECTION( __VA_ARGS__ ) #define FAIL( ... ) do { \ INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ); \ Catch::Detail::Unreachable(); \ @@ -179,6 +189,9 @@ #define STATIC_CHECK_FALSE( ... ) CHECK_FALSE( __VA_ARGS__ ) #endif + #define CONSTEXPR_REQUIRE( ... ) INTERNAL_CATCH_CONSTEXPR_ASSERT( "CONSTEXPR_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) + #define CONSTEXPR_REQUIRE_FALSE( ... ) INTERNAL_CATCH_CONSTEXPR_ASSERT( "CONSTEXPR_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) + // "BDD-style" convenience wrappers #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) @@ -215,6 +228,7 @@ #define REGISTER_TEST_CASE( Function, ... ) (void)(0) #define SECTION( ... ) #define DYNAMIC_SECTION( ... ) + #define CONSTEXPR_SECTION( ... ) #define FAIL( ... ) (void)(0) #define FAIL_CHECK( ... ) (void)(0) #define SUCCEED( ... ) (void)(0) @@ -224,6 +238,8 @@ #define STATIC_REQUIRE_FALSE( ... ) (void)(0) #define STATIC_CHECK( ... ) (void)(0) #define STATIC_CHECK_FALSE( ... ) (void)(0) + #define CONSTEXPR_REQUIRE( ... ) (void)(0) + #define CONSTEXPR_REQUIRE_FALSE( ... ) (void)(0) // "BDD-style" convenience wrappers #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( CATCH2_INTERNAL_TEST_ ) ) diff --git a/src/catch2/internal/catch_constexpr_asserts.hpp b/src/catch2/internal/catch_constexpr_asserts.hpp new file mode 100644 index 0000000000..21c12317a8 --- /dev/null +++ b/src/catch2/internal/catch_constexpr_asserts.hpp @@ -0,0 +1,43 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 +#ifndef CATCH_CONSTEXPR_ASSERTS_HPP_INCLUDED +#define CATCH_CONSTEXPR_ASSERTS_HPP_INCLUDED +#include +#include + +namespace Catch { + template + void handleExpression( StringRef macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition, + ExpressionType decomposedExpression ) { + AssertionHandler catchAssertionHandler( + macroName, lineInfo, capturedExpression, resultDisposition ); + catchAssertionHandler.handleExpr( decomposedExpression ); + catchAssertionHandler.complete(); + } +} // namespace Catch + +#define INTERNAL_CATCH_CONSTEXPR_ASSERT( macroName, resultDisposition, ... ) \ + do { \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + const auto expr__InternalCatch__ = Catch::Decomposer() <= __VA_ARGS__; \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + if ( expr__InternalCatch__.getResult() != \ + Catch::isFalseTest( resultDisposition ) ) { \ + } else \ + Catch::handleExpression( macroName##_catch_sr, \ + CATCH_INTERNAL_LINEINFO, \ + CATCH_INTERNAL_STRINGIFY( __VA_ARGS__ ), \ + resultDisposition, \ + expr__InternalCatch__ ); \ + } while ( false ) + +#endif // CATCH_CONSTEXPR_ASSERTS_HPP_INCLUDED diff --git a/src/catch2/internal/catch_constexpr_section.cpp b/src/catch2/internal/catch_constexpr_section.cpp new file mode 100644 index 0000000000..2e5c46c4fb --- /dev/null +++ b/src/catch2/internal/catch_constexpr_section.cpp @@ -0,0 +1,23 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 + +#include +#include + +namespace Catch { + void ConstexprSection::addFakeAssertion() { + AssertionHandler catchAssertionHandler( + "CONSTEXPR_SECTION", + SourceLineInfo( "unknown-file", 0 ), + "[Passed during compilation]", + ResultDisposition::Normal ); + catchAssertionHandler.handleMessage( ResultWas::Ok, + "[Passed during compilation]" ); + catchAssertionHandler.complete(); + } +} // namespace Catch \ No newline at end of file diff --git a/src/catch2/internal/catch_constexpr_section.hpp b/src/catch2/internal/catch_constexpr_section.hpp new file mode 100644 index 0000000000..9205591324 --- /dev/null +++ b/src/catch2/internal/catch_constexpr_section.hpp @@ -0,0 +1,49 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 +#ifndef CATCH_CONSTEXPR_SECTION_HPP_INCLUDED +#define CATCH_CONSTEXPR_SECTION_HPP_INCLUDED + +#if defined( CATCH_CPP17_OR_GREATER ) && __cpp_constexpr >= 201603 +# define CATCH_CONFIG_CONSTEXPR_SECTIONS +#endif + +#include +#include +#include + +namespace Catch { + + struct ConstexprSection { + template + ConstexprSection( Callable callable ) { + static_assert( ( callable(), true ), "CONSTEXPR_SECTION failure" ); + addFakeAssertion(); + callable(); + } + + // Add a fake assertion to the section to avoid failures because the + // section is empty + static void addFakeAssertion(); + }; +} // namespace Catch + +#ifdef CATCH_CONFIG_CONSTEXPR_SECTIONS + +# define INTERNAL_CATCH_CONSTEXPR_SECTION( ... ) \ + INTERNAL_CATCH_SECTION( "[Passed during compilation] " __VA_ARGS__ ) \ + [[maybe_unused]] const ::Catch::ConstexprSection \ + INTERNAL_CATCH_UNIQUE_NAME( \ + catch_internal_CompileTimeSection ) = [&]() + +#else +# define INTERNAL_CATCH_CONSTEXPR_SECTION( ... ) \ + static_assert( false, "C++17 is required for CONSTEXPR_SECTION" ); \ + if ( false ) +#endif + +#endif // CATCH_CONSTEXPR_SECTION_HPP_INCLUDED diff --git a/src/catch2/internal/catch_decomposer.hpp b/src/catch2/internal/catch_decomposer.hpp index fcc017dda9..1feba6cc80 100644 --- a/src/catch2/internal/catch_decomposer.hpp +++ b/src/catch2/internal/catch_decomposer.hpp @@ -436,6 +436,10 @@ namespace Catch { constexpr auto makeUnaryExpr() const -> UnaryExpr { return UnaryExpr{ m_lhs }; } + + constexpr auto getResult() const -> bool { + return makeUnaryExpr().getResult(); + } }; struct Decomposer { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8f8a3755ae..cfc748ef20 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -105,6 +105,7 @@ set(TEST_SOURCES ${SELF_TEST_DIR}/UsageTests/Benchmark.tests.cpp ${SELF_TEST_DIR}/UsageTests/Class.tests.cpp ${SELF_TEST_DIR}/UsageTests/Compilation.tests.cpp + ${SELF_TEST_DIR}/UsageTests/CompileTimeTests.tests.cpp ${SELF_TEST_DIR}/UsageTests/Condition.tests.cpp ${SELF_TEST_DIR}/UsageTests/Decomposition.tests.cpp ${SELF_TEST_DIR}/UsageTests/EnumToString.tests.cpp diff --git a/tests/SelfTest/Baselines/automake.sw.approved.txt b/tests/SelfTest/Baselines/automake.sw.approved.txt index 4a6886d6c2..7e4a9ccce2 100644 --- a/tests/SelfTest/Baselines/automake.sw.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.approved.txt @@ -104,6 +104,9 @@ Nor would this :test-result: PASS CAPTURE can deal with complex expressions :test-result: PASS CAPTURE can deal with complex expressions involving commas :test-result: PASS CAPTURE parses string and character constants +:test-result: XFAIL CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure +:test-result: PASS CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success +:test-result: PASS CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during compilation :test-result: PASS Capture and info messages :test-result: FAIL Captures do not leave block with an exception :test-result: FAIL Captures outlive section end @@ -241,6 +244,7 @@ A string sent directly to stdout A string sent directly to stderr A string sent to stderr via clog :test-result: FAIL Sends stuff to stdout and stderr +:test-result: PASS Simple compile time section :test-result: PASS Some simple comparisons between doubles Message from section one Message from section two diff --git a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt index b0d30b87d9..6b31be73fd 100644 --- a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt @@ -102,6 +102,9 @@ :test-result: PASS CAPTURE can deal with complex expressions :test-result: PASS CAPTURE can deal with complex expressions involving commas :test-result: PASS CAPTURE parses string and character constants +:test-result: XFAIL CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure +:test-result: PASS CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success +:test-result: PASS CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during compilation :test-result: PASS Capture and info messages :test-result: FAIL Captures do not leave block with an exception :test-result: FAIL Captures outlive section end @@ -236,6 +239,7 @@ :test-result: FAIL Scoped messages do not leave block with an exception :test-result: FAIL Scoped messages outlive section end :test-result: FAIL Sends stuff to stdout and stderr +:test-result: PASS Simple compile time section :test-result: PASS Some simple comparisons between doubles :test-result: FAIL Standard output from all sections is reported :test-result: FAIL StartsWith string matcher diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index cacb898afb..7922121661 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -368,6 +368,18 @@ MatchersRanges.tests.cpp:: passed: unrelated::ADL_empty{}, IsEmpty( Message.tests.cpp:: passed: with 7 messages: 'a := 1' and 'b := 2' and 'c := 3' and 'a + b := 3' and 'a+b := 3' and 'c > b := true' and 'a == 1 := true' Message.tests.cpp:: passed: with 7 messages: 'custom_index_op{1, 2, 3}[0, 1, 2] := 0' and 'custom_index_op{1, 2, 3}[(0, 1)] := 0' and 'custom_index_op{1, 2, 3}[0] := 0' and '(helper_1436{12, -12}) := { 12, -12 }' and '(helper_1436(-12, 12)) := { -12, 12 }' and '(1, 2) := 2' and '(2, 3) := 3' Message.tests.cpp:: passed: with 11 messages: '("comma, in string", "escaped, \", ") := "escaped, ", "' and '"single quote in string,'," := "single quote in string,',"' and '"some escapes, \\,\\\\" := "some escapes, \,\\"' and '"some, ), unmatched, } prenheses {[<" := "some, ), unmatched, } prenheses {[<"' and ''"' := '"'' and ''\'' := '''' and '',' := ','' and ''}' := '}'' and '')' := ')'' and ''(' := '('' and ''{' := '{'' +CompileTimeTests.tests.cpp:: passed: numberOfCalls < 2 for: 1 < 2 +CompileTimeTests.tests.cpp:: failed: ( lambda() != 50 ) for: false +CompileTimeTests.tests.cpp:: passed: numberOfCalls < 2 for: 1 < 2 +CompileTimeTests.tests.cpp:: failed: lambda() != 50 for: 50 != 50 +CompileTimeTests.tests.cpp:: passed: with 1 message: 'Silent empty section warning' +CompileTimeTests.tests.cpp:: passed: with 1 message: 'Silent empty section warning (at runtime, CONSTEXPR_REQUIRE does nothing if passed)' +CompileTimeTests.tests.cpp:: passed: with 1 message: 'Silent empty section warning' +CompileTimeTests.tests.cpp:: passed: with 1 message: 'Silent empty section warning (at runtime, CONSTEXPR_REQUIRE does nothing if passed)' +CompileTimeTests.tests.cpp:: passed: with 1 message: 'Silent empty section warning' +unknown-file:0: passed: [Passed during compilation] with 1 message: '[Passed during compilation]' +unknown-file:0: passed: [Passed during compilation] with 1 message: '[Passed during compilation]' +unknown-file:0: passed: [Passed during compilation] with 1 message: '[Passed during compilation]' ToStringGeneral.tests.cpp:: passed: true with 1 message: 'i := 2' ToStringGeneral.tests.cpp:: passed: true with 1 message: '3' Message.tests.cpp:: failed: false with 1 message: 'a := 1' @@ -1766,6 +1778,7 @@ Message.tests.cpp:: failed: false with 1 message: 'Should survive a A string sent directly to stdout A string sent directly to stderr A string sent to stderr via clog +unknown-file:0: passed: [Passed during compilation] with 1 message: '[Passed during compilation]' Approx.tests.cpp:: passed: d == Approx( 1.23 ) for: 1.22999999999999998 == Approx( 1.22999999999999998 ) @@ -2888,7 +2901,7 @@ InternalBenchmark.tests.cpp:: passed: med == 18. for: 18.0 == 18.0 InternalBenchmark.tests.cpp:: passed: q3 == 23. for: 23.0 == 23.0 Misc.tests.cpp:: passed: Misc.tests.cpp:: passed: -test cases: 435 | 317 passed | 95 failed | 6 skipped | 17 failed as expected -assertions: 2303 | 2105 passed | 157 failed | 41 failed as expected +test cases: 439 | 320 passed | 95 failed | 6 skipped | 18 failed as expected +assertions: 2316 | 2116 passed | 157 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt index 10395c9adf..f3821e1dbe 100644 --- a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt @@ -366,6 +366,18 @@ MatchersRanges.tests.cpp:: passed: unrelated::ADL_empty{}, IsEmpty( Message.tests.cpp:: passed: with 7 messages: 'a := 1' and 'b := 2' and 'c := 3' and 'a + b := 3' and 'a+b := 3' and 'c > b := true' and 'a == 1 := true' Message.tests.cpp:: passed: with 7 messages: 'custom_index_op{1, 2, 3}[0, 1, 2] := 0' and 'custom_index_op{1, 2, 3}[(0, 1)] := 0' and 'custom_index_op{1, 2, 3}[0] := 0' and '(helper_1436{12, -12}) := { 12, -12 }' and '(helper_1436(-12, 12)) := { -12, 12 }' and '(1, 2) := 2' and '(2, 3) := 3' Message.tests.cpp:: passed: with 11 messages: '("comma, in string", "escaped, \", ") := "escaped, ", "' and '"single quote in string,'," := "single quote in string,',"' and '"some escapes, \\,\\\\" := "some escapes, \,\\"' and '"some, ), unmatched, } prenheses {[<" := "some, ), unmatched, } prenheses {[<"' and ''"' := '"'' and ''\'' := '''' and '',' := ','' and ''}' := '}'' and '')' := ')'' and ''(' := '('' and ''{' := '{'' +CompileTimeTests.tests.cpp:: passed: numberOfCalls < 2 for: 1 < 2 +CompileTimeTests.tests.cpp:: failed: ( lambda() != 50 ) for: false +CompileTimeTests.tests.cpp:: passed: numberOfCalls < 2 for: 1 < 2 +CompileTimeTests.tests.cpp:: failed: lambda() != 50 for: 50 != 50 +CompileTimeTests.tests.cpp:: passed: with 1 message: 'Silent empty section warning' +CompileTimeTests.tests.cpp:: passed: with 1 message: 'Silent empty section warning (at runtime, CONSTEXPR_REQUIRE does nothing if passed)' +CompileTimeTests.tests.cpp:: passed: with 1 message: 'Silent empty section warning' +CompileTimeTests.tests.cpp:: passed: with 1 message: 'Silent empty section warning (at runtime, CONSTEXPR_REQUIRE does nothing if passed)' +CompileTimeTests.tests.cpp:: passed: with 1 message: 'Silent empty section warning' +unknown-file:0: passed: [Passed during compilation] with 1 message: '[Passed during compilation]' +unknown-file:0: passed: [Passed during compilation] with 1 message: '[Passed during compilation]' +unknown-file:0: passed: [Passed during compilation] with 1 message: '[Passed during compilation]' ToStringGeneral.tests.cpp:: passed: true with 1 message: 'i := 2' ToStringGeneral.tests.cpp:: passed: true with 1 message: '3' Message.tests.cpp:: failed: false with 1 message: 'a := 1' @@ -1761,6 +1773,7 @@ Message.tests.cpp:: failed: false with 1 message: 'This will be rep Message.tests.cpp:: failed: false with 1 message: 'Should be in scope at the end' Message.tests.cpp:: passed: true with 1 message: 'Should survive a section end' Message.tests.cpp:: failed: false with 1 message: 'Should survive a section end' +unknown-file:0: passed: [Passed during compilation] with 1 message: '[Passed during compilation]' Approx.tests.cpp:: passed: d == Approx( 1.23 ) for: 1.22999999999999998 == Approx( 1.22999999999999998 ) @@ -2877,7 +2890,7 @@ InternalBenchmark.tests.cpp:: passed: med == 18. for: 18.0 == 18.0 InternalBenchmark.tests.cpp:: passed: q3 == 23. for: 23.0 == 23.0 Misc.tests.cpp:: passed: Misc.tests.cpp:: passed: -test cases: 435 | 317 passed | 95 failed | 6 skipped | 17 failed as expected -assertions: 2303 | 2105 passed | 157 failed | 41 failed as expected +test cases: 439 | 320 passed | 95 failed | 6 skipped | 18 failed as expected +assertions: 2316 | 2116 passed | 157 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt index c1512db5c9..f9e59e7f42 100644 --- a/tests/SelfTest/Baselines/console.std.approved.txt +++ b/tests/SelfTest/Baselines/console.std.approved.txt @@ -379,6 +379,32 @@ AssertionHandler.tests.cpp:: FAILED: due to unexpected exception with message: { nested assertion failed } +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of failure + Unary -> Expression should be evaluated only once +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: FAILED: + CONSTEXPR_REQUIRE( ( lambda() != 50 ) ) +with expansion: + false + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of failure + Binary -> Expression should be evaluated only once +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: FAILED: + CONSTEXPR_REQUIRE( lambda() != 50 ) +with expansion: + 50 != 50 + ------------------------------------------------------------------------------- Captures do not leave block with an exception ------------------------------------------------------------------------------- @@ -1719,6 +1745,6 @@ due to unexpected exception with message: Why would you throw a std::string? =============================================================================== -test cases: 435 | 335 passed | 76 failed | 7 skipped | 17 failed as expected -assertions: 2282 | 2105 passed | 136 failed | 41 failed as expected +test cases: 439 | 338 passed | 76 failed | 7 skipped | 18 failed as expected +assertions: 2295 | 2116 passed | 136 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index 7fd5951481..d6e6099f26 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -2893,6 +2893,140 @@ with messages: '(' := '(' '{' := '{' +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of failure + Unary -> Expression should be evaluated only once +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: + REQUIRE( numberOfCalls < 2 ) +with expansion: + 1 < 2 + +CompileTimeTests.tests.cpp:: FAILED: + CONSTEXPR_REQUIRE( ( lambda() != 50 ) ) +with expansion: + false + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of failure + Binary -> Expression should be evaluated only once +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: + REQUIRE( numberOfCalls < 2 ) +with expansion: + 1 < 2 + +CompileTimeTests.tests.cpp:: FAILED: + CONSTEXPR_REQUIRE( lambda() != 50 ) +with expansion: + 50 != 50 + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of failure +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: +with message: + Silent empty section warning + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of success + Unary -> Expression should be evaluated only once +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: +with message: + Silent empty section warning (at runtime, CONSTEXPR_REQUIRE does nothing if + passed) + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of success +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: +with message: + Silent empty section warning + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of success + Binary -> Expression should be evaluated only once +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: +with message: + Silent empty section warning (at runtime, CONSTEXPR_REQUIRE does nothing if + passed) + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of success +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: +with message: + Silent empty section warning + +------------------------------------------------------------------------------- +CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during +compilation + [Passed during compilation] First +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +unknown-file:0: PASSED: + CONSTEXPR_SECTION( [Passed during compilation] ) +with message: + [Passed during compilation] + +------------------------------------------------------------------------------- +CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during +compilation + [Passed during compilation] Second +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +unknown-file:0: PASSED: + CONSTEXPR_SECTION( [Passed during compilation] ) +with message: + [Passed during compilation] + +------------------------------------------------------------------------------- +CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during +compilation + [Passed during compilation] Third +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +unknown-file:0: PASSED: + CONSTEXPR_SECTION( [Passed during compilation] ) +with message: + [Passed during compilation] + ------------------------------------------------------------------------------- Capture and info messages Capture should stringify like assertions @@ -11269,6 +11403,18 @@ Misc.tests.cpp: No assertions in test case 'Sends stuff to stdout and stderr' +------------------------------------------------------------------------------- +Simple compile time section + [Passed during compilation] Simple compile time section +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +unknown-file:0: PASSED: + CONSTEXPR_SECTION( [Passed during compilation] ) +with message: + [Passed during compilation] + ------------------------------------------------------------------------------- Some simple comparisons between doubles ------------------------------------------------------------------------------- @@ -19295,6 +19441,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 435 | 317 passed | 95 failed | 6 skipped | 17 failed as expected -assertions: 2303 | 2105 passed | 157 failed | 41 failed as expected +test cases: 439 | 320 passed | 95 failed | 6 skipped | 18 failed as expected +assertions: 2316 | 2116 passed | 157 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.multi.approved.txt b/tests/SelfTest/Baselines/console.sw.multi.approved.txt index 08ab1b2bef..1d506c8825 100644 --- a/tests/SelfTest/Baselines/console.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.multi.approved.txt @@ -2891,6 +2891,140 @@ with messages: '(' := '(' '{' := '{' +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of failure + Unary -> Expression should be evaluated only once +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: + REQUIRE( numberOfCalls < 2 ) +with expansion: + 1 < 2 + +CompileTimeTests.tests.cpp:: FAILED: + CONSTEXPR_REQUIRE( ( lambda() != 50 ) ) +with expansion: + false + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of failure + Binary -> Expression should be evaluated only once +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: + REQUIRE( numberOfCalls < 2 ) +with expansion: + 1 < 2 + +CompileTimeTests.tests.cpp:: FAILED: + CONSTEXPR_REQUIRE( lambda() != 50 ) +with expansion: + 50 != 50 + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of failure +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: +with message: + Silent empty section warning + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of success + Unary -> Expression should be evaluated only once +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: +with message: + Silent empty section warning (at runtime, CONSTEXPR_REQUIRE does nothing if + passed) + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of success +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: +with message: + Silent empty section warning + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of success + Binary -> Expression should be evaluated only once +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: +with message: + Silent empty section warning (at runtime, CONSTEXPR_REQUIRE does nothing if + passed) + +------------------------------------------------------------------------------- +CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only +once at runtime in case of success +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +CompileTimeTests.tests.cpp:: PASSED: +with message: + Silent empty section warning + +------------------------------------------------------------------------------- +CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during +compilation + [Passed during compilation] First +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +unknown-file:0: PASSED: + CONSTEXPR_SECTION( [Passed during compilation] ) +with message: + [Passed during compilation] + +------------------------------------------------------------------------------- +CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during +compilation + [Passed during compilation] Second +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +unknown-file:0: PASSED: + CONSTEXPR_SECTION( [Passed during compilation] ) +with message: + [Passed during compilation] + +------------------------------------------------------------------------------- +CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during +compilation + [Passed during compilation] Third +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +unknown-file:0: PASSED: + CONSTEXPR_SECTION( [Passed during compilation] ) +with message: + [Passed during compilation] + ------------------------------------------------------------------------------- Capture and info messages Capture should stringify like assertions @@ -11264,6 +11398,18 @@ Misc.tests.cpp: No assertions in test case 'Sends stuff to stdout and stderr' +------------------------------------------------------------------------------- +Simple compile time section + [Passed during compilation] Simple compile time section +------------------------------------------------------------------------------- +CompileTimeTests.tests.cpp: +............................................................................... + +unknown-file:0: PASSED: + CONSTEXPR_SECTION( [Passed during compilation] ) +with message: + [Passed during compilation] + ------------------------------------------------------------------------------- Some simple comparisons between doubles ------------------------------------------------------------------------------- @@ -19284,6 +19430,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 435 | 317 passed | 95 failed | 6 skipped | 17 failed as expected -assertions: 2303 | 2105 passed | 157 failed | 41 failed as expected +test cases: 439 | 320 passed | 95 failed | 6 skipped | 18 failed as expected +assertions: 2316 | 2116 passed | 157 failed | 43 failed as expected diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index c12b61787b..a06296e659 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -441,6 +441,34 @@ at AssertionHandler.tests.cpp: + + + + +FAILED: + CONSTEXPR_REQUIRE( ( lambda() != 50 ) ) +with expansion: + false +at CompileTimeTests.tests.cpp: + + + + + +FAILED: + CONSTEXPR_REQUIRE( lambda() != 50 ) +with expansion: + 50 != 50 +at CompileTimeTests.tests.cpp: + + + + + + + + + @@ -1456,6 +1484,8 @@ A string sent directly to stderr A string sent to stderr via clog + + diff --git a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt index e844ca6cb0..f339599554 100644 --- a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt @@ -1,6 +1,6 @@ - + @@ -440,6 +440,34 @@ at AssertionHandler.tests.cpp: + + + + +FAILED: + CONSTEXPR_REQUIRE( ( lambda() != 50 ) ) +with expansion: + false +at CompileTimeTests.tests.cpp: + + + + + +FAILED: + CONSTEXPR_REQUIRE( lambda() != 50 ) +with expansion: + 50 != 50 +at CompileTimeTests.tests.cpp: + + + + + + + + + @@ -1455,6 +1483,8 @@ A string sent directly to stderr A string sent to stderr via clog + + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index d79abd3748..2f64b4ec85 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -665,6 +665,36 @@ at Class.tests.cpp: + + + + +FAILED: + CONSTEXPR_REQUIRE( ( lambda() != 50 ) ) +with expansion: + false +at CompileTimeTests.tests.cpp: + + + + +FAILED: + CONSTEXPR_REQUIRE( lambda() != 50 ) +with expansion: + 50 != 50 +at CompileTimeTests.tests.cpp: + + + + + + + + + + + + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt index 98a06c1491..63351d6c54 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt @@ -664,6 +664,36 @@ at Class.tests.cpp: + + + + +FAILED: + CONSTEXPR_REQUIRE( ( lambda() != 50 ) ) +with expansion: + false +at CompileTimeTests.tests.cpp: + + + + +FAILED: + CONSTEXPR_REQUIRE( lambda() != 50 ) +with expansion: + 50 != 50 +at CompileTimeTests.tests.cpp: + + + + + + + + + + + + diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index 3e5d18321a..6f85b6508a 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -684,6 +684,30 @@ ok {test-number} - with 7 messages: 'a := 1' and 'b := 2' and 'c := 3' and 'a + ok {test-number} - with 7 messages: 'custom_index_op{1, 2, 3}[0, 1, 2] := 0' and 'custom_index_op{1, 2, 3}[(0, 1)] := 0' and 'custom_index_op{1, 2, 3}[0] := 0' and '(helper_1436{12, -12}) := { 12, -12 }' and '(helper_1436(-12, 12)) := { -12, 12 }' and '(1, 2) := 2' and '(2, 3) := 3' # CAPTURE parses string and character constants ok {test-number} - with 11 messages: '("comma, in string", "escaped, \", ") := "escaped, ", "' and '"single quote in string,'," := "single quote in string,',"' and '"some escapes, \\,\\\\" := "some escapes, \,\\"' and '"some, ), unmatched, } prenheses {[<" := "some, ), unmatched, } prenheses {[<"' and ''"' := '"'' and ''\'' := '''' and '',' := ','' and ''}' := '}'' and '')' := ')'' and ''(' := '('' and ''{' := '{'' +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure +ok {test-number} - numberOfCalls < 2 for: 1 < 2 +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure +not ok {test-number} - ( lambda() != 50 ) for: false +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure +ok {test-number} - numberOfCalls < 2 for: 1 < 2 +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure +not ok {test-number} - lambda() != 50 for: 50 != 50 +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure +ok {test-number} - with 1 message: 'Silent empty section warning' +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success +ok {test-number} - with 1 message: 'Silent empty section warning (at runtime, CONSTEXPR_REQUIRE does nothing if passed)' +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success +ok {test-number} - with 1 message: 'Silent empty section warning' +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success +ok {test-number} - with 1 message: 'Silent empty section warning (at runtime, CONSTEXPR_REQUIRE does nothing if passed)' +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success +ok {test-number} - with 1 message: 'Silent empty section warning' +# CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during compilation +ok {test-number} - [Passed during compilation] with 1 message: '[Passed during compilation]' +# CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during compilation +ok {test-number} - [Passed during compilation] with 1 message: '[Passed during compilation]' +# CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during compilation +ok {test-number} - [Passed during compilation] with 1 message: '[Passed during compilation]' # Capture and info messages ok {test-number} - true with 1 message: 'i := 2' # Capture and info messages @@ -2677,6 +2701,8 @@ not ok {test-number} - false with 1 message: 'Should survive a section end' A string sent directly to stdout A string sent directly to stderr A string sent to stderr via clog +# Simple compile time section +ok {test-number} - [Passed during compilation] with 1 message: '[Passed during compilation]' # Some simple comparisons between doubles ok {test-number} - d == Approx( 1.23 ) for: 1.22999999999999998 == Approx( 1.22999999999999998 ) # Some simple comparisons between doubles @@ -4627,5 +4653,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2315 +1..2328 diff --git a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt index 0fdb266a2a..e0cf579c7d 100644 --- a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt @@ -682,6 +682,30 @@ ok {test-number} - with 7 messages: 'a := 1' and 'b := 2' and 'c := 3' and 'a + ok {test-number} - with 7 messages: 'custom_index_op{1, 2, 3}[0, 1, 2] := 0' and 'custom_index_op{1, 2, 3}[(0, 1)] := 0' and 'custom_index_op{1, 2, 3}[0] := 0' and '(helper_1436{12, -12}) := { 12, -12 }' and '(helper_1436(-12, 12)) := { -12, 12 }' and '(1, 2) := 2' and '(2, 3) := 3' # CAPTURE parses string and character constants ok {test-number} - with 11 messages: '("comma, in string", "escaped, \", ") := "escaped, ", "' and '"single quote in string,'," := "single quote in string,',"' and '"some escapes, \\,\\\\" := "some escapes, \,\\"' and '"some, ), unmatched, } prenheses {[<" := "some, ), unmatched, } prenheses {[<"' and ''"' := '"'' and ''\'' := '''' and '',' := ','' and ''}' := '}'' and '')' := ')'' and ''(' := '('' and ''{' := '{'' +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure +ok {test-number} - numberOfCalls < 2 for: 1 < 2 +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure +not ok {test-number} - ( lambda() != 50 ) for: false +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure +ok {test-number} - numberOfCalls < 2 for: 1 < 2 +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure +not ok {test-number} - lambda() != 50 for: 50 != 50 +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure +ok {test-number} - with 1 message: 'Silent empty section warning' +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success +ok {test-number} - with 1 message: 'Silent empty section warning (at runtime, CONSTEXPR_REQUIRE does nothing if passed)' +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success +ok {test-number} - with 1 message: 'Silent empty section warning' +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success +ok {test-number} - with 1 message: 'Silent empty section warning (at runtime, CONSTEXPR_REQUIRE does nothing if passed)' +# CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success +ok {test-number} - with 1 message: 'Silent empty section warning' +# CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during compilation +ok {test-number} - [Passed during compilation] with 1 message: '[Passed during compilation]' +# CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during compilation +ok {test-number} - [Passed during compilation] with 1 message: '[Passed during compilation]' +# CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during compilation +ok {test-number} - [Passed during compilation] with 1 message: '[Passed during compilation]' # Capture and info messages ok {test-number} - true with 1 message: 'i := 2' # Capture and info messages @@ -2672,6 +2696,8 @@ not ok {test-number} - false with 1 message: 'Should be in scope at the end' ok {test-number} - true with 1 message: 'Should survive a section end' # Scoped messages outlive section end not ok {test-number} - false with 1 message: 'Should survive a section end' +# Simple compile time section +ok {test-number} - [Passed during compilation] with 1 message: '[Passed during compilation]' # Some simple comparisons between doubles ok {test-number} - d == Approx( 1.23 ) for: 1.22999999999999998 == Approx( 1.22999999999999998 ) # Some simple comparisons between doubles @@ -4616,5 +4642,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2315 +1..2328 diff --git a/tests/SelfTest/Baselines/teamcity.sw.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.approved.txt index 853f3d8048..d9e467f79e 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.approved.txt @@ -247,6 +247,14 @@ ##teamcity[testFinished name='CAPTURE can deal with complex expressions involving commas' duration="{duration}"] ##teamcity[testStarted name='CAPTURE parses string and character constants'] ##teamcity[testFinished name='CAPTURE parses string and character constants' duration="{duration}"] +##teamcity[testStarted name='CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure'] +##teamcity[testIgnored name='CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure' message='-------------------------------------------------------------------------------|nUnary -> Expression should be evaluated only once|n-------------------------------------------------------------------------------|nCompileTimeTests.tests.cpp:|n...............................................................................|n|nCompileTimeTests.tests.cpp:|nexpression failed|n CONSTEXPR_REQUIRE( ( lambda() != 50 ) )|nwith expansion:|n false|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testIgnored name='CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure' message='-------------------------------------------------------------------------------|nBinary -> Expression should be evaluated only once|n-------------------------------------------------------------------------------|nCompileTimeTests.tests.cpp:|n...............................................................................|n|nCompileTimeTests.tests.cpp:|nexpression failed|n CONSTEXPR_REQUIRE( lambda() != 50 )|nwith expansion:|n 50 != 50|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testFinished name='CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure' duration="{duration}"] +##teamcity[testStarted name='CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success'] +##teamcity[testFinished name='CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success' duration="{duration}"] +##teamcity[testStarted name='CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during compilation'] +##teamcity[testFinished name='CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during compilation' duration="{duration}"] ##teamcity[testStarted name='Capture and info messages'] ##teamcity[testFinished name='Capture and info messages' duration="{duration}"] ##teamcity[testStarted name='Captures do not leave block with an exception'] @@ -604,6 +612,8 @@ ##teamcity[testStdOut name='Sends stuff to stdout and stderr' out='A string sent directly to stdout|n'] ##teamcity[testStdErr name='Sends stuff to stdout and stderr' out='A string sent directly to stderr|nA string sent to stderr via clog|n'] ##teamcity[testFinished name='Sends stuff to stdout and stderr' duration="{duration}"] +##teamcity[testStarted name='Simple compile time section'] +##teamcity[testFinished name='Simple compile time section' duration="{duration}"] ##teamcity[testStarted name='Some simple comparisons between doubles'] ##teamcity[testFinished name='Some simple comparisons between doubles' duration="{duration}"] ##teamcity[testStarted name='Standard output from all sections is reported'] diff --git a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt index 10e318de5c..7b56090bb8 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt @@ -247,6 +247,14 @@ ##teamcity[testFinished name='CAPTURE can deal with complex expressions involving commas' duration="{duration}"] ##teamcity[testStarted name='CAPTURE parses string and character constants'] ##teamcity[testFinished name='CAPTURE parses string and character constants' duration="{duration}"] +##teamcity[testStarted name='CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure'] +##teamcity[testIgnored name='CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure' message='-------------------------------------------------------------------------------|nUnary -> Expression should be evaluated only once|n-------------------------------------------------------------------------------|nCompileTimeTests.tests.cpp:|n...............................................................................|n|nCompileTimeTests.tests.cpp:|nexpression failed|n CONSTEXPR_REQUIRE( ( lambda() != 50 ) )|nwith expansion:|n false|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testIgnored name='CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure' message='-------------------------------------------------------------------------------|nBinary -> Expression should be evaluated only once|n-------------------------------------------------------------------------------|nCompileTimeTests.tests.cpp:|n...............................................................................|n|nCompileTimeTests.tests.cpp:|nexpression failed|n CONSTEXPR_REQUIRE( lambda() != 50 )|nwith expansion:|n 50 != 50|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testFinished name='CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of failure' duration="{duration}"] +##teamcity[testStarted name='CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success'] +##teamcity[testFinished name='CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate the expression only once at runtime in case of success' duration="{duration}"] +##teamcity[testStarted name='CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during compilation'] +##teamcity[testFinished name='CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE behavior during compilation' duration="{duration}"] ##teamcity[testStarted name='Capture and info messages'] ##teamcity[testFinished name='Capture and info messages' duration="{duration}"] ##teamcity[testStarted name='Captures do not leave block with an exception'] @@ -604,6 +612,8 @@ ##teamcity[testStdOut name='Sends stuff to stdout and stderr' out='A string sent directly to stdout|n'] ##teamcity[testStdErr name='Sends stuff to stdout and stderr' out='A string sent directly to stderr|nA string sent to stderr via clog|n'] ##teamcity[testFinished name='Sends stuff to stdout and stderr' duration="{duration}"] +##teamcity[testStarted name='Simple compile time section'] +##teamcity[testFinished name='Simple compile time section' duration="{duration}"] ##teamcity[testStarted name='Some simple comparisons between doubles'] ##teamcity[testFinished name='Some simple comparisons between doubles' duration="{duration}"] ##teamcity[testStarted name='Standard output from all sections is reported'] diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index 142d662016..35f04954fa 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -3127,6 +3127,92 @@ Approx( 1.23399996757507324 ) + +
+ + + numberOfCalls < 2 + + + 1 < 2 + + + + + ( lambda() != 50 ) + + + false + + + +
+
+ + + numberOfCalls < 2 + + + 1 < 2 + + + + + lambda() != 50 + + + 50 != 50 + + + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ + + [Passed during compilation] + + + [Passed during compilation] + + + +
+
+ + + [Passed during compilation] + + + [Passed during compilation] + + + +
+
+ + + [Passed during compilation] + + + [Passed during compilation] + + + +
+ +
@@ -13208,6 +13294,20 @@ A string sent to stderr via clog + +
+ + + [Passed during compilation] + + + [Passed during compilation] + + + +
+ +
@@ -22324,6 +22424,6 @@ Approx( -1.95996398454005449 )
- - + + diff --git a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt index 62562332c9..e51acfcb5a 100644 --- a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt @@ -3127,6 +3127,92 @@ Approx( 1.23399996757507324 )
+ +
+ + + numberOfCalls < 2 + + + 1 < 2 + + + + + ( lambda() != 50 ) + + + false + + + +
+
+ + + numberOfCalls < 2 + + + 1 < 2 + + + + + lambda() != 50 + + + 50 != 50 + + + +
+ +
+ +
+ +
+
+ +
+ +
+ +
+ + + [Passed during compilation] + + + [Passed during compilation] + + + +
+
+ + + [Passed during compilation] + + + [Passed during compilation] + + + +
+
+ + + [Passed during compilation] + + + [Passed during compilation] + + + +
+ +
@@ -13208,6 +13294,20 @@ A string sent to stderr via clog + +
+ + + [Passed during compilation] + + + [Passed during compilation] + + + +
+ +
@@ -22323,6 +22423,6 @@ Approx( -1.95996398454005449 )
- - + + diff --git a/tests/SelfTest/UsageTests/CompileTimeTests.tests.cpp b/tests/SelfTest/UsageTests/CompileTimeTests.tests.cpp new file mode 100644 index 0000000000..dd06806116 --- /dev/null +++ b/tests/SelfTest/UsageTests/CompileTimeTests.tests.cpp @@ -0,0 +1,126 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 + +#include +#include + +// In C++14, CONSTEXPR_SECTIONS are not supported. +// For consistency between test results across C++ standard versions, we +// redefine here CONSTEXPR_SECTION as a SECTION with a mock assertion. +#ifndef CATCH_CONFIG_CONSTEXPR_SECTIONS + +# if defined( __GNUC__ ) && !defined( __clang__ ) && !defined( __ICC ) && \ + !defined( __CUDACC__ ) && !defined( __LCC__ ) && \ + !defined( __NVCOMPILER ) && __GNUC__ <= 9 +# define SUPPRESS_MISLEADING_INDENTATION_WARNINGS \ + _Pragma( "GCC diagnostic ignored \"-Wmisleading-indentation\"" ) +# else +# define SUPPRESS_MISLEADING_INDENTATION_WARNINGS +# endif + +# undef CONSTEXPR_SECTION +# define CONSTEXPR_SECTION( ... ) \ + CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + SUPPRESS_MISLEADING_INDENTATION_WARNINGS \ + SECTION( "[Passed during compilation] " __VA_ARGS__ ) { \ + Catch::ConstexprSection::addFakeAssertion(); \ + } \ + CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION +#endif + +TEST_CASE( "Simple compile time section" ) { + CONSTEXPR_SECTION( "Simple compile time section" ) { + int x = 5; + x *= 10; + CONSTEXPR_REQUIRE( x == 50 ); + CONSTEXPR_REQUIRE_FALSE( x != 50 ); + }; +} + +TEST_CASE( "CONSTEXPR_SECTION, CONSTEXPR_REQUIRE, " + "CONSTEXPR_REQUIRE_FALSE behavior during compilation" ) { + CONSTEXPR_SECTION( "First" ) { + int x = 19; + CONSTEXPR_REQUIRE( x == 19 ); + x *= 10; + CONSTEXPR_REQUIRE( x == 190 ); + + bool b = false; + CONSTEXPR_REQUIRE_FALSE( b ); + b = true; + CONSTEXPR_REQUIRE( b ); + }; + + CONSTEXPR_SECTION( "Second", "Having a description should be ok" ) { + double x = 1.1; + x *= 10; + CONSTEXPR_REQUIRE( x > 10.0 ); + CONSTEXPR_REQUIRE_FALSE( x < -9.0 ); + }; + + CONSTEXPR_SECTION( "Third" ){ + // Keeping the implementation should be perfectly fine + }; +} + +TEST_CASE( "CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate " + "the expression only once at runtime in case of success" ) { + SECTION( "Unary -> Expression should be evaluated only once" ) { + int r = 5; + auto lambda = [&] { + r *= 10; + return r; + }; + CONSTEXPR_REQUIRE( ( lambda() == 50 ) ); + CONSTEXPR_REQUIRE( ( lambda() == 500 ) ); + const bool result = lambda() == 5000; + CONSTEXPR_REQUIRE( result ); + CONSTEXPR_REQUIRE_FALSE( !result ); + + CONSTEXPR_REQUIRE( true ); + CONSTEXPR_REQUIRE_FALSE( false ); + SUCCEED( "Silent empty section warning (at runtime, " + "CONSTEXPR_REQUIRE does nothing if passed)" ); + } + SECTION( "Binary -> Expression should be evaluated only once" ) { + int r = 5; + auto lambda = [&] { + r *= 10; + return r; + }; + CONSTEXPR_REQUIRE( lambda() == 50 ); + CONSTEXPR_REQUIRE( lambda() == 500 ); + SUCCEED( "Silent empty section warning (at runtime, " + "CONSTEXPR_REQUIRE does nothing if passed)" ); + } + SUCCEED( "Silent empty section warning" ); +} + +TEST_CASE( "CONSTEXPR_REQUIRE, CONSTEXPR_REQUIRE_FALSE should evaluate " + "the expression only once at runtime in case of failure", + "[!shouldfail]" ) { + SECTION( "Unary -> Expression should be evaluated only once" ) { + int numberOfCalls = 0; + auto lambda = [&] { + ++numberOfCalls; + REQUIRE( numberOfCalls < 2 ); // lambda() was evaluated + return 50; + }; + CONSTEXPR_REQUIRE( ( lambda() != 50 ) ); + } + SECTION( "Binary -> Expression should be evaluated only once" ) { + int numberOfCalls = 0; + auto lambda = [&] { + ++numberOfCalls; + REQUIRE( numberOfCalls < 2 ); // lambda() was evaluated twice + return 50; + }; + CONSTEXPR_REQUIRE( lambda() != 50 ); + } + SUCCEED( "Silent empty section warning" ); +}