Add a matcher that checks exception's message

Only works for exceptions that publicly derive from `std::exception`
and the matching is done exactly, including case and whitespace.

Closes #1649
Closes #1728

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Your branch is up-to-date with 'origin/master'.
#
# Changes to be committed:
#	modified:   ../docs/matchers.md
#	modified:   ../include/internal/catch_capture_matchers.h
#	modified:   ../projects/CMakeLists.txt
#	modified:   ../projects/SelfTest/Baselines/compact.sw.approved.txt
#	modified:   ../projects/SelfTest/Baselines/console.std.approved.txt
#	modified:   ../projects/SelfTest/Baselines/console.sw.approved.txt
#	modified:   ../projects/SelfTest/Baselines/junit.sw.approved.txt
#	modified:   ../projects/SelfTest/Baselines/xml.sw.approved.txt
#	modified:   ../projects/SelfTest/UsageTests/Matchers.tests.cpp
#
# Untracked files:
#	./
#	../clang-full/
#	../clang-test/
#	../clang10-build/
#	../coverage-build/
#	../gcc-build/
#	../gcc-full/
#	../include/internal/catch_matchers_exception.cpp
#	../include/internal/catch_matchers_exception.hpp
#	../misc-build/
#	../msvc-sln/
#	../notes.txt
#	../test-install/
#
This commit is contained in:
Martin Hořeňovský 2019-10-13 20:37:07 +02:00
parent 28663fb959
commit 2cc0c71856
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
11 changed files with 198 additions and 26 deletions

View File

@ -81,6 +81,22 @@ The second argument is an optional description of the predicate, and is
used only during reporting of the result. used only during reporting of the result.
### Exception matchers
Catch2 also provides an exception matcher that can be used to verify
that an exception's message exactly matches desired string. The matcher
is `ExceptionMessageMatcher`, and we also provide a helper function
`Message`.
The matched exception must publicly derive from `std::exception` and
the message matching is done _exactly_, including case.
> `ExceptionMessageMatcher` was introduced in Catch X.Y.Z
Example use:
```cpp
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, Message("DerivedException::what"));
```
## Custom matchers ## Custom matchers
It's easy to provide your own matchers to extend Catch or just to work with your own types. It's easy to provide your own matchers to extend Catch or just to work with your own types.

View File

@ -10,6 +10,7 @@
#include "catch_capture.hpp" #include "catch_capture.hpp"
#include "catch_matchers.h" #include "catch_matchers.h"
#include "catch_matchers_exception.hpp"
#include "catch_matchers_floating.h" #include "catch_matchers_floating.h"
#include "catch_matchers_generic.hpp" #include "catch_matchers_generic.hpp"
#include "catch_matchers_string.h" #include "catch_matchers_string.h"

View File

@ -0,0 +1,30 @@
/*
* Created by Martin Hořeňovský on 13/10/2019.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "catch_matchers_exception.hpp"
namespace Catch {
namespace Matchers {
namespace Exception {
bool ExceptionMessageMatcher::match(std::exception const& ex) const {
return ex.what() == m_message;
}
std::string ExceptionMessageMatcher::describe() const {
return "exception message matches \"" + m_message + "\"";
}
}
Exception::ExceptionMessageMatcher Message(std::string const& message) {
return Exception::ExceptionMessageMatcher(message);
}
// namespace Exception
} // namespace Matchers
} // namespace Catch

View File

@ -0,0 +1,39 @@
/*
* Created by Martin Hořeňovský on 13/10/2019.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED
#include "catch_matchers.h"
#include <functional>
#include <string>
namespace Catch {
namespace Matchers {
namespace Exception {
class ExceptionMessageMatcher : public MatcherBase<std::exception> {
std::string m_message;
public:
ExceptionMessageMatcher(std::string const& message):
m_message(message)
{}
bool match(std::exception const& ex) const override;
std::string describe() const override;
};
} // namespace Exception
Exception::ExceptionMessageMatcher Message(std::string const& message);
} // namespace Matchers
} // namespace Catch
#endif // TWOBLUECUBES_CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED

View File

@ -151,6 +151,7 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_leak_detector.h ${HEADER_DIR}/internal/catch_leak_detector.h
${HEADER_DIR}/internal/catch_list.h ${HEADER_DIR}/internal/catch_list.h
${HEADER_DIR}/internal/catch_matchers.h ${HEADER_DIR}/internal/catch_matchers.h
${HEADER_DIR}/internal/catch_matchers_exception.hpp
${HEADER_DIR}/internal/catch_matchers_floating.h ${HEADER_DIR}/internal/catch_matchers_floating.h
${HEADER_DIR}/internal/catch_matchers_generic.hpp ${HEADER_DIR}/internal/catch_matchers_generic.hpp
${HEADER_DIR}/internal/catch_matchers_string.h ${HEADER_DIR}/internal/catch_matchers_string.h
@ -229,6 +230,7 @@ set(IMPL_SOURCES
${HEADER_DIR}/internal/catch_list.cpp ${HEADER_DIR}/internal/catch_list.cpp
${HEADER_DIR}/internal/catch_leak_detector.cpp ${HEADER_DIR}/internal/catch_leak_detector.cpp
${HEADER_DIR}/internal/catch_matchers.cpp ${HEADER_DIR}/internal/catch_matchers.cpp
${HEADER_DIR}/internal/catch_matchers_exception.cpp
${HEADER_DIR}/internal/catch_matchers_floating.cpp ${HEADER_DIR}/internal/catch_matchers_floating.cpp
${HEADER_DIR}/internal/catch_matchers_generic.cpp ${HEADER_DIR}/internal/catch_matchers_generic.cpp
${HEADER_DIR}/internal/catch_matchers_string.cpp ${HEADER_DIR}/internal/catch_matchers_string.cpp

View File

@ -385,16 +385,20 @@ Matchers.tests.cpp:<line number>: failed: expected exception, got none; expressi
Matchers.tests.cpp:<line number>: failed: expected exception, got none; expression was: doesNotThrow(), SpecialException, ExceptionMatcher{1} Matchers.tests.cpp:<line number>: failed: expected exception, got none; expression was: doesNotThrow(), SpecialException, ExceptionMatcher{1}
Matchers.tests.cpp:<line number>: failed: unexpected exception with message: 'Unknown exception'; expression was: throwsAsInt(1), SpecialException, ExceptionMatcher{1} Matchers.tests.cpp:<line number>: failed: unexpected exception with message: 'Unknown exception'; expression was: throwsAsInt(1), SpecialException, ExceptionMatcher{1}
Matchers.tests.cpp:<line number>: failed: unexpected exception with message: 'Unknown exception'; expression was: throwsAsInt(1), SpecialException, ExceptionMatcher{1} Matchers.tests.cpp:<line number>: failed: unexpected exception with message: 'Unknown exception'; expression was: throwsAsInt(1), SpecialException, ExceptionMatcher{1}
Matchers.tests.cpp:<line number>: failed: throws(3), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1 Matchers.tests.cpp:<line number>: failed: throwsSpecialException(3), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: failed: throws(4), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1 Matchers.tests.cpp:<line number>: failed: throwsSpecialException(4), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: passed: throws(1), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1 Matchers.tests.cpp:<line number>: passed: throwsSpecialException(1), SpecialException, ExceptionMatcher{1} for: SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: passed: throws(2), SpecialException, ExceptionMatcher{2} for: SpecialException::what special exception has value of 2 Matchers.tests.cpp:<line number>: passed: throwsSpecialException(2), SpecialException, ExceptionMatcher{2} for: SpecialException::what special exception has value of 2
Exception.tests.cpp:<line number>: passed: thisThrows(), "expected exception" for: "expected exception" equals: "expected exception" Exception.tests.cpp:<line number>: passed: thisThrows(), "expected exception" for: "expected exception" equals: "expected exception"
Exception.tests.cpp:<line number>: passed: thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) for: "expected exception" equals: "expected exception" (case insensitive) Exception.tests.cpp:<line number>: passed: thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) for: "expected exception" equals: "expected exception" (case insensitive)
Exception.tests.cpp:<line number>: passed: thisThrows(), StartsWith( "expected" ) for: "expected exception" starts with: "expected" Exception.tests.cpp:<line number>: passed: thisThrows(), StartsWith( "expected" ) for: "expected exception" starts with: "expected"
Exception.tests.cpp:<line number>: passed: thisThrows(), EndsWith( "exception" ) for: "expected exception" ends with: "exception" Exception.tests.cpp:<line number>: passed: thisThrows(), EndsWith( "exception" ) for: "expected exception" ends with: "exception"
Exception.tests.cpp:<line number>: passed: thisThrows(), Contains( "except" ) for: "expected exception" contains: "except" Exception.tests.cpp:<line number>: passed: thisThrows(), Contains( "except" ) for: "expected exception" contains: "except"
Exception.tests.cpp:<line number>: passed: thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) for: "expected exception" contains: "except" (case insensitive) Exception.tests.cpp:<line number>: passed: thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) for: "expected exception" contains: "except" (case insensitive)
Matchers.tests.cpp:<line number>: passed: throwsDerivedException(), DerivedException, Message("DerivedException::what") for: DerivedException::what
Matchers.tests.cpp:<line number>: passed: throwsDerivedException(), DerivedException, !Message("derivedexception::what") for: DerivedException::what not
Matchers.tests.cpp:<line number>: passed: throwsSpecialException(2), SpecialException, !Message("DerivedException::what") for: SpecialException::what not
Matchers.tests.cpp:<line number>: passed: throwsSpecialException(2), SpecialException, Message("SpecialException::what") for: SpecialException::what
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'expected exception'; expression was: thisThrows(), std::string Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'expected exception'; expression was: thisThrows(), std::string
Exception.tests.cpp:<line number>: failed: expected exception, got none; expression was: thisDoesntThrow(), std::domain_error Exception.tests.cpp:<line number>: failed: expected exception, got none; expression was: thisDoesntThrow(), std::domain_error
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'expected exception'; expression was: thisThrows() Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'expected exception'; expression was: thisThrows()

View File

@ -520,12 +520,12 @@ Matchers.tests.cpp:<line number>
............................................................................... ...............................................................................
Matchers.tests.cpp:<line number>: FAILED: Matchers.tests.cpp:<line number>: FAILED:
CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{1} ) CHECK_THROWS_MATCHES( throwsSpecialException(3), SpecialException, ExceptionMatcher{1} )
with expansion: with expansion:
SpecialException::what special exception has value of 1 SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: FAILED: Matchers.tests.cpp:<line number>: FAILED:
REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{1} ) REQUIRE_THROWS_MATCHES( throwsSpecialException(4), SpecialException, ExceptionMatcher{1} )
with expansion: with expansion:
SpecialException::what special exception has value of 1 SpecialException::what special exception has value of 1
@ -1380,6 +1380,6 @@ due to unexpected exception with message:
Why would you throw a std::string? Why would you throw a std::string?
=============================================================================== ===============================================================================
test cases: 303 | 229 passed | 70 failed | 4 failed as expected test cases: 304 | 230 passed | 70 failed | 4 failed as expected
assertions: 1615 | 1463 passed | 131 failed | 21 failed as expected assertions: 1619 | 1467 passed | 131 failed | 21 failed as expected

View File

@ -2930,12 +2930,12 @@ Matchers.tests.cpp:<line number>
............................................................................... ...............................................................................
Matchers.tests.cpp:<line number>: FAILED: Matchers.tests.cpp:<line number>: FAILED:
CHECK_THROWS_MATCHES( throws(3), SpecialException, ExceptionMatcher{1} ) CHECK_THROWS_MATCHES( throwsSpecialException(3), SpecialException, ExceptionMatcher{1} )
with expansion: with expansion:
SpecialException::what special exception has value of 1 SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: FAILED: Matchers.tests.cpp:<line number>: FAILED:
REQUIRE_THROWS_MATCHES( throws(4), SpecialException, ExceptionMatcher{1} ) REQUIRE_THROWS_MATCHES( throwsSpecialException(4), SpecialException, ExceptionMatcher{1} )
with expansion: with expansion:
SpecialException::what special exception has value of 1 SpecialException::what special exception has value of 1
@ -2946,12 +2946,12 @@ Matchers.tests.cpp:<line number>
............................................................................... ...............................................................................
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
CHECK_THROWS_MATCHES( throws(1), SpecialException, ExceptionMatcher{1} ) CHECK_THROWS_MATCHES( throwsSpecialException(1), SpecialException, ExceptionMatcher{1} )
with expansion: with expansion:
SpecialException::what special exception has value of 1 SpecialException::what special exception has value of 1
Matchers.tests.cpp:<line number>: PASSED: Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throws(2), SpecialException, ExceptionMatcher{2} ) REQUIRE_THROWS_MATCHES( throwsSpecialException(2), SpecialException, ExceptionMatcher{2} )
with expansion: with expansion:
SpecialException::what special exception has value of 2 SpecialException::what special exception has value of 2
@ -3006,6 +3006,32 @@ Exception.tests.cpp:<line number>: PASSED:
with expansion: with expansion:
"expected exception" contains: "except" (case insensitive) "expected exception" contains: "except" (case insensitive)
-------------------------------------------------------------------------------
Exceptions matchers
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throwsDerivedException(), DerivedException, Message("DerivedException::what") )
with expansion:
DerivedException::what
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throwsDerivedException(), DerivedException, !Message("derivedexception::what") )
with expansion:
DerivedException::what not
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throwsSpecialException(2), SpecialException, !Message("DerivedException::what") )
with expansion:
SpecialException::what not
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THROWS_MATCHES( throwsSpecialException(2), SpecialException, Message("SpecialException::what") )
with expansion:
SpecialException::what
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Expected exceptions that don't throw or unexpected exceptions fail the test Expected exceptions that don't throw or unexpected exceptions fail the test
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
@ -12913,6 +12939,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED: Misc.tests.cpp:<line number>: PASSED:
=============================================================================== ===============================================================================
test cases: 303 | 213 passed | 86 failed | 4 failed as expected test cases: 304 | 214 passed | 86 failed | 4 failed as expected
assertions: 1632 | 1463 passed | 148 failed | 21 failed as expected assertions: 1636 | 1467 passed | 148 failed | 21 failed as expected

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<testsuitesloose text artifact <testsuitesloose text artifact
> >
<testsuite name="<exe-name>" errors="17" failures="132" tests="1633" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> <testsuite name="<exe-name>" errors="17" failures="132" tests="1637" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties> <properties>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/> <property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/>
<property name="random-seed" value="1"/> <property name="random-seed" value="1"/>
@ -371,6 +371,7 @@ Matchers.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Exception messages can be tested for/exact match" time="{duration}"/> <testcase classname="<exe-name>.global" name="Exception messages can be tested for/exact match" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Exception messages can be tested for/different case" time="{duration}"/> <testcase classname="<exe-name>.global" name="Exception messages can be tested for/different case" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Exception messages can be tested for/wildcarded" time="{duration}"/> <testcase classname="<exe-name>.global" name="Exception messages can be tested for/wildcarded" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Exceptions matchers" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Expected exceptions that don't throw or unexpected exceptions fail the test" time="{duration}"> <testcase classname="<exe-name>.global" name="Expected exceptions that don't throw or unexpected exceptions fail the test" time="{duration}">
<error message="thisThrows(), std::string" type="CHECK_THROWS_AS"> <error message="thisThrows(), std::string" type="CHECK_THROWS_AS">
expected exception expected exception

View File

@ -3464,7 +3464,7 @@ Nor would this
<Section name="Contents are wrong" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" > <Section name="Contents are wrong" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="false" type="CHECK_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" > <Expression success="false" type="CHECK_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original> <Original>
throws(3), SpecialException, ExceptionMatcher{1} throwsSpecialException(3), SpecialException, ExceptionMatcher{1}
</Original> </Original>
<Expanded> <Expanded>
SpecialException::what special exception has value of 1 SpecialException::what special exception has value of 1
@ -3472,7 +3472,7 @@ Nor would this
</Expression> </Expression>
<Expression success="false" type="REQUIRE_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" > <Expression success="false" type="REQUIRE_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original> <Original>
throws(4), SpecialException, ExceptionMatcher{1} throwsSpecialException(4), SpecialException, ExceptionMatcher{1}
</Original> </Original>
<Expanded> <Expanded>
SpecialException::what special exception has value of 1 SpecialException::what special exception has value of 1
@ -3485,7 +3485,7 @@ Nor would this
<TestCase name="Exception matchers that succeed" tags="[!throws][exceptions][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" > <TestCase name="Exception matchers that succeed" tags="[!throws][exceptions][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="CHECK_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" > <Expression success="true" type="CHECK_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original> <Original>
throws(1), SpecialException, ExceptionMatcher{1} throwsSpecialException(1), SpecialException, ExceptionMatcher{1}
</Original> </Original>
<Expanded> <Expanded>
SpecialException::what special exception has value of 1 SpecialException::what special exception has value of 1
@ -3493,7 +3493,7 @@ Nor would this
</Expression> </Expression>
<Expression success="true" type="REQUIRE_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" > <Expression success="true" type="REQUIRE_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original> <Original>
throws(2), SpecialException, ExceptionMatcher{2} throwsSpecialException(2), SpecialException, ExceptionMatcher{2}
</Original> </Original>
<Expanded> <Expanded>
SpecialException::what special exception has value of 2 SpecialException::what special exception has value of 2
@ -3561,6 +3561,41 @@ Nor would this
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<TestCase name="Exceptions matchers" tags="[!throws][exceptions][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="REQUIRE_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
throwsDerivedException(), DerivedException, Message("DerivedException::what")
</Original>
<Expanded>
DerivedException::what
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
throwsDerivedException(), DerivedException, !Message("derivedexception::what")
</Original>
<Expanded>
DerivedException::what not
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
throwsSpecialException(2), SpecialException, !Message("DerivedException::what")
</Original>
<Expanded>
SpecialException::what not
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
throwsSpecialException(2), SpecialException, Message("SpecialException::what")
</Original>
<Expanded>
SpecialException::what
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Expected exceptions that don't throw or unexpected exceptions fail the test" tags="[!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" > <TestCase name="Expected exceptions that don't throw or unexpected exceptions fail the test" tags="[!throws][.][failing]" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
<Expression success="false" type="CHECK_THROWS_AS" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" > <Expression success="false" type="CHECK_THROWS_AS" filename="projects/<exe-name>/UsageTests/Exception.tests.cpp" >
<Original> <Original>
@ -15376,7 +15411,7 @@ loose text artifact
</Section> </Section>
<OverallResult success="true"/> <OverallResult success="true"/>
</TestCase> </TestCase>
<OverallResults successes="1463" failures="149" expectedFailures="21"/> <OverallResults successes="1467" failures="149" expectedFailures="21"/>
</Group> </Group>
<OverallResults successes="1463" failures="148" expectedFailures="21"/> <OverallResults successes="1467" failures="148" expectedFailures="21"/>
</Catch> </Catch>

View File

@ -52,10 +52,16 @@ namespace { namespace MatchersTests {
int i; int i;
}; };
struct DerivedException : std::exception {
char const* what() const noexcept override {
return "DerivedException::what";
}
};
void doesNotThrow() {} void doesNotThrow() {}
[[noreturn]] [[noreturn]]
void throws(int i) { void throwsSpecialException(int i) {
throw SpecialException{i}; throw SpecialException{i};
} }
@ -64,6 +70,11 @@ namespace { namespace MatchersTests {
throw i; throw i;
} }
[[noreturn]]
void throwsDerivedException() {
throw DerivedException{};
}
class ExceptionMatcher : public Catch::MatcherBase<SpecialException> { class ExceptionMatcher : public Catch::MatcherBase<SpecialException> {
int m_expected; int m_expected;
public: public:
@ -319,8 +330,8 @@ namespace { namespace MatchersTests {
} }
TEST_CASE("Exception matchers that succeed", "[matchers][exceptions][!throws]") { TEST_CASE("Exception matchers that succeed", "[matchers][exceptions][!throws]") {
CHECK_THROWS_MATCHES(throws(1), SpecialException, ExceptionMatcher{1}); CHECK_THROWS_MATCHES(throwsSpecialException(1), SpecialException, ExceptionMatcher{1});
REQUIRE_THROWS_MATCHES(throws(2), SpecialException, ExceptionMatcher{2}); REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, ExceptionMatcher{2});
} }
TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.failing]") { TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.failing]") {
@ -333,8 +344,8 @@ namespace { namespace MatchersTests {
REQUIRE_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{1}); REQUIRE_THROWS_MATCHES(throwsAsInt(1), SpecialException, ExceptionMatcher{1});
} }
SECTION("Contents are wrong") { SECTION("Contents are wrong") {
CHECK_THROWS_MATCHES(throws(3), SpecialException, ExceptionMatcher{1}); CHECK_THROWS_MATCHES(throwsSpecialException(3), SpecialException, ExceptionMatcher{1});
REQUIRE_THROWS_MATCHES(throws(4), SpecialException, ExceptionMatcher{1}); REQUIRE_THROWS_MATCHES(throwsSpecialException(4), SpecialException, ExceptionMatcher{1});
} }
} }
@ -533,6 +544,13 @@ namespace { namespace MatchersTests {
} }
} }
TEST_CASE("Exceptions matchers", "[matchers][exceptions][!throws]") {
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, Message("DerivedException::what"));
REQUIRE_THROWS_MATCHES(throwsDerivedException(), DerivedException, !Message("derivedexception::what"));
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, !Message("DerivedException::what"));
REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException, Message("SpecialException::what"));
}
} } // namespace MatchersTests } } // namespace MatchersTests
#endif // CATCH_CONFIG_DISABLE_MATCHERS #endif // CATCH_CONFIG_DISABLE_MATCHERS