mirror of
https://github.com/catchorg/Catch2.git
synced 2025-07-04 16:45:32 +02:00
Lazily stringify expressions (closes #556)
This commit is contained in:
parent
981347b6e4
commit
ebf172be0b
@ -133,7 +133,7 @@
|
||||
try { \
|
||||
std::string matcherAsString = (matcher).toString(); \
|
||||
__catchResult \
|
||||
.setLhs( Catch::toString( arg ) ) \
|
||||
.setLhs( arg ) \
|
||||
.setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
|
||||
.setOp( "matches" ) \
|
||||
.setResultType( (matcher).match( arg ) ); \
|
||||
|
@ -71,7 +71,7 @@ public:
|
||||
void endExpression() {
|
||||
bool value = m_lhs ? true : false;
|
||||
m_rb
|
||||
.setLhs( Catch::toString( value ) )
|
||||
.setLhs( value )
|
||||
.setResultType( value )
|
||||
.endExpression();
|
||||
}
|
||||
@ -90,8 +90,8 @@ private:
|
||||
ResultBuilder& captureExpression( RhsT const& rhs ) {
|
||||
return m_rb
|
||||
.setResultType( Internal::compare<Op>( m_lhs, rhs ) )
|
||||
.setLhs( Catch::toString( m_lhs ) )
|
||||
.setRhs( Catch::toString( rhs ) )
|
||||
.setLhs( m_lhs )
|
||||
.setRhs( rhs )
|
||||
.setOp( Internal::OperatorTraits<Op>::getName() );
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "catch_assertionresult.h"
|
||||
#include "catch_common.h"
|
||||
#include "catch_matchers.hpp"
|
||||
#include "catch_tostring.h"
|
||||
|
||||
namespace Catch {
|
||||
|
||||
@ -34,6 +35,17 @@ namespace Catch {
|
||||
std::ostringstream oss;
|
||||
};
|
||||
|
||||
struct AnyTypeHolderBase {
|
||||
virtual std::string toString() = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct AnyTypeHolder : AnyTypeHolderBase {
|
||||
AnyTypeHolder( const T& value ) : value ( value ) {}
|
||||
std::string toString() { return Catch::toString( value ); }
|
||||
T value;
|
||||
};
|
||||
|
||||
class ResultBuilder {
|
||||
public:
|
||||
ResultBuilder( char const* macroName,
|
||||
@ -57,8 +69,10 @@ namespace Catch {
|
||||
|
||||
ResultBuilder& setResultType( ResultWas::OfType result );
|
||||
ResultBuilder& setResultType( bool result );
|
||||
ResultBuilder& setLhs( std::string const& lhs );
|
||||
ResultBuilder& setRhs( std::string const& rhs );
|
||||
template <typename T>
|
||||
ResultBuilder& setLhs( T const& lhs );
|
||||
template <typename T>
|
||||
ResultBuilder& setRhs( T const& rhs );
|
||||
ResultBuilder& setOp( std::string const& op );
|
||||
|
||||
void endExpression();
|
||||
@ -80,9 +94,11 @@ namespace Catch {
|
||||
AssertionInfo m_assertionInfo;
|
||||
AssertionResultData m_data;
|
||||
struct ExprComponents {
|
||||
ExprComponents() : testFalse( false ) {}
|
||||
ExprComponents() : testFalse( false ), lhs( NULL ), rhs( NULL ) {}
|
||||
~ExprComponents() { delete lhs; delete rhs; }
|
||||
bool testFalse;
|
||||
std::string lhs, rhs, op;
|
||||
std::string op;
|
||||
AnyTypeHolderBase* lhs, *rhs;
|
||||
} m_exprComponents;
|
||||
CopyableStream m_stream;
|
||||
|
||||
|
@ -41,12 +41,14 @@ namespace Catch {
|
||||
m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
|
||||
return *this;
|
||||
}
|
||||
ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) {
|
||||
m_exprComponents.lhs = lhs;
|
||||
template <typename T>
|
||||
ResultBuilder& ResultBuilder::setLhs( T const& lhs ) {
|
||||
m_exprComponents.lhs = new AnyTypeHolder<T>( lhs );
|
||||
return *this;
|
||||
}
|
||||
ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) {
|
||||
m_exprComponents.rhs = rhs;
|
||||
template <typename T>
|
||||
ResultBuilder& ResultBuilder::setRhs( T const& rhs ) {
|
||||
m_exprComponents.rhs = new AnyTypeHolder<T>( rhs );
|
||||
return *this;
|
||||
}
|
||||
ResultBuilder& ResultBuilder::setOp( std::string const& op ) {
|
||||
@ -130,6 +132,7 @@ namespace Catch {
|
||||
}
|
||||
|
||||
data.message = m_stream.oss.str();
|
||||
if( data.resultType == ResultWas::ExpressionFailed ) {
|
||||
data.reconstructedExpression = reconstructExpression();
|
||||
if( m_exprComponents.testFalse ) {
|
||||
if( m_exprComponents.op == "" )
|
||||
@ -137,20 +140,23 @@ namespace Catch {
|
||||
else
|
||||
data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
|
||||
}
|
||||
}
|
||||
return AssertionResult( m_assertionInfo, data );
|
||||
}
|
||||
std::string ResultBuilder::reconstructExpression() const {
|
||||
std::string lhs = m_exprComponents.lhs->toString(),
|
||||
rhs = m_exprComponents.rhs->toString();
|
||||
if( m_exprComponents.op == "" )
|
||||
return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
|
||||
return lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + lhs;
|
||||
else if( m_exprComponents.op == "matches" )
|
||||
return m_exprComponents.lhs + " " + m_exprComponents.rhs;
|
||||
return lhs + " " + rhs;
|
||||
else if( m_exprComponents.op != "!" ) {
|
||||
if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
|
||||
m_exprComponents.lhs.find("\n") == std::string::npos &&
|
||||
m_exprComponents.rhs.find("\n") == std::string::npos )
|
||||
return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
|
||||
if( lhs.size() + rhs.size() < 40 &&
|
||||
lhs.find("\n") == std::string::npos &&
|
||||
rhs.find("\n") == std::string::npos )
|
||||
return lhs + " " + m_exprComponents.op + " " + rhs;
|
||||
else
|
||||
return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
|
||||
return lhs + "\n" + m_exprComponents.op + "\n" + rhs;
|
||||
}
|
||||
else
|
||||
return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}";
|
||||
|
Loading…
x
Reference in New Issue
Block a user