diff --git a/include/internal/catch_assertionresult_builder.h b/include/internal/catch_assertionresult_builder.h index 8987242c..3ef2f5fd 100644 --- a/include/internal/catch_assertionresult_builder.h +++ b/include/internal/catch_assertionresult_builder.h @@ -22,17 +22,24 @@ class AssertionResultBuilder { public: AssertionResultBuilder(); + AssertionResultBuilder( const AssertionResultBuilder& other ); + AssertionResultBuilder& operator=(const AssertionResultBuilder& other ); AssertionResultBuilder& setResultType( ResultWas::OfType result ); AssertionResultBuilder& setCapturedExpression( const std::string& capturedExpression ); AssertionResultBuilder& setIsFalse( bool isFalse ); - AssertionResultBuilder& setMessage( const std::string& message ); AssertionResultBuilder& setLineInfo( const SourceLineInfo& lineInfo ); AssertionResultBuilder& setLhs( const std::string& lhs ); AssertionResultBuilder& setRhs( const std::string& rhs ); AssertionResultBuilder& setOp( const std::string& op ); AssertionResultBuilder& setMacroName( const std::string& macroName ); + template + AssertionResultBuilder& operator << ( const T& value ) { + m_stream << value; + return *this; + } + std::string reconstructExpression() const; AssertionResult build() const; @@ -43,14 +50,14 @@ public: template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( const RhsT& ); - bool getIsFalse() const { - return m_isFalse; - } - private: AssertionResultData m_data; - std::string m_lhs, m_rhs, m_op; - bool m_isFalse; + struct ExprComponents { + ExprComponents() : isFalse( false ) {} + bool isFalse; + std::string lhs, rhs, op; + } m_exprComponents; + std::ostringstream m_stream; }; } // end namespace Catch diff --git a/include/internal/catch_assertionresult_builder.hpp b/include/internal/catch_assertionresult_builder.hpp index 1c34b918..dce5af7e 100644 --- a/include/internal/catch_assertionresult_builder.hpp +++ b/include/internal/catch_assertionresult_builder.hpp @@ -13,12 +13,26 @@ namespace Catch { AssertionResultBuilder::AssertionResultBuilder() {} + AssertionResultBuilder::AssertionResultBuilder( const AssertionResultBuilder& other ) + : m_data( other.m_data ), + m_exprComponents( other.m_exprComponents ) + { + m_stream << other.m_stream.str(); + } + + AssertionResultBuilder& AssertionResultBuilder::operator=(const AssertionResultBuilder& other ) { + m_data = other.m_data; + m_exprComponents = other.m_exprComponents; + m_stream.clear(); + m_stream << other.m_stream.str(); + return *this; + } AssertionResultBuilder& AssertionResultBuilder::setResultType( ResultWas::OfType result ) { // Flip bool results if isFalse is set - if( m_isFalse && result == ResultWas::Ok ) + if( m_exprComponents.isFalse && result == ResultWas::Ok ) m_data.resultType = ResultWas::ExpressionFailed; - else if( m_isFalse && result == ResultWas::ExpressionFailed ) + else if( m_exprComponents.isFalse && result == ResultWas::ExpressionFailed ) m_data.resultType = ResultWas::Ok; else m_data.resultType = result; @@ -29,12 +43,7 @@ namespace Catch { return *this; } AssertionResultBuilder& AssertionResultBuilder::setIsFalse( bool isFalse ) { - m_isFalse = isFalse; - return *this; - } - - AssertionResultBuilder& AssertionResultBuilder::setMessage( const std::string& message ) { - m_data.message = message; + m_exprComponents.isFalse = isFalse; return *this; } @@ -49,26 +58,27 @@ namespace Catch { } AssertionResultBuilder& AssertionResultBuilder::setLhs( const std::string& lhs ) { - m_lhs = lhs; + m_exprComponents.lhs = lhs; return *this; } AssertionResultBuilder& AssertionResultBuilder::setRhs( const std::string& rhs ) { - m_rhs = rhs; + m_exprComponents.rhs = rhs; return *this; } AssertionResultBuilder& AssertionResultBuilder::setOp( const std::string& op ) { - m_op = op; + m_exprComponents.op = op; return *this; } AssertionResult AssertionResultBuilder::build() const { AssertionResultData data = m_data; + data.message = m_stream.str(); data.reconstructedExpression = reconstructExpression(); - if( m_isFalse ) { - if( m_op == "" ) { + if( m_exprComponents.isFalse ) { + if( m_exprComponents.op == "" ) { data.capturedExpression = "!" + data.capturedExpression; data.reconstructedExpression = "!" + data.reconstructedExpression; } @@ -81,17 +91,17 @@ namespace Catch { } std::string AssertionResultBuilder::reconstructExpression() const { - if( m_op == "" ) - return m_lhs.empty() ? m_data.capturedExpression : m_op + m_lhs; - else if( m_op == "matches" ) - return m_lhs + " " + m_rhs; - else if( m_op != "!" ) { - if( m_lhs.size() + m_rhs.size() < 30 ) - return m_lhs + " " + m_op + " " + m_rhs; - else if( m_lhs.size() < 70 && m_rhs.size() < 70 ) - return "\n\t" + m_lhs + "\n\t" + m_op + "\n\t" + m_rhs; + if( m_exprComponents.op == "" ) + return m_exprComponents.lhs.empty() ? m_data.capturedExpression : m_exprComponents.op + m_exprComponents.lhs; + else if( m_exprComponents.op == "matches" ) + return m_exprComponents.lhs + " " + m_exprComponents.rhs; + else if( m_exprComponents.op != "!" ) { + if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 30 ) + return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs; + else if( m_exprComponents.lhs.size() < 70 && m_exprComponents.rhs.size() < 70 ) + return "\n\t" + m_exprComponents.lhs + "\n\t" + m_exprComponents.op + "\n\t" + m_exprComponents.rhs; else - return "\n" + m_lhs + "\n" + m_op + "\n" + m_rhs + "\n\n"; + return "\n" + m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs + "\n\n"; } else return "{can't expand - use " + m_data.macroName + "_FALSE( " + m_data.capturedExpression.substr(1) + " ) instead of " + m_data.macroName + "( " + m_data.capturedExpression + " ) for better diagnostics}"; diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index d734dd0d..c43c944f 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -9,6 +9,7 @@ #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED #include "catch_expression_builder.hpp" +#include "catch_assertionresult_builder.h" #include "catch_interfaces_capture.h" #include "catch_debugger.hpp" #include "catch_context.h" @@ -22,11 +23,44 @@ namespace Catch { return getCurrentContext().getResultCapture(); } + template + AssertionResultBuilder assertionBuilderFromMatcher( const MatcherT& matcher, + const std::string& matcherCallAsString ) { + std::string matcherAsString = matcher.toString(); + if( matcherAsString == "{?}" ) + matcherAsString = matcherCallAsString; + return AssertionResultBuilder() + .setRhs( matcherAsString ) + .setOp( "matches" ); + } + + template + AssertionResultBuilder assertionBuilderFromMatcher( const MatcherT& matcher, + const ArgT& arg, + const std::string& matcherCallAsString ) { + return assertionBuilderFromMatcher( matcher, matcherCallAsString ) + .setLhs( Catch::toString( arg ) ) + .setResultType( matcher.match( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed ); + } + + template + AssertionResultBuilder assertionBuilderFromMatcher( const MatcherT& matcher, + ArgT* arg, + const std::string& matcherCallAsString ) { + return assertionBuilderFromMatcher( matcher, matcherCallAsString ) + .setLhs( Catch::toString( arg ) ) + .setResultType( matcher.match( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed ); + } + struct TestFailureException{}; class ScopedInfo { public: - ScopedInfo() : m_oss() { + ScopedInfo() { + m_resultBuilder + .setResultType( ResultWas::Info ) + .setMacroName( "SCOPED_INFO" ); + getResultCapture().pushScopedInfo( this ); } @@ -36,30 +70,27 @@ public: template ScopedInfo& operator << ( const T& value ) { - m_oss << value; + m_resultBuilder << value; return *this; } AssertionResult getInfo () const { - return AssertionResultBuilder() - .setResultType( ResultWas::Info ) - .setMessage( m_oss.str() ) - .setMacroName( "SCOPED_INFO" ) - .build(); + return m_resultBuilder.build(); } private: + AssertionResultBuilder m_resultBuilder; std::ostringstream m_oss; }; -// This is just here to avoid compiler warnings with macro constants +// This is just here to avoid compiler warnings with macro constants and boolean literals inline bool isTrue( bool value ){ return value; } } // end namespace Catch /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure, originalExpr ) \ - if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( expr ) ) { \ +#define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, stopOnFailure, originalExpr ) \ + if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr ) ) { \ if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \ if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \ if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \ @@ -74,7 +105,7 @@ inline bool isTrue( bool value ){ return value; } } catch( Catch::TestFailureException& ) { \ throw; \ } catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder() << Catch::translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, expr ); \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::AssertionResultBuilder().setResultType( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), false, expr ); \ throw; \ } } while( Catch::isTrue( false ) ) @@ -93,10 +124,10 @@ inline bool isTrue( bool value ){ return value; } try { \ Catch::getResultCapture().acceptAssertionInfo( Catch::AssertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr ) ); \ expr; \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder().setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::AssertionResultBuilder().setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \ } \ catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder() << Catch::translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::AssertionResultBuilder().setResultType( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), stopOnFailure, false ); \ } /////////////////////////////////////////////////////////////////////////////// @@ -105,26 +136,26 @@ inline bool isTrue( bool value ){ return value; } Catch::getResultCapture().acceptAssertionInfo( Catch::AssertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #expr ) ); \ if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \ expr; \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder().setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::AssertionResultBuilder().setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure, false ); \ } \ } \ catch( Catch::TestFailureException& ) { \ throw; \ } \ catch( exceptionType ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder().setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::AssertionResultBuilder().setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \ } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, stopOnFailure, macroName ) \ INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \ catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder() << Catch::getRegistryHub().getExceptionTranslatorRegistry() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::AssertionResultBuilder().setResultType( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), stopOnFailure, false ); \ } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \ - Catch::getResultCapture().acceptExpression( ( Catch::ExpressionBuilder() << reason ).setResultType( resultType ) ); + Catch::getResultCapture().acceptExpression( Catch::AssertionResultBuilder().setResultType( resultType ) << reason ); /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_SCOPED_INFO( log ) \ @@ -135,11 +166,11 @@ inline bool isTrue( bool value ){ return value; } #define INTERNAL_CHECK_THAT( arg, matcher, stopOnFailure, macroName ) \ do { try { \ Catch::getResultCapture().acceptAssertionInfo( Catch::AssertionInfo( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher ) ); \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder().acceptMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), stopOnFailure, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::assertionBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), stopOnFailure, false ); \ } catch( Catch::TestFailureException& ) { \ throw; \ } catch( ... ) { \ - INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder() << Catch::translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, false ); \ + INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::AssertionResultBuilder().setResultType( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), false, false ); \ throw; \ }}while( Catch::isTrue( false ) ) diff --git a/include/internal/catch_expression_builder.hpp b/include/internal/catch_expression_builder.hpp index 4016f9f4..deca8022 100644 --- a/include/internal/catch_expression_builder.hpp +++ b/include/internal/catch_expression_builder.hpp @@ -10,12 +10,6 @@ #include "catch_expression.hpp" #include "catch_assertionresult_builder.h" -#include "catch_tostring.hpp" -#include "catch_assertionresult.h" -#include "catch_result_type.h" -#include "catch_context.h" -#include "catch_common.h" -#include namespace Catch { @@ -23,7 +17,6 @@ class ExpressionBuilder { public: ExpressionBuilder( bool isFalse = false ) - : m_messageStream() { m_result.setIsFalse( isFalse ); } @@ -38,56 +31,9 @@ public: Expression expr( m_result, value ); return expr; } - - template - ExpressionBuilder& operator << ( const T & value ) { - m_messageStream << Catch::toString( value ); - return *this; - } - - template - ExpressionBuilder& acceptMatcher( const MatcherT& matcher, - const ArgT& arg, - const std::string& matcherCallAsString ) { - std::string matcherAsString = matcher.toString(); - if( matcherAsString == "{?}" ) - matcherAsString = matcherCallAsString; - m_result - .setLhs( Catch::toString( arg ) ) - .setRhs( matcherAsString ) - .setOp( "matches" ) - .setResultType( matcher.match( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed ); - return *this; - } - - template - ExpressionBuilder& acceptMatcher( const MatcherT& matcher, - ArgT* arg, - const std::string& matcherCallAsString ) { - std::string matcherAsString = matcher.toString(); - if( matcherAsString == "{?}" ) - matcherAsString = matcherCallAsString; - m_result - .setLhs( Catch::toString( arg ) ) - .setRhs( matcherAsString ) - .setOp( "matches" ) - .setResultType( matcher.match( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed ); - return *this; - } - - ExpressionBuilder& setResultType( ResultWas::OfType resultType ) { - m_result.setResultType( resultType ); - return *this; - } - - operator AssertionResultBuilder&() { - m_result.setMessage( m_messageStream.str() ); - return m_result; - } - + private: AssertionResultBuilder m_result; - std::ostringstream m_messageStream; }; } // end namespace Catch diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h index 4915132c..baf5b711 100644 --- a/include/internal/catch_interfaces_capture.h +++ b/include/internal/catch_interfaces_capture.h @@ -39,7 +39,6 @@ namespace Catch { virtual ResultAction::Value acceptResult( bool result ) = 0; virtual ResultAction::Value acceptResult( ResultWas::OfType result ) = 0; virtual ResultAction::Value acceptExpression( const AssertionResultBuilder& assertionResult ) = 0; - virtual void acceptMessage( const std::string& msg ) = 0; virtual std::string getCurrentTestName() const = 0; virtual const AssertionResult* getLastResult() const = 0; diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index d23bb55b..048a988b 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -148,10 +148,6 @@ namespace Catch { return actOnCurrentResult(); } - virtual void acceptMessage( const std::string& msg ) { - m_currentResult.setMessage( msg ); - } - virtual void testEnded( const AssertionResult& result ) { if( result.getResultType() == ResultWas::Ok ) { m_totals.assertions.passed++; @@ -293,8 +289,10 @@ namespace Catch { // This just means the test was aborted due to failure } catch(...) { - acceptMessage( getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() ); - acceptResult( ResultWas::ThrewException ); + m_currentResult + .setResultType( ResultWas::ThrewException ) + << translateActiveException(); + actOnCurrentResult(); } m_info.clear(); }