Moved matcher-based capture macros into their own file

- this file excluded from the CATCH_CONFIG_DISABLE_MATCHERS path.
- matchers are always compiled in to the impl file
- _THROWS_WITH macros are still available with matchers disabled - but only the ones that take a string
- tests that use matchers have #ifdefs, so the whole SelfTest project can compile with matchers disable.
This commit is contained in:
Phil Nash 2017-08-09 12:10:14 +01:00
parent b59e0ed48a
commit ee9b19efd3
18 changed files with 143 additions and 105 deletions

View File

@ -126,6 +126,7 @@ set(INTERNAL_HEADERS
${HEADER_DIR}/internal/catch_assertioninfo.h
${HEADER_DIR}/internal/catch_assertionresult.h
${HEADER_DIR}/internal/catch_capture.hpp
${HEADER_DIR}/internal/catch_capture_matchers.h
${HEADER_DIR}/internal/catch_clara.h
${HEADER_DIR}/internal/catch_commandline.hpp
${HEADER_DIR}/internal/catch_common.h
@ -201,6 +202,7 @@ set(IMPL_SOURCES
${HEADER_DIR}/internal/catch_assertionhandler.cpp
${HEADER_DIR}/internal/catch_assertionresult.cpp
${HEADER_DIR}/internal/catch_benchmark.cpp
${HEADER_DIR}/internal/catch_capture_matchers.cpp
${HEADER_DIR}/internal/catch_commandline.cpp
${HEADER_DIR}/internal/catch_common.cpp
${HEADER_DIR}/internal/catch_config.cpp

View File

@ -41,6 +41,10 @@
#include "internal/catch_compiler_capabilities.h"
#include "internal/catch_interfaces_tag_alias_registry.h"
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
#include "internal/catch_capture_matchers.h"
#endif
// These files are included here so the single_include script doesn't put them
// in the conditionally compiled sections
#include "internal/catch_test_case_info.h"
@ -72,8 +76,8 @@
#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ )
#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
#endif// CATCH_CONFIG_DISABLE_MATCHERS
#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
@ -86,8 +90,8 @@
#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ )
#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
@ -134,8 +138,8 @@
#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
@ -148,8 +152,8 @@
#define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )

View File

@ -14,7 +14,7 @@
#include "catch_context.h"
#include "catch_debugger.h"
#include "catch_interfaces_registry_hub.h"
#include "catch_matchers_string.h"
#include "catch_capture_matchers.h"
#include <cassert>
@ -138,12 +138,8 @@ namespace Catch {
m_inExceptionGuard = false;
}
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) {
MatchExpr<std::string, StringMatcher const&> expr( Catch::translateActiveException(), matcher, matcherString );
handler.handle( expr );
}
// This is the overload that takes a string and infers the Equals matcher from it
// The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ) {
handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );
}

View File

@ -10,7 +10,6 @@
#include "catch_decomposer.h"
#include "catch_assertioninfo.h"
#include "catch_matchers_string.h" // !TBD: for exception matchers
namespace Catch {
@ -67,9 +66,6 @@ namespace Catch {
void unsetExceptionGuard();
};
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString );
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString );
} // namespace Catch

View File

@ -134,18 +134,8 @@
#define INTERNAL_CATCH_INFO( macroName, log ) \
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
INTERNAL_CATCH_TRY( catchAssertionHandler ) { \
catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
///////////////////////////////////////////////////////////////////////////////
// Although this is matcher-based, it can be used with just a string
#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #matcher, resultDisposition ); \
@ -163,26 +153,4 @@
} while( Catch::alwaysFalse() )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #exceptionType ", " #matcher, resultDisposition ); \
if( catchAssertionHandler.allowThrows() ) \
try { \
static_cast<void>(__VA_ARGS__ ); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
} \
catch( exceptionType const& ex ) { \
catchAssertionHandler.handle( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \
} \
catch( ... ) { \
catchAssertionHandler.useActiveException(); \
} \
else \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED

View File

@ -0,0 +1,23 @@
/*
* Created by Phil on 9/8/2017.
* Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
*
* 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_capture_matchers.h"
#include "catch_interfaces_registry_hub.h"
namespace Catch {
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
// This is the general overload that takes a any string matcher
// There is another overload, in catch_assertinhandler.h/.cpp, that only takes a string and infers
// the Equals matcher (so the header does not mention matchers)
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) {
MatchExpr<std::string, StringMatcher const&> expr( Catch::translateActiveException(), matcher, matcherString );
handler.handle( expr );
}
} // namespace Catch

View File

@ -0,0 +1,87 @@
/*
* Created by Phil on 9/8/2017
* Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
*
* 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_CAPTURE_MATCHERS_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED
#include "catch_capture.hpp"
#include "catch_matchers.hpp"
#include "catch_matchers_string.h"
namespace Catch {
template<typename ArgT, typename MatcherT>
class MatchExpr : public ITransientExpression {
ArgT const& m_arg;
MatcherT m_matcher;
StringRef m_matcherString;
bool m_result;
public:
MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString )
: m_arg( arg ),
m_matcher( matcher ),
m_matcherString( matcherString ),
m_result( matcher.match( arg ) )
{}
auto isBinaryExpression() const -> bool override { return true; }
auto getResult() const -> bool override { return m_result; }
void streamReconstructedExpression( std::ostream &os ) const override {
auto matcherAsString = m_matcher.toString();
os << Catch::Detail::stringify( m_arg ) << ' ';
if( matcherAsString == Detail::unprintableString )
os << m_matcherString.c_str();
else
os << matcherAsString;
}
};
using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString );
template<typename ArgT, typename MatcherT>
auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr<ArgT, MatcherT> {
return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
}
} // namespace Catch
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
INTERNAL_CATCH_TRY( catchAssertionHandler ) { \
catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
do { \
Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #exceptionType ", " #matcher, resultDisposition ); \
if( catchAssertionHandler.allowThrows() ) \
try { \
static_cast<void>(__VA_ARGS__ ); \
catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \
} \
catch( exceptionType const& ex ) { \
catchAssertionHandler.handle( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \
} \
catch( ... ) { \
catchAssertionHandler.useActiveException(); \
} \
else \
catchAssertionHandler.handle( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( catchAssertionHandler ) \
} while( Catch::alwaysFalse() )
#endif // TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED

View File

@ -10,7 +10,6 @@
#include "catch_tostring.h"
#include "catch_stringref.h"
#include "catch_matchers.hpp" // !TBD: for exception matchers - move this
#include <ostream>
@ -156,39 +155,6 @@ namespace Catch {
}
};
// !TBD: this is just here temporarily
template<typename ArgT, typename MatcherT>
class MatchExpr : public ITransientExpression {
ArgT const& m_arg;
MatcherT m_matcher;
StringRef m_matcherString;
bool m_result;
public:
MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString )
: m_arg( arg ),
m_matcher( matcher ),
m_matcherString( matcherString ),
m_result( matcher.match( arg ) )
{}
auto isBinaryExpression() const -> bool override { return true; }
auto getResult() const -> bool override { return m_result; }
void streamReconstructedExpression( std::ostream &os ) const override {
auto matcherAsString = m_matcher.toString();
os << Catch::Detail::stringify( m_arg ) << ' ';
if( matcherAsString == Detail::unprintableString )
os << m_matcherString.c_str();
else
os << matcherAsString;
}
};
template<typename ArgT, typename MatcherT>
auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr<ArgT, MatcherT> {
return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
}
} // end namespace Catch
#ifdef _MSC_VER

View File

@ -5,8 +5,6 @@
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#include "catch_matchers.hpp"
namespace Catch {
@ -26,5 +24,3 @@ using namespace Matchers;
using Matchers::Impl::MatcherBase;
} // namespace Catch
#endif // CATCH_CONFIG_DISABLE_MATCHERS

View File

@ -8,8 +8,6 @@
#ifndef TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#include "catch_common.h"
#include <string>
@ -182,6 +180,4 @@ using Matchers::Impl::MatcherBase;
} // namespace Catch
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED

View File

@ -6,8 +6,6 @@
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#include "catch_matchers_string.h"
#include "catch_string_manip.h"
@ -94,5 +92,3 @@ namespace Matchers {
} // namespace Matchers
} // namespace Catch
#endif // CATCH_CONFIG_DISABLE_MATCHERS

View File

@ -8,8 +8,6 @@
#ifndef TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#include "catch_matchers.hpp"
#include <string>
@ -68,6 +66,4 @@ namespace Matchers {
} // namespace Matchers
} // namespace Catch
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#endif // TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED

View File

@ -8,9 +8,6 @@
#ifndef TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
#include "catch_matchers.hpp"
namespace Catch {
@ -115,6 +112,4 @@ namespace Matchers {
} // namespace Matchers
} // namespace Catch
#endif // CATCH_CONFIG_DISABLE_MATCHERS
#endif // TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED

View File

@ -43,7 +43,9 @@ bool templated_tests(T t) {
REQUIRE_THROWS(throws_int(true));
CHECK_THROWS_AS(throws_int(true), int);
REQUIRE_NOTHROW(throws_int(false));
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
REQUIRE_THAT("aaa", Catch::EndsWith("aaa"));
#endif
return true;
}

View File

@ -181,6 +181,8 @@ TEST_CASE( "Unexpected exceptions can be translated", "[.][failing][!throws]" )
throw double( 3.14 );
}
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
TEST_CASE( "Exception messages can be tested for", "[!throws]" ) {
using namespace Catch::Matchers;
SECTION( "exact match" )
@ -195,6 +197,8 @@ TEST_CASE( "Exception messages can be tested for", "[!throws]" ) {
}
}
#endif
TEST_CASE( "Mismatching exception messages failing the test", "[.][failing][!throws]" ) {
REQUIRE_THROWS_WITH( thisThrows(), "expected exception" );
REQUIRE_THROWS_WITH( thisThrows(), "should fail" );

View File

@ -8,6 +8,8 @@
#include "catch.hpp"
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
inline const char* testStringForMatching()
{
return "this string contains 'abc' as a substring";
@ -223,3 +225,5 @@ TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.fail
REQUIRE_THROWS_MATCHES(throws(4), SpecialException, ExceptionMatcher{ 1 });
}
}
#endif // CATCH_CONFIG_DISABLE_MATCHERS

View File

@ -11,8 +11,6 @@
TEST_CASE( "Tag alias can be registered against tag patterns" ) {
using namespace Catch::Matchers;
Catch::TagAliasRegistry registry;
registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 2 ) );
@ -24,11 +22,14 @@ TEST_CASE( "Tag alias can be registered against tag patterns" ) {
FAIL( "expected exception" );
}
catch( std::exception& ex ) {
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
std::string what = ex.what();
using namespace Catch::Matchers;
CHECK_THAT( what, Contains( "[@zzz]" ) );
CHECK_THAT( what, Contains( "file" ) );
CHECK_THAT( what, Contains( "2" ) );
CHECK_THAT( what, Contains( "10" ) );
#endif
}
}

View File

@ -47,7 +47,9 @@ inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){
TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) {
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
using namespace Catch::Matchers;
#endif
Catch::ConfigData config;
auto cli = Catch::makeCommandLineParser(config);
@ -153,7 +155,9 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
auto result = cli.parse({"test", "-x", "oops"});
CHECK(!result);
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
REQUIRE_THAT(result.errorMessage(), Contains("convert") && Contains("oops"));
#endif
}
}
@ -225,7 +229,9 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]"
SECTION( "error" ) {
auto result = cli.parse({"test", "--use-colour", "wrong"});
CHECK( !result );
#ifndef CATCH_CONFIG_DISABLE_MATCHERS
CHECK_THAT( result.errorMessage(), Contains( "colour mode must be one of" ) );
#endif
}
}
}