mirror of https://github.com/catchorg/Catch2.git
First cut of Matcher support
This commit is contained in:
parent
5ff4ab0a76
commit
eca5637c58
|
@ -60,6 +60,9 @@
|
||||||
#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" )
|
#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" )
|
||||||
#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CHECK_NOTHROW" )
|
#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CHECK_NOTHROW" )
|
||||||
|
|
||||||
|
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, false, "CHECK_THAT" )
|
||||||
|
#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, true, "REQUIRE_THAT" )
|
||||||
|
|
||||||
#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" )
|
#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" )
|
||||||
#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" )
|
#define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" )
|
||||||
#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
|
#define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
|
||||||
|
|
|
@ -266,6 +266,33 @@ public:
|
||||||
m_line = line;
|
m_line = line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
void setLhs
|
||||||
|
(
|
||||||
|
const std::string& lhs
|
||||||
|
)
|
||||||
|
{
|
||||||
|
m_lhs = lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
void setRhs
|
||||||
|
(
|
||||||
|
const std::string& rhs
|
||||||
|
)
|
||||||
|
{
|
||||||
|
m_rhs = rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
void setOp
|
||||||
|
(
|
||||||
|
const std::string& op
|
||||||
|
)
|
||||||
|
{
|
||||||
|
m_op = op;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template<typename RhsT>
|
template<typename RhsT>
|
||||||
STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator ||
|
STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator ||
|
||||||
|
@ -513,6 +540,7 @@ private:
|
||||||
MutableResultInfo* m_result;
|
MutableResultInfo* m_result;
|
||||||
const LhsT* m_lhs;
|
const LhsT* m_lhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ResultBuilder
|
class ResultBuilder
|
||||||
{
|
{
|
||||||
|
@ -599,6 +627,25 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
template<typename MatcherT, typename ArgT>
|
||||||
|
ResultBuilder& acceptMatcher
|
||||||
|
(
|
||||||
|
const MatcherT& matcher,
|
||||||
|
const ArgT& arg,
|
||||||
|
const std::string& matcherCallAsString
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::string matcherAsString = Catch::toString( matcher );
|
||||||
|
if( matcherAsString == "{?}" )
|
||||||
|
matcherAsString = matcherCallAsString;
|
||||||
|
m_result.setLhs( Catch::toString( arg ) );
|
||||||
|
m_result.setRhs( matcherAsString );
|
||||||
|
m_result.setOp( "matches" );
|
||||||
|
m_result.setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
ResultBuilder& setResultType
|
ResultBuilder& setResultType
|
||||||
(
|
(
|
||||||
|
@ -749,4 +796,15 @@ inline bool isTrue
|
||||||
Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
|
Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
|
||||||
INTERNAL_CATCH_UNIQUE_NAME( info ) << log
|
INTERNAL_CATCH_UNIQUE_NAME( info ) << log
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
#define INTERNAL_CHECK_THAT( arg, matcher, stopOnFailure, macroName ) \
|
||||||
|
do{ try{ \
|
||||||
|
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #arg " " #matcher, false ).acceptMatcher( matcher, arg, #matcher ) ), stopOnFailure ); \
|
||||||
|
}catch( Catch::TestFailureException& ){ \
|
||||||
|
throw; \
|
||||||
|
} catch( ... ){ \
|
||||||
|
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #arg " " #matcher ) << Catch::Hub::getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false ); \
|
||||||
|
throw; \
|
||||||
|
}}while( Catch::isTrue( false ) )
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
|
||||||
|
|
|
@ -51,8 +51,8 @@ namespace Catch
|
||||||
m_filename( filename ),
|
m_filename( filename ),
|
||||||
m_line( line ),
|
m_line( line ),
|
||||||
m_expr( expr ),
|
m_expr( expr ),
|
||||||
m_lhs(),
|
m_lhs(),
|
||||||
m_rhs(),
|
m_rhs(),
|
||||||
m_op( isNotExpression( expr ) ? "!" : "" ),
|
m_op( isNotExpression( expr ) ? "!" : "" ),
|
||||||
m_message( message ),
|
m_message( message ),
|
||||||
m_result( result ),
|
m_result( result ),
|
||||||
|
@ -157,6 +157,8 @@ namespace Catch
|
||||||
{
|
{
|
||||||
if( m_op == "" || m_isNot )
|
if( m_op == "" || m_isNot )
|
||||||
return m_lhs.empty() ? m_expr : m_op + m_lhs;
|
return m_lhs.empty() ? m_expr : m_op + m_lhs;
|
||||||
|
else if( m_op == "matches" )
|
||||||
|
return m_lhs + " " + m_rhs;
|
||||||
else if( m_op != "!" )
|
else if( m_op != "!" )
|
||||||
return m_lhs + " " + m_op + " " + m_rhs;
|
return m_lhs + " " + m_op + " " + m_rhs;
|
||||||
else
|
else
|
||||||
|
|
|
@ -118,8 +118,8 @@ namespace Catch
|
||||||
{
|
{
|
||||||
TextColour colour( TextColour::ResultSuccess );
|
TextColour colour( TextColour::ResultSuccess );
|
||||||
m_config.stream() << "All tests passed ("
|
m_config.stream() << "All tests passed ("
|
||||||
<< pluralise( totals.assertions.passed, "assertion" ) << " in "
|
<< pluralise( totals.assertions.passed, "assertion" ) << " in "
|
||||||
<< pluralise( totals.testCases.passed, "test case" ) << ")";
|
<< pluralise( totals.testCases.passed, "test case" ) << ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ namespace Catch
|
||||||
SpanInfo& sectionSpan = m_sectionSpans.back();
|
SpanInfo& sectionSpan = m_sectionSpans.back();
|
||||||
if( sectionSpan.emitted && !sectionSpan.name.empty() )
|
if( sectionSpan.emitted && !sectionSpan.name.empty() )
|
||||||
{
|
{
|
||||||
m_config.stream() << "[End of section: '" << sectionName << "'";
|
m_config.stream() << "[End of section: '" << sectionName << "' ";
|
||||||
|
|
||||||
if( assertions.failed )
|
if( assertions.failed )
|
||||||
{
|
{
|
||||||
|
@ -217,7 +217,7 @@ namespace Catch
|
||||||
{
|
{
|
||||||
TextColour colour( TextColour::ResultSuccess );
|
TextColour colour( TextColour::ResultSuccess );
|
||||||
m_config.stream() << ( assertions.passed > 1 ? "All " : "" )
|
m_config.stream() << ( assertions.passed > 1 ? "All " : "" )
|
||||||
<< pluralise( assertions.passed, "assertion" ) << "passed" ;
|
<< pluralise( assertions.passed, "assertion" ) << "passed" ;
|
||||||
}
|
}
|
||||||
m_config.stream() << "]\n" << std::endl;
|
m_config.stream() << "]\n" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,3 +185,34 @@ TEST_CASE("./succeeding/atomic if", "")
|
||||||
else
|
else
|
||||||
REQUIRE(x == 0);
|
REQUIRE(x == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Matchers
|
||||||
|
{
|
||||||
|
struct ContainsStdString
|
||||||
|
{
|
||||||
|
ContainsStdString( const std::string& substr ) : m_substr( substr ){}
|
||||||
|
|
||||||
|
bool operator()( const std::string& str ) const
|
||||||
|
{
|
||||||
|
return str.find( m_substr ) != std::string::npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::ostream& operator<<( std::ostream& os, const ContainsStdString& matcher )
|
||||||
|
{
|
||||||
|
os << "contains: \"" << matcher.m_substr << "\"";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
std::string m_substr;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Matchers::ContainsStdString Contains( const std::string& substr ){ return Matchers::ContainsStdString( substr ); }
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("./succeeding/matcher", "")
|
||||||
|
{
|
||||||
|
const char* actualStr = "this string contains 'abc' as a substring";
|
||||||
|
REQUIRE_THAT( actualStr, Contains( "string" ) );
|
||||||
|
CHECK_THAT( actualStr, Contains( "not there" ) );
|
||||||
|
CHECK_THAT( actualStr, Contains( "a2bc" ) );
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue