Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/tests/SelfTest/UsageTests
diff options
context:
space:
mode:
authorMartin Hořeňovský2025-07-21 17:47:59 +0200
committerMartin Hořeňovský2025-07-21 21:50:47 +0200
commit10aef62f21e52e5cd73bf0dc6ac8be35fbc4a798 (patch)
tree6e3bae072a2a0ecbd31f3ec0aab7eac8d673c5af /tests/SelfTest/UsageTests
parent98b4bbb35efc3937b24e1de5559c974bd2578a14 (diff)
downloadcatch3-10aef62f21e52e5cd73bf0dc6ac8be35fbc4a798.tar.gz
Regularize scoped message lifetime to only consider the object's scope
This means that: 1) Scoped messages are always removed at the end of their scope, even if the scope ended due to an exception. 2) Scoped messages outlive section end, if that section's scope is enclosed in their own. Previously neither of these were true, which has led to a number of surprising behaviour, where e.g. this: ```cpp TEST_CASE() { try { INFO( "some info" ); throw std::runtime_error( "ex" ); } catch (std::exception const&) {} REQUIRE( false ); } ``` would print "some info" as the message for the assertion, while this: ```cpp TEST_CASE() { INFO("Hello"); SECTION("dummy") {} REQUIRE(false); } ``` would not print out "Hello" as the message for the assertion. This had an underlying reason, in that it was trying to helpfully keep the messages around in case of unexpected exceptions, so that code like this: ```cpp TEST_CASE() { auto [input, expected] = GENERATE(...); CAPTURE(input); auto result = transform(input); // throws REQUIRE(result == expected); } ``` would report the value of `input` when `transform` throws. However, it was surprising in practice and was causing various issues around handling of messages in other cases. Closes #1759 Closes #2019 Closes #2959
Diffstat (limited to 'tests/SelfTest/UsageTests')
-rw-r--r--tests/SelfTest/UsageTests/Message.tests.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/tests/SelfTest/UsageTests/Message.tests.cpp b/tests/SelfTest/UsageTests/Message.tests.cpp
index 7626e005..07d3ee7b 100644
--- a/tests/SelfTest/UsageTests/Message.tests.cpp
+++ b/tests/SelfTest/UsageTests/Message.tests.cpp
@@ -310,3 +310,53 @@ TEST_CASE( "INFO and UNSCOPED_INFO can stream multiple arguments",
<< " parts." );
FAIL( "Show infos!" );
}
+
+TEST_CASE( "Scoped messages do not leave block with an exception", "[messages][info][.failing]" ) {
+ INFO( "Should be in scope at the end" );
+ { INFO( "This should go out of scope immediately" ); }
+
+ try {
+ INFO( "Should not be in scope at the end" );
+ throw std::runtime_error( "ex" );
+ } catch (std::exception const&) {}
+
+ REQUIRE( false );
+}
+
+TEST_CASE( "Captures do not leave block with an exception",
+ "[messages][capture][.failing]" ) {
+ int a = 1, b = 2, c = 3;
+
+ CAPTURE( a );
+ { CAPTURE( b ); }
+
+ try {
+ CAPTURE( c );
+ throw std::runtime_error( "ex" );
+ } catch ( std::exception const& ) {}
+
+ REQUIRE( false );
+}
+
+TEST_CASE( "Scoped messages outlive section end",
+ "[messages][info][.failing]" ) {
+ INFO( "Should survive a section end" );
+ SECTION( "Dummy section" ) { CHECK( true ); }
+
+ REQUIRE( false );
+}
+
+TEST_CASE( "Captures outlive section end", "[messages][info][.failing]" ) {
+ int a = 1;
+ CAPTURE( a );
+ SECTION( "Dummy section" ) { CHECK( true ); }
+
+ REQUIRE( false );
+}
+
+TEST_CASE( "Scoped message applies to all assertions in scope",
+ "[messages][info][.failing]" ) {
+ INFO( "This will be reported multiple times" );
+ CHECK( false );
+ CHECK( false );
+}