From d547cae549f484dda3c6a2b3cc5f71b9db40e842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 27 Jul 2025 20:28:51 +0200 Subject: [PATCH] Fix bad error reporting for nested exceptions in default configuration Bad handling of `TestFailureException` when translating unexpected exceptions inside assertion macros led to the unexpected exceptions handling erroring out through throwing the same exception again. This was then backstopped by the machinery for handling uncaught exceptions from assertions, which is normally used by the `CATCH_CONFIG_FAST_COMPILE` machinery, where we assume that it can only be invoked because the assertion macros are not configured to catch assertions. Closes #1292 --- docs/skipping-passing-failing.md | 14 ++++ src/catch2/benchmark/catch_benchmark.hpp | 4 +- .../catch_exception_translator_registry.cpp | 4 +- .../Baselines/automake.sw.approved.txt | 3 + .../Baselines/automake.sw.multi.approved.txt | 3 + .../Baselines/compact.sw.approved.txt | 11 ++- .../Baselines/compact.sw.multi.approved.txt | 11 ++- .../Baselines/console.std.approved.txt | 51 ++++++++++++- .../Baselines/console.sw.approved.txt | 54 +++++++++++++- .../Baselines/console.sw.multi.approved.txt | 54 +++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 48 +++++++++++- .../Baselines/junit.sw.multi.approved.txt | 48 +++++++++++- .../Baselines/sonarqube.sw.approved.txt | 43 +++++++++++ .../Baselines/sonarqube.sw.multi.approved.txt | 43 +++++++++++ tests/SelfTest/Baselines/tap.sw.approved.txt | 16 +++- .../Baselines/tap.sw.multi.approved.txt | 16 +++- .../Baselines/teamcity.sw.approved.txt | 12 +++ .../Baselines/teamcity.sw.multi.approved.txt | 12 +++ tests/SelfTest/Baselines/xml.sw.approved.txt | 73 ++++++++++++++++++- .../Baselines/xml.sw.multi.approved.txt | 73 ++++++++++++++++++- .../AssertionHandler.tests.cpp | 25 +++++++ 21 files changed, 595 insertions(+), 23 deletions(-) diff --git a/docs/skipping-passing-failing.md b/docs/skipping-passing-failing.md index 52bb18f7..1bdc1f03 100644 --- a/docs/skipping-passing-failing.md +++ b/docs/skipping-passing-failing.md @@ -52,6 +52,20 @@ TEST_CASE("failing test") { } ``` +Same applies for a `SKIP` nested inside an assertion: + +```cpp +static bool do_skip() { + SKIP(); + return true; +} + +TEST_CASE("Another failing test") { + CHECK(do_skip()); +} +``` + + ### Interaction with Sections and Generators Sections, nested sections as well as specific outputs from [generators](generators.md#top) diff --git a/src/catch2/benchmark/catch_benchmark.hpp b/src/catch2/benchmark/catch_benchmark.hpp index eb688e7d..ce68aee7 100644 --- a/src/catch2/benchmark/catch_benchmark.hpp +++ b/src/catch2/benchmark/catch_benchmark.hpp @@ -86,9 +86,7 @@ namespace Catch { auto analysis = Detail::analyse(*cfg, samples.data(), samples.data() + samples.size()); BenchmarkStats<> stats{ CATCH_MOVE(info), CATCH_MOVE(analysis.samples), analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance }; getResultCapture().benchmarkEnded(stats); - } CATCH_CATCH_ANON (TestFailureException const&) { - getResultCapture().benchmarkFailed("Benchmark failed due to failed assertion"_sr); - } CATCH_CATCH_ALL{ + } CATCH_CATCH_ALL { getResultCapture().benchmarkFailed(translateActiveException()); // We let the exception go further up so that the // test case is marked as failed. diff --git a/src/catch2/internal/catch_exception_translator_registry.cpp b/src/catch2/internal/catch_exception_translator_registry.cpp index 1eb61147..8867d78b 100644 --- a/src/catch2/internal/catch_exception_translator_registry.cpp +++ b/src/catch2/internal/catch_exception_translator_registry.cpp @@ -59,10 +59,10 @@ namespace Catch { // To avoid having to handle TFE explicitly everywhere, we just // rethrow it so that it goes back up the caller. catch( TestFailureException& ) { - std::rethrow_exception(std::current_exception()); + return "{ nested assertion failed }"; } catch( TestSkipException& ) { - std::rethrow_exception(std::current_exception()); + return "{ nested SKIP() called }"; } catch( std::exception const& ex ) { return ex.what(); diff --git a/tests/SelfTest/Baselines/automake.sw.approved.txt b/tests/SelfTest/Baselines/automake.sw.approved.txt index c5f538ff..63420188 100644 --- a/tests/SelfTest/Baselines/automake.sw.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.approved.txt @@ -95,6 +95,8 @@ Nor would this :test-result: PASS Approximate comparisons with mixed numeric types :test-result: PASS Arbitrary predicate matcher :test-result: PASS Assertion macros support bit operators and bool conversions +:test-result: XFAIL Assertions can be nested - CHECK +:test-result: XFAIL Assertions can be nested - REQUIRE :test-result: PASS Assertions then sections :test-result: PASS Basic use of the Contains range matcher :test-result: PASS Basic use of the Empty range matcher @@ -153,6 +155,7 @@ Nor would this :test-result: PASS Exceptions matchers :test-result: FAIL Expected exceptions that don't throw or unexpected exceptions fail the test :test-result: FAIL FAIL aborts the test +:test-result: XFAIL FAIL can be nested in assertion :test-result: FAIL FAIL does not require an argument :test-result: FAIL FAIL_CHECK does not abort the test :test-result: PASS Factorials are computed diff --git a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt index b573f81e..21725c68 100644 --- a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt @@ -93,6 +93,8 @@ :test-result: PASS Approximate comparisons with mixed numeric types :test-result: PASS Arbitrary predicate matcher :test-result: PASS Assertion macros support bit operators and bool conversions +:test-result: XFAIL Assertions can be nested - CHECK +:test-result: XFAIL Assertions can be nested - REQUIRE :test-result: PASS Assertions then sections :test-result: PASS Basic use of the Contains range matcher :test-result: PASS Basic use of the Empty range matcher @@ -151,6 +153,7 @@ :test-result: PASS Exceptions matchers :test-result: FAIL Expected exceptions that don't throw or unexpected exceptions fail the test :test-result: FAIL FAIL aborts the test +:test-result: XFAIL FAIL can be nested in assertion :test-result: FAIL FAIL does not require an argument :test-result: FAIL FAIL_CHECK does not abort the test :test-result: PASS Factorials are computed diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index 008d627c..84b00a50 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -332,6 +332,11 @@ Compilation.tests.cpp:: passed: !(lhs & rhs) for: !(Val: 1 & Val: 2 Compilation.tests.cpp:: passed: HasBitOperators{ 1 } & HasBitOperators{ 1 } for: Val: 1 & Val: 1 Compilation.tests.cpp:: passed: lhs ^ rhs for: Val: 1 ^ Val: 2 Compilation.tests.cpp:: passed: !(lhs ^ lhs) for: !(Val: 1 ^ Val: 1) +AssertionHandler.tests.cpp:: failed: i > 10 for: 2 > 10 +AssertionHandler.tests.cpp:: failed: unexpected exception with message: '{ nested assertion failed }'; expression was: foo( 2 ) == 2 +AssertionHandler.tests.cpp:: passed: true +AssertionHandler.tests.cpp:: failed: i > 10 for: 2 > 10 +AssertionHandler.tests.cpp:: failed: unexpected exception with message: '{ nested assertion failed }'; expression was: foo( 2 ) == 2 Tricky.tests.cpp:: passed: true Tricky.tests.cpp:: passed: true Tricky.tests.cpp:: passed: true @@ -636,6 +641,8 @@ Exception.tests.cpp:: failed: unexpected exception with message: 'e Exception.tests.cpp:: failed: expected exception, got none; expression was: thisDoesntThrow(), std::domain_error Exception.tests.cpp:: failed: unexpected exception with message: 'expected exception'; expression was: thisThrows() Message.tests.cpp:: failed: explicitly with 1 message: 'This is a failure' +AssertionHandler.tests.cpp:: failed: explicitly with 1 message: 'Throw a Catch::TestFailureException' +AssertionHandler.tests.cpp:: failed: unexpected exception with message: '{ nested assertion failed }'; expression was: do_fail() Message.tests.cpp:: failed: explicitly Message.tests.cpp:: failed: explicitly with 1 message: 'This is a failure' Message.tests.cpp:: warning: 'This message appears in the output' @@ -2862,7 +2869,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: 428 | 313 passed | 95 failed | 6 skipped | 14 failed as expected -assertions: 2281 | 2089 passed | 157 failed | 35 failed as expected +test cases: 431 | 313 passed | 95 failed | 6 skipped | 17 failed as expected +assertions: 2288 | 2090 passed | 157 failed | 41 failed as expected diff --git a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt index 57303829..dc500516 100644 --- a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt @@ -330,6 +330,11 @@ Compilation.tests.cpp:: passed: !(lhs & rhs) for: !(Val: 1 & Val: 2 Compilation.tests.cpp:: passed: HasBitOperators{ 1 } & HasBitOperators{ 1 } for: Val: 1 & Val: 1 Compilation.tests.cpp:: passed: lhs ^ rhs for: Val: 1 ^ Val: 2 Compilation.tests.cpp:: passed: !(lhs ^ lhs) for: !(Val: 1 ^ Val: 1) +AssertionHandler.tests.cpp:: failed: i > 10 for: 2 > 10 +AssertionHandler.tests.cpp:: failed: unexpected exception with message: '{ nested assertion failed }'; expression was: foo( 2 ) == 2 +AssertionHandler.tests.cpp:: passed: true +AssertionHandler.tests.cpp:: failed: i > 10 for: 2 > 10 +AssertionHandler.tests.cpp:: failed: unexpected exception with message: '{ nested assertion failed }'; expression was: foo( 2 ) == 2 Tricky.tests.cpp:: passed: true Tricky.tests.cpp:: passed: true Tricky.tests.cpp:: passed: true @@ -634,6 +639,8 @@ Exception.tests.cpp:: failed: unexpected exception with message: 'e Exception.tests.cpp:: failed: expected exception, got none; expression was: thisDoesntThrow(), std::domain_error Exception.tests.cpp:: failed: unexpected exception with message: 'expected exception'; expression was: thisThrows() Message.tests.cpp:: failed: explicitly with 1 message: 'This is a failure' +AssertionHandler.tests.cpp:: failed: explicitly with 1 message: 'Throw a Catch::TestFailureException' +AssertionHandler.tests.cpp:: failed: unexpected exception with message: '{ nested assertion failed }'; expression was: do_fail() Message.tests.cpp:: failed: explicitly Message.tests.cpp:: failed: explicitly with 1 message: 'This is a failure' Message.tests.cpp:: warning: 'This message appears in the output' @@ -2851,7 +2858,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: 428 | 313 passed | 95 failed | 6 skipped | 14 failed as expected -assertions: 2281 | 2089 passed | 157 failed | 35 failed as expected +test cases: 431 | 313 passed | 95 failed | 6 skipped | 17 failed as expected +assertions: 2288 | 2090 passed | 157 failed | 41 failed as expected diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt index 194b3676..96f43224 100644 --- a/tests/SelfTest/Baselines/console.std.approved.txt +++ b/tests/SelfTest/Baselines/console.std.approved.txt @@ -347,6 +347,38 @@ Exception.tests.cpp:: FAILED: due to unexpected exception with message: unexpected exception +------------------------------------------------------------------------------- +Assertions can be nested - CHECK +------------------------------------------------------------------------------- +AssertionHandler.tests.cpp: +............................................................................... + +AssertionHandler.tests.cpp:: FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 + +AssertionHandler.tests.cpp:: FAILED: + CHECK( foo( 2 ) == 2 ) +due to unexpected exception with message: + { nested assertion failed } + +------------------------------------------------------------------------------- +Assertions can be nested - REQUIRE +------------------------------------------------------------------------------- +AssertionHandler.tests.cpp: +............................................................................... + +AssertionHandler.tests.cpp:: FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 + +AssertionHandler.tests.cpp:: FAILED: + REQUIRE( foo( 2 ) == 2 ) +due to unexpected exception with message: + { nested assertion failed } + ------------------------------------------------------------------------------- Captures do not leave block with an exception ------------------------------------------------------------------------------- @@ -619,6 +651,21 @@ Message.tests.cpp:: FAILED: explicitly with message: This is a failure +------------------------------------------------------------------------------- +FAIL can be nested in assertion +------------------------------------------------------------------------------- +AssertionHandler.tests.cpp: +............................................................................... + +AssertionHandler.tests.cpp:: FAILED: +explicitly with message: + Throw a Catch::TestFailureException + +AssertionHandler.tests.cpp:: FAILED: + CHECK_NOTHROW( do_fail() ) +due to unexpected exception with message: + { nested assertion failed } + ------------------------------------------------------------------------------- FAIL does not require an argument ------------------------------------------------------------------------------- @@ -1672,6 +1719,6 @@ due to unexpected exception with message: Why would you throw a std::string? =============================================================================== -test cases: 428 | 331 passed | 76 failed | 7 skipped | 14 failed as expected -assertions: 2260 | 2089 passed | 136 failed | 35 failed as expected +test cases: 431 | 331 passed | 76 failed | 7 skipped | 17 failed as expected +assertions: 2267 | 2090 passed | 136 failed | 41 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index 1740933b..efb96e04 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -2566,6 +2566,41 @@ Compilation.tests.cpp:: PASSED: with expansion: !(Val: 1 ^ Val: 1) +------------------------------------------------------------------------------- +Assertions can be nested - CHECK +------------------------------------------------------------------------------- +AssertionHandler.tests.cpp: +............................................................................... + +AssertionHandler.tests.cpp:: FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 + +AssertionHandler.tests.cpp:: FAILED: + CHECK( foo( 2 ) == 2 ) +due to unexpected exception with message: + { nested assertion failed } + +AssertionHandler.tests.cpp:: PASSED: + CHECK( true ) + +------------------------------------------------------------------------------- +Assertions can be nested - REQUIRE +------------------------------------------------------------------------------- +AssertionHandler.tests.cpp: +............................................................................... + +AssertionHandler.tests.cpp:: FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 + +AssertionHandler.tests.cpp:: FAILED: + REQUIRE( foo( 2 ) == 2 ) +due to unexpected exception with message: + { nested assertion failed } + ------------------------------------------------------------------------------- Assertions then sections ------------------------------------------------------------------------------- @@ -4561,6 +4596,21 @@ Message.tests.cpp:: FAILED: explicitly with message: This is a failure +------------------------------------------------------------------------------- +FAIL can be nested in assertion +------------------------------------------------------------------------------- +AssertionHandler.tests.cpp: +............................................................................... + +AssertionHandler.tests.cpp:: FAILED: +explicitly with message: + Throw a Catch::TestFailureException + +AssertionHandler.tests.cpp:: FAILED: + CHECK_NOTHROW( do_fail() ) +due to unexpected exception with message: + { nested assertion failed } + ------------------------------------------------------------------------------- FAIL does not require an argument ------------------------------------------------------------------------------- @@ -19134,6 +19184,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 428 | 313 passed | 95 failed | 6 skipped | 14 failed as expected -assertions: 2281 | 2089 passed | 157 failed | 35 failed as expected +test cases: 431 | 313 passed | 95 failed | 6 skipped | 17 failed as expected +assertions: 2288 | 2090 passed | 157 failed | 41 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.multi.approved.txt b/tests/SelfTest/Baselines/console.sw.multi.approved.txt index 786ad4e9..0a84798a 100644 --- a/tests/SelfTest/Baselines/console.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.multi.approved.txt @@ -2564,6 +2564,41 @@ Compilation.tests.cpp:: PASSED: with expansion: !(Val: 1 ^ Val: 1) +------------------------------------------------------------------------------- +Assertions can be nested - CHECK +------------------------------------------------------------------------------- +AssertionHandler.tests.cpp: +............................................................................... + +AssertionHandler.tests.cpp:: FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 + +AssertionHandler.tests.cpp:: FAILED: + CHECK( foo( 2 ) == 2 ) +due to unexpected exception with message: + { nested assertion failed } + +AssertionHandler.tests.cpp:: PASSED: + CHECK( true ) + +------------------------------------------------------------------------------- +Assertions can be nested - REQUIRE +------------------------------------------------------------------------------- +AssertionHandler.tests.cpp: +............................................................................... + +AssertionHandler.tests.cpp:: FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 + +AssertionHandler.tests.cpp:: FAILED: + REQUIRE( foo( 2 ) == 2 ) +due to unexpected exception with message: + { nested assertion failed } + ------------------------------------------------------------------------------- Assertions then sections ------------------------------------------------------------------------------- @@ -4559,6 +4594,21 @@ Message.tests.cpp:: FAILED: explicitly with message: This is a failure +------------------------------------------------------------------------------- +FAIL can be nested in assertion +------------------------------------------------------------------------------- +AssertionHandler.tests.cpp: +............................................................................... + +AssertionHandler.tests.cpp:: FAILED: +explicitly with message: + Throw a Catch::TestFailureException + +AssertionHandler.tests.cpp:: FAILED: + CHECK_NOTHROW( do_fail() ) +due to unexpected exception with message: + { nested assertion failed } + ------------------------------------------------------------------------------- FAIL does not require an argument ------------------------------------------------------------------------------- @@ -19123,6 +19173,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 428 | 313 passed | 95 failed | 6 skipped | 14 failed as expected -assertions: 2281 | 2089 passed | 157 failed | 35 failed as expected +test cases: 431 | 313 passed | 95 failed | 6 skipped | 17 failed as expected +assertions: 2288 | 2090 passed | 157 failed | 41 failed as expected diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index f4e3bb0e..5c3af7bb 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -390,6 +390,38 @@ at Exception.tests.cpp: + + + +FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 +at AssertionHandler.tests.cpp: + + +FAILED: + CHECK( foo( 2 ) == 2 ) +{ nested assertion failed } +at AssertionHandler.tests.cpp: + + + + + +FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 +at AssertionHandler.tests.cpp: + + +FAILED: + REQUIRE( foo( 2 ) == 2 ) +{ nested assertion failed } +at AssertionHandler.tests.cpp: + + @@ -738,6 +770,20 @@ This is a failure at Message.tests.cpp: + + + +FAILED: +Throw a Catch::TestFailureException +at AssertionHandler.tests.cpp: + + +FAILED: + CHECK_NOTHROW( do_fail() ) +{ nested assertion failed } +at AssertionHandler.tests.cpp: + + FAILED: diff --git a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt index 0a205437..7b4563ff 100644 --- a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt @@ -1,6 +1,6 @@ - + @@ -389,6 +389,38 @@ at Exception.tests.cpp: + + + +FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 +at AssertionHandler.tests.cpp: + + +FAILED: + CHECK( foo( 2 ) == 2 ) +{ nested assertion failed } +at AssertionHandler.tests.cpp: + + + + + +FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 +at AssertionHandler.tests.cpp: + + +FAILED: + REQUIRE( foo( 2 ) == 2 ) +{ nested assertion failed } +at AssertionHandler.tests.cpp: + + @@ -737,6 +769,20 @@ This is a failure at Message.tests.cpp: + + + +FAILED: +Throw a Catch::TestFailureException +at AssertionHandler.tests.cpp: + + +FAILED: + CHECK_NOTHROW( do_fail() ) +{ nested assertion failed } +at AssertionHandler.tests.cpp: + + FAILED: diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index d25bceda..b97312d2 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -3,6 +3,49 @@ + + +FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 +at AssertionHandler.tests.cpp: + + +FAILED: + CHECK( foo( 2 ) == 2 ) +{ nested assertion failed } +at AssertionHandler.tests.cpp: + + + + +FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 +at AssertionHandler.tests.cpp: + + +FAILED: + REQUIRE( foo( 2 ) == 2 ) +{ nested assertion failed } +at AssertionHandler.tests.cpp: + + + + +FAILED: +Throw a Catch::TestFailureException +at AssertionHandler.tests.cpp: + + +FAILED: + CHECK_NOTHROW( do_fail() ) +{ nested assertion failed } +at AssertionHandler.tests.cpp: + + FAILED: diff --git a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt index 66b2c832..43493ebf 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt @@ -2,6 +2,49 @@ + + +FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 +at AssertionHandler.tests.cpp: + + +FAILED: + CHECK( foo( 2 ) == 2 ) +{ nested assertion failed } +at AssertionHandler.tests.cpp: + + + + +FAILED: + REQUIRE( i > 10 ) +with expansion: + 2 > 10 +at AssertionHandler.tests.cpp: + + +FAILED: + REQUIRE( foo( 2 ) == 2 ) +{ nested assertion failed } +at AssertionHandler.tests.cpp: + + + + +FAILED: +Throw a Catch::TestFailureException +at AssertionHandler.tests.cpp: + + +FAILED: + CHECK_NOTHROW( do_fail() ) +{ nested assertion failed } +at AssertionHandler.tests.cpp: + + FAILED: diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index c7f2f3a5..ed79ca8d 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -612,6 +612,16 @@ ok {test-number} - HasBitOperators{ 1 } & HasBitOperators{ 1 } for: Val: 1 & Val ok {test-number} - lhs ^ rhs for: Val: 1 ^ Val: 2 # Assertion macros support bit operators and bool conversions ok {test-number} - !(lhs ^ lhs) for: !(Val: 1 ^ Val: 1) +# Assertions can be nested - CHECK +not ok {test-number} - i > 10 for: 2 > 10 +# Assertions can be nested - CHECK +not ok {test-number} - unexpected exception with message: '{ nested assertion failed }'; expression was: foo( 2 ) == 2 +# Assertions can be nested - CHECK +ok {test-number} - true +# Assertions can be nested - REQUIRE +not ok {test-number} - i > 10 for: 2 > 10 +# Assertions can be nested - REQUIRE +not ok {test-number} - unexpected exception with message: '{ nested assertion failed }'; expression was: foo( 2 ) == 2 # Assertions then sections ok {test-number} - true # Assertions then sections @@ -1132,6 +1142,10 @@ not ok {test-number} - expected exception, got none; expression was: thisDoesntT not ok {test-number} - unexpected exception with message: 'expected exception'; expression was: thisThrows() # FAIL aborts the test not ok {test-number} - explicitly with 1 message: 'This is a failure' +# FAIL can be nested in assertion +not ok {test-number} - explicitly with 1 message: 'Throw a Catch::TestFailureException' +# FAIL can be nested in assertion +not ok {test-number} - unexpected exception with message: '{ nested assertion failed }'; expression was: do_fail() # FAIL does not require an argument not ok {test-number} - explicitly # FAIL_CHECK does not abort the test @@ -4583,5 +4597,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2293 +1..2300 diff --git a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt index 3632b386..901b458a 100644 --- a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt @@ -610,6 +610,16 @@ ok {test-number} - HasBitOperators{ 1 } & HasBitOperators{ 1 } for: Val: 1 & Val ok {test-number} - lhs ^ rhs for: Val: 1 ^ Val: 2 # Assertion macros support bit operators and bool conversions ok {test-number} - !(lhs ^ lhs) for: !(Val: 1 ^ Val: 1) +# Assertions can be nested - CHECK +not ok {test-number} - i > 10 for: 2 > 10 +# Assertions can be nested - CHECK +not ok {test-number} - unexpected exception with message: '{ nested assertion failed }'; expression was: foo( 2 ) == 2 +# Assertions can be nested - CHECK +ok {test-number} - true +# Assertions can be nested - REQUIRE +not ok {test-number} - i > 10 for: 2 > 10 +# Assertions can be nested - REQUIRE +not ok {test-number} - unexpected exception with message: '{ nested assertion failed }'; expression was: foo( 2 ) == 2 # Assertions then sections ok {test-number} - true # Assertions then sections @@ -1130,6 +1140,10 @@ not ok {test-number} - expected exception, got none; expression was: thisDoesntT not ok {test-number} - unexpected exception with message: 'expected exception'; expression was: thisThrows() # FAIL aborts the test not ok {test-number} - explicitly with 1 message: 'This is a failure' +# FAIL can be nested in assertion +not ok {test-number} - explicitly with 1 message: 'Throw a Catch::TestFailureException' +# FAIL can be nested in assertion +not ok {test-number} - unexpected exception with message: '{ nested assertion failed }'; expression was: do_fail() # FAIL does not require an argument not ok {test-number} - explicitly # FAIL_CHECK does not abort the test @@ -4572,5 +4586,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2293 +1..2300 diff --git a/tests/SelfTest/Baselines/teamcity.sw.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.approved.txt index 388164ef..87560b63 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.approved.txt @@ -225,6 +225,14 @@ ##teamcity[testFinished name='Arbitrary predicate matcher' duration="{duration}"] ##teamcity[testStarted name='Assertion macros support bit operators and bool conversions'] ##teamcity[testFinished name='Assertion macros support bit operators and bool conversions' duration="{duration}"] +##teamcity[testStarted name='Assertions can be nested - CHECK'] +##teamcity[testIgnored name='Assertions can be nested - CHECK' message='AssertionHandler.tests.cpp:|n...............................................................................|n|nAssertionHandler.tests.cpp:|nexpression failed|n REQUIRE( i > 10 )|nwith expansion:|n 2 > 10|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testIgnored name='Assertions can be nested - CHECK' message='AssertionHandler.tests.cpp:|nunexpected exception with message:|n "{ nested assertion failed }"|n CHECK( foo( 2 ) == 2 )|nwith expansion:|n foo( 2 ) == 2|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testFinished name='Assertions can be nested - CHECK' duration="{duration}"] +##teamcity[testStarted name='Assertions can be nested - REQUIRE'] +##teamcity[testIgnored name='Assertions can be nested - REQUIRE' message='AssertionHandler.tests.cpp:|n...............................................................................|n|nAssertionHandler.tests.cpp:|nexpression failed|n REQUIRE( i > 10 )|nwith expansion:|n 2 > 10|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testIgnored name='Assertions can be nested - REQUIRE' message='AssertionHandler.tests.cpp:|nunexpected exception with message:|n "{ nested assertion failed }"|n REQUIRE( foo( 2 ) == 2 )|nwith expansion:|n foo( 2 ) == 2|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testFinished name='Assertions can be nested - REQUIRE' duration="{duration}"] ##teamcity[testStarted name='Assertions then sections'] ##teamcity[testFinished name='Assertions then sections' duration="{duration}"] ##teamcity[testStarted name='Basic use of the Contains range matcher'] @@ -376,6 +384,10 @@ ##teamcity[testStarted name='FAIL aborts the test'] ##teamcity[testFailed name='FAIL aborts the test' message='Message.tests.cpp:|n...............................................................................|n|nMessage.tests.cpp:|nexplicit failure with message:|n "This is a failure"'] ##teamcity[testFinished name='FAIL aborts the test' duration="{duration}"] +##teamcity[testStarted name='FAIL can be nested in assertion'] +##teamcity[testIgnored name='FAIL can be nested in assertion' message='AssertionHandler.tests.cpp:|n...............................................................................|n|nAssertionHandler.tests.cpp:|nexplicit failure with message:|n "Throw a Catch::TestFailureException"- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testIgnored name='FAIL can be nested in assertion' message='AssertionHandler.tests.cpp:|nunexpected exception with message:|n "{ nested assertion failed }"|n CHECK_NOTHROW( do_fail() )|nwith expansion:|n do_fail()|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testFinished name='FAIL can be nested in assertion' duration="{duration}"] ##teamcity[testStarted name='FAIL does not require an argument'] ##teamcity[testFailed name='FAIL does not require an argument' message='Message.tests.cpp:|n...............................................................................|n|nMessage.tests.cpp:|nexplicit failure'] ##teamcity[testFinished name='FAIL does not require an argument' duration="{duration}"] diff --git a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt index 1140d12b..228deda4 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt @@ -225,6 +225,14 @@ ##teamcity[testFinished name='Arbitrary predicate matcher' duration="{duration}"] ##teamcity[testStarted name='Assertion macros support bit operators and bool conversions'] ##teamcity[testFinished name='Assertion macros support bit operators and bool conversions' duration="{duration}"] +##teamcity[testStarted name='Assertions can be nested - CHECK'] +##teamcity[testIgnored name='Assertions can be nested - CHECK' message='AssertionHandler.tests.cpp:|n...............................................................................|n|nAssertionHandler.tests.cpp:|nexpression failed|n REQUIRE( i > 10 )|nwith expansion:|n 2 > 10|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testIgnored name='Assertions can be nested - CHECK' message='AssertionHandler.tests.cpp:|nunexpected exception with message:|n "{ nested assertion failed }"|n CHECK( foo( 2 ) == 2 )|nwith expansion:|n foo( 2 ) == 2|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testFinished name='Assertions can be nested - CHECK' duration="{duration}"] +##teamcity[testStarted name='Assertions can be nested - REQUIRE'] +##teamcity[testIgnored name='Assertions can be nested - REQUIRE' message='AssertionHandler.tests.cpp:|n...............................................................................|n|nAssertionHandler.tests.cpp:|nexpression failed|n REQUIRE( i > 10 )|nwith expansion:|n 2 > 10|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testIgnored name='Assertions can be nested - REQUIRE' message='AssertionHandler.tests.cpp:|nunexpected exception with message:|n "{ nested assertion failed }"|n REQUIRE( foo( 2 ) == 2 )|nwith expansion:|n foo( 2 ) == 2|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testFinished name='Assertions can be nested - REQUIRE' duration="{duration}"] ##teamcity[testStarted name='Assertions then sections'] ##teamcity[testFinished name='Assertions then sections' duration="{duration}"] ##teamcity[testStarted name='Basic use of the Contains range matcher'] @@ -376,6 +384,10 @@ ##teamcity[testStarted name='FAIL aborts the test'] ##teamcity[testFailed name='FAIL aborts the test' message='Message.tests.cpp:|n...............................................................................|n|nMessage.tests.cpp:|nexplicit failure with message:|n "This is a failure"'] ##teamcity[testFinished name='FAIL aborts the test' duration="{duration}"] +##teamcity[testStarted name='FAIL can be nested in assertion'] +##teamcity[testIgnored name='FAIL can be nested in assertion' message='AssertionHandler.tests.cpp:|n...............................................................................|n|nAssertionHandler.tests.cpp:|nexplicit failure with message:|n "Throw a Catch::TestFailureException"- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testIgnored name='FAIL can be nested in assertion' message='AssertionHandler.tests.cpp:|nunexpected exception with message:|n "{ nested assertion failed }"|n CHECK_NOTHROW( do_fail() )|nwith expansion:|n do_fail()|n- failure ignore as test marked as |'ok to fail|'|n'] +##teamcity[testFinished name='FAIL can be nested in assertion' duration="{duration}"] ##teamcity[testStarted name='FAIL does not require an argument'] ##teamcity[testFailed name='FAIL does not require an argument' message='Message.tests.cpp:|n...............................................................................|n|nMessage.tests.cpp:|nexplicit failure'] ##teamcity[testFinished name='FAIL does not require an argument' duration="{duration}"] diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index e004b390..f5433e33 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -2716,6 +2716,58 @@ Approx( 1.23399996757507324 ) + + + + i > 10 + + + 2 > 10 + + + + + foo( 2 ) == 2 + + + foo( 2 ) == 2 + + + { nested assertion failed } + + + + + true + + + true + + + + + + + + i > 10 + + + 2 > 10 + + + + + foo( 2 ) == 2 + + + foo( 2 ) == 2 + + + { nested assertion failed } + + + + @@ -5124,6 +5176,23 @@ Approx( 1.30000000000000004 ) + + + Throw a Catch::TestFailureException + + + + do_fail() + + + do_fail() + + + { nested assertion failed } + + + + @@ -22113,6 +22182,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 897c955d..cfbbe39b 100644 --- a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt @@ -2716,6 +2716,58 @@ Approx( 1.23399996757507324 ) + + + + i > 10 + + + 2 > 10 + + + + + foo( 2 ) == 2 + + + foo( 2 ) == 2 + + + { nested assertion failed } + + + + + true + + + true + + + + + + + + i > 10 + + + 2 > 10 + + + + + foo( 2 ) == 2 + + + foo( 2 ) == 2 + + + { nested assertion failed } + + + + @@ -5124,6 +5176,23 @@ Approx( 1.30000000000000004 ) + + + Throw a Catch::TestFailureException + + + + do_fail() + + + do_fail() + + + { nested assertion failed } + + + + @@ -22112,6 +22181,6 @@ Approx( -1.95996398454005449 ) - - + + diff --git a/tests/SelfTest/IntrospectiveTests/AssertionHandler.tests.cpp b/tests/SelfTest/IntrospectiveTests/AssertionHandler.tests.cpp index ab096074..15966a07 100644 --- a/tests/SelfTest/IntrospectiveTests/AssertionHandler.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/AssertionHandler.tests.cpp @@ -15,3 +15,28 @@ TEST_CASE( "Incomplete AssertionHandler", "[assertion-handler][!shouldfail]" ) { "Dummy", Catch::ResultDisposition::Normal ); } + + +static int foo( int i ) { + REQUIRE( i > 10 ); + return 42; +} + +TEST_CASE( "Assertions can be nested - CHECK", "[assertions][!shouldfail]" ) { + CHECK( foo( 2 ) == 2 ); + // We should hit this, because CHECK continues on failure + CHECK( true ); +} + +TEST_CASE( "Assertions can be nested - REQUIRE", "[assertions][!shouldfail]" ) { + REQUIRE( foo( 2 ) == 2 ); + // We should not hit this, because REQUIRE does not continue on failure + CHECK( true ); +} + +static void do_fail() { FAIL( "Throw a Catch::TestFailureException" ); } + +TEST_CASE( "FAIL can be nested in assertion", "[assertions][!shouldfail]" ) { + // Fails, but the error message makes sense. + CHECK_NOTHROW( do_fail() ); +}