Added _THROWS_WITH macros
- asserts on exception message
diff --git a/include/catch.hpp b/include/catch.hpp
index f6359c0..505fa19 100644
--- a/include/catch.hpp
+++ b/include/catch.hpp
@@ -70,8 +70,9 @@
#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
-#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
+#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
+#define CATCH_REQUIRE_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, expectedMessage, "CATCH_REQUIRE_THROWS_WITH" )
#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
@@ -82,6 +83,7 @@
#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
+#define CATCH_CHECK_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, expectedMessage, "CATCH_CHECK_THROWS_WITH" )
#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
@@ -135,8 +137,9 @@
#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
-#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
+#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
+#define REQUIRE_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, expectedMessage, "REQUIRE_THROWS_WITH" )
#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
@@ -145,8 +148,9 @@
#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
-#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
+#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
+#define CHECK_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, expectedMessage, "CHECK_THROWS_WITH" )
#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp
index 7bfef0e..3858261 100644
--- a/include/internal/catch_capture.hpp
+++ b/include/internal/catch_capture.hpp
@@ -66,16 +66,16 @@
} while( Catch::alwaysFalse() )
///////////////////////////////////////////////////////////////////////////////
-#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \
+#define INTERNAL_CATCH_THROWS( expr, resultDisposition, expectedMessage, macroName ) \
do { \
- Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, expectedMessage ); \
if( __catchResult.allowThrows() ) \
try { \
expr; \
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
} \
catch( ... ) { \
- __catchResult.captureResult( Catch::ResultWas::Ok ); \
+ __catchResult.captureExpectedException( expectedMessage ); \
} \
else \
__catchResult.captureResult( Catch::ResultWas::Ok ); \
diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h
index b44882b..c8cd92e 100644
--- a/include/internal/catch_result_builder.h
+++ b/include/internal/catch_result_builder.h
@@ -38,7 +38,8 @@
ResultBuilder( char const* macroName,
SourceLineInfo const& lineInfo,
char const* capturedExpression,
- ResultDisposition::Flags resultDisposition );
+ ResultDisposition::Flags resultDisposition,
+ char const* secondArg = "" );
template<typename T>
ExpressionLhs<T const&> operator <= ( T const& operand );
@@ -67,6 +68,8 @@
void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
void captureResult( ResultWas::OfType resultType );
void captureExpression();
+ void captureExpectedException( std::string const& expectedMessage );
+ void handleResult( AssertionResult const& result );
void react();
bool shouldDebugBreak() const;
bool allowThrows() const;
diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.hpp
index 8ce4a4f..cc083bc 100644
--- a/include/internal/catch_result_builder.hpp
+++ b/include/internal/catch_result_builder.hpp
@@ -18,11 +18,17 @@
namespace Catch {
+ std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
+ return secondArg.empty()
+ ? capturedExpression
+ : capturedExpression + ", \"" + secondArg + "\"";
+ }
ResultBuilder::ResultBuilder( char const* macroName,
SourceLineInfo const& lineInfo,
char const* capturedExpression,
- ResultDisposition::Flags resultDisposition )
- : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ),
+ ResultDisposition::Flags resultDisposition,
+ char const* secondArg )
+ : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
m_shouldDebugBreak( false ),
m_shouldThrow( false )
{}
@@ -64,10 +70,31 @@
captureExpression();
}
+ void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
+ assert( m_exprComponents.testFalse == false );
+ AssertionResultData data = m_data;
+ data.resultType = ResultWas::Ok;
+ data.reconstructedExpression = m_assertionInfo.capturedExpression;
+ if( expectedMessage != "" ) {
+
+ std::string actualMessage = Catch::translateActiveException();
+ if( expectedMessage != actualMessage ) {
+ data.resultType = ResultWas::ExpressionFailed;
+ data.reconstructedExpression = actualMessage;
+ }
+ }
+ AssertionResult result( m_assertionInfo, data );
+ handleResult( result );
+ }
+
void ResultBuilder::captureExpression() {
AssertionResult result = build();
+ handleResult( result );
+ }
+ void ResultBuilder::handleResult( AssertionResult const& result )
+ {
getResultCapture().assertionEnded( result );
-
+
if( !result.isOk() ) {
if( getCurrentContext().getConfig()->shouldDebugBreak() )
m_shouldDebugBreak = true;
diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt
index 3fc7612..de86a47 100644
--- a/projects/SelfTest/Baselines/console.std.approved.txt
+++ b/projects/SelfTest/Baselines/console.std.approved.txt
@@ -398,6 +398,17 @@
3.14
-------------------------------------------------------------------------------
+Exception messages can be tested for
+-------------------------------------------------------------------------------
+ExceptionTests.cpp:<line number>
+...............................................................................
+
+ExceptionTests.cpp:<line number>: FAILED:
+ REQUIRE_THROWS_WITH( thisThrows(), "should fail" )
+with expansion:
+ expected exception
+
+-------------------------------------------------------------------------------
INFO and WARN do not abort tests
-------------------------------------------------------------------------------
MessageTests.cpp:<line number>
@@ -786,6 +797,6 @@
"first" == "second"
===============================================================================
-test cases: 155 | 116 passed | 38 failed | 1 failed as expected
-assertions: 765 | 673 passed | 79 failed | 13 failed as expected
+test cases: 156 | 116 passed | 39 failed | 1 failed as expected
+assertions: 767 | 674 passed | 80 failed | 13 failed as expected
diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt
index 2023c59..6e191f5 100644
--- a/projects/SelfTest/Baselines/console.sw.approved.txt
+++ b/projects/SelfTest/Baselines/console.sw.approved.txt
@@ -1278,6 +1278,21 @@
REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) )
-------------------------------------------------------------------------------
+Exception messages can be tested for
+-------------------------------------------------------------------------------
+ExceptionTests.cpp:<line number>
+...............................................................................
+
+ExceptionTests.cpp:<line number>:
+PASSED:
+ REQUIRE_THROWS_WITH( thisThrows(), "expected exception" )
+
+ExceptionTests.cpp:<line number>: FAILED:
+ REQUIRE_THROWS_WITH( thisThrows(), "should fail" )
+with expansion:
+ expected exception
+
+-------------------------------------------------------------------------------
Generators over two ranges
-------------------------------------------------------------------------------
GeneratorTests.cpp:<line number>
@@ -7944,6 +7959,6 @@
true
===============================================================================
-test cases: 155 | 100 passed | 54 failed | 1 failed as expected
-assertions: 785 | 673 passed | 99 failed | 13 failed as expected
+test cases: 156 | 100 passed | 55 failed | 1 failed as expected
+assertions: 787 | 674 passed | 100 failed | 13 failed as expected
diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt
index 48b8467..36e31fe 100644
--- a/projects/SelfTest/Baselines/junit.sw.approved.txt
+++ b/projects/SelfTest/Baselines/junit.sw.approved.txt
@@ -1,5 +1,5 @@
<testsuites>
- <testsuite name="all tests" errors="12" failures="87" tests="785" hostname="tbd" time="{duration}" timestamp="tbd">
+ <testsuite name="all tests" errors="12" failures="88" tests="787" hostname="tbd" time="{duration}" timestamp="tbd">
<testcase classname="global" name="toString(enum)" time="{duration}"/>
<testcase classname="global" name="toString(enum w/operator<<)" time="{duration}"/>
<testcase classname="global" name="toString(enum class)" time="{duration}"/>
@@ -251,6 +251,11 @@
</error>
</testcase>
<testcase classname="global" name="NotImplemented exception" time="{duration}"/>
+ <testcase classname="global" name="Exception messages can be tested for" time="{duration}">
+ <failure message="expected exception" type="REQUIRE_THROWS_WITH">
+ExceptionTests.cpp:<line number>
+ </failure>
+ </testcase>
<testcase classname="global" name="Generators over two ranges" time="{duration}"/>
<testcase classname="global" name="Generator over a range of pairs" time="{duration}"/>
<testcase classname="global" name="INFO and WARN do not abort tests" time="{duration}"/>
diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt
index 974559a..01144a0 100644
--- a/projects/SelfTest/Baselines/xml.sw.approved.txt
+++ b/projects/SelfTest/Baselines/xml.sw.approved.txt
@@ -1596,6 +1596,25 @@
</Expression>
<OverallResult success="true"/>
</TestCase>
+ <TestCase name="Exception messages can be tested for">
+ <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" >
+ <Original>
+ thisThrows(), "expected exception"
+ </Original>
+ <Expanded>
+ thisThrows(), "expected exception"
+ </Expanded>
+ </Expression>
+ <Expression success="false" type="REQUIRE_THROWS_WITH" filename="projects/SelfTest/ExceptionTests.cpp" >
+ <Original>
+ thisThrows(), "should fail"
+ </Original>
+ <Expanded>
+ expected exception
+ </Expanded>
+ </Expression>
+ <OverallResult success="false"/>
+ </TestCase>
<TestCase name="Generators over two ranges">
<Expression success="true" type="CATCH_REQUIRE" filename="projects/SelfTest/GeneratorTests.cpp" >
<Original>
@@ -8220,7 +8239,7 @@
</Section>
<OverallResult success="true"/>
</TestCase>
- <OverallResults successes="673" failures="99" expectedFailures="13"/>
+ <OverallResults successes="674" failures="100" expectedFailures="13"/>
</Group>
- <OverallResults successes="673" failures="99" expectedFailures="13"/>
+ <OverallResults successes="674" failures="100" expectedFailures="13"/>
</Catch>
diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp
index 7de1d17..eb24160 100644
--- a/projects/SelfTest/ExceptionTests.cpp
+++ b/projects/SelfTest/ExceptionTests.cpp
@@ -152,3 +152,8 @@
{
REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) );
}
+
+TEST_CASE( "Exception messages can be tested for", "[.][failing]" ) {
+ REQUIRE_THROWS_WITH( thisThrows(), "expected exception" );
+ REQUIRE_THROWS_WITH( thisThrows(), "should fail" );
+}