diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index cf2f4220..48164836 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -39,7 +39,8 @@ public: return ResultInfoBuilder() .setResultType( ResultWas::Info ) .setMessage( m_oss.str() ) - .setMacroName( "SCOPED_INFO" ); + .setMacroName( "SCOPED_INFO" ) + .build(); } private: diff --git a/include/internal/catch_expression.hpp b/include/internal/catch_expression.hpp index ad78a909..61c6f702 100644 --- a/include/internal/catch_expression.hpp +++ b/include/internal/catch_expression.hpp @@ -25,44 +25,44 @@ public: template ResultInfoBuilder& operator == ( const RhsT& rhs ) { - return m_result.captureExpression( m_lhs, rhs ); + return captureExpression( m_result, m_lhs, rhs ); } - + template ResultInfoBuilder& operator != ( const RhsT& rhs ) { - return m_result.captureExpression( m_lhs, rhs ); + return captureExpression( m_result, m_lhs, rhs ); } template ResultInfoBuilder& operator < ( const RhsT& rhs ) { - return m_result.captureExpression( m_lhs, rhs ); + return captureExpression( m_result, m_lhs, rhs ); } template ResultInfoBuilder& operator > ( const RhsT& rhs ) { - return m_result.captureExpression( m_lhs, rhs ); + return captureExpression( m_result, m_lhs, rhs ); } template ResultInfoBuilder& operator <= ( const RhsT& rhs ) { - return m_result.captureExpression( m_lhs, rhs ); + return captureExpression( m_result, m_lhs, rhs ); } template ResultInfoBuilder& operator >= ( const RhsT& rhs ) { - return m_result.captureExpression( m_lhs, rhs ); + return captureExpression( m_result, m_lhs, rhs ); } ResultInfoBuilder& operator == ( bool rhs ) { - return m_result.captureExpression( m_lhs, rhs ); + return captureExpression( m_result, m_lhs, rhs ); } ResultInfoBuilder& operator != ( bool rhs ) { - return m_result.captureExpression( m_lhs, rhs ); + return captureExpression( m_result, m_lhs, rhs ); } operator ResultInfoBuilder& () { - return m_result.captureBoolExpression( m_lhs ); + return captureBoolExpression( m_result, m_lhs ); } template diff --git a/include/internal/catch_expression_builder.hpp b/include/internal/catch_expression_builder.hpp index 1f8487f8..1082fb91 100644 --- a/include/internal/catch_expression_builder.hpp +++ b/include/internal/catch_expression_builder.hpp @@ -26,9 +26,14 @@ public: const char* macroName, const char* expr = "", bool isNot = false ) - : m_result( expr, isNot, lineInfo, macroName ), - m_messageStream() - {} + : m_messageStream() + { + m_result + .setCapturedExpression( expr ) + .setIsFalse( isNot ) + .setLineInfo( lineInfo ) + .setMacroName( macroName ); + } template Expression operator->* ( const T & operand ) { @@ -54,10 +59,11 @@ public: 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 ); + m_result + .setLhs( Catch::toString( arg ) ) + .setRhs( matcherAsString ) + .setOp( "matches" ) + .setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed ); return *this; } @@ -68,10 +74,11 @@ public: 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 ); + m_result + .setLhs( Catch::toString( arg ) ) + .setRhs( matcherAsString ) + .setOp( "matches" ) + .setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed ); return *this; } diff --git a/include/internal/catch_result_type.h b/include/internal/catch_result_type.h index 6f61f8c0..e151f070 100644 --- a/include/internal/catch_result_type.h +++ b/include/internal/catch_result_type.h @@ -28,6 +28,10 @@ struct ResultWas { enum OfType { }; }; +inline bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; +} + struct ResultAction { enum Value { None, Failed = 1, // Failure - but no debug break if Debug bit not set diff --git a/include/internal/catch_resultinfo.h b/include/internal/catch_resultinfo.h index 8bcc8c0c..4ef6beba 100644 --- a/include/internal/catch_resultinfo.h +++ b/include/internal/catch_resultinfo.h @@ -13,9 +13,22 @@ namespace Catch { + struct ResultData + { + ResultData() : resultType( ResultWas::Unknown ) {} + + std::string macroName; + SourceLineInfo lineInfo; + std::string capturedExpression; + std::string reconstructedExpression; + std::string message; + ResultWas::OfType resultType; + }; + class ResultInfo { public: - ResultInfo(); + ResultInfo(); + ResultInfo( const ResultData& data ); ~ResultInfo(); bool ok() const; @@ -42,6 +55,7 @@ namespace Catch { bool isNotExpression( const char* expr ); protected: + ResultData m_data; std::string m_macroName; SourceLineInfo m_lineInfo; std::string m_expr, m_lhs, m_rhs, m_op; diff --git a/include/internal/catch_resultinfo.hpp b/include/internal/catch_resultinfo.hpp index 8ad48ee5..52c9b816 100644 --- a/include/internal/catch_resultinfo.hpp +++ b/include/internal/catch_resultinfo.hpp @@ -23,6 +23,8 @@ namespace Catch { m_isNot( false ) {} + ResultInfo::ResultInfo( const ResultData& data ) : m_data( data ) {} + ResultInfo::ResultInfo(const char* expr, ResultWas::OfType result, bool isNot, diff --git a/include/internal/catch_resultinfo_builder.h b/include/internal/catch_resultinfo_builder.h index 70082aef..28d6e671 100644 --- a/include/internal/catch_resultinfo_builder.h +++ b/include/internal/catch_resultinfo_builder.h @@ -18,54 +18,56 @@ namespace Catch { struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; -class ResultInfoBuilder : public ResultInfo { +class ResultInfoBuilder : protected ResultInfo { public: - ResultInfoBuilder(); + ResultInfoBuilder(); ResultInfoBuilder& setResultType( ResultWas::OfType result ); + ResultInfoBuilder& setCapturedExpression( const std::string& capturedExpression ); + ResultInfoBuilder& setIsFalse( bool isFalse ); ResultInfoBuilder& setMessage( const std::string& message ); ResultInfoBuilder& setLineInfo( const SourceLineInfo& lineInfo ); ResultInfoBuilder& setLhs( const std::string& lhs ); ResultInfoBuilder& setRhs( const std::string& rhs ); ResultInfoBuilder& setOp( const std::string& op ); ResultInfoBuilder& setMacroName( const std::string& macroName ); - + + std::string reconstructExpression() const; + + const ResultInfo& build() const; + + // Disable attempts to use || and && in expressions (without parantheses) template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( const RhsT& ); - template STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( const RhsT& ); - -private: - ResultInfoBuilder( const char* expr, - bool isNot, - const SourceLineInfo& lineInfo, - const char* macroName ); - - friend class ExpressionBuilder; - template friend class Expression; - - template friend class PtrExpression; - - ResultInfoBuilder& captureBoolExpression( bool result ); - - template - ResultInfoBuilder& captureExpression( const T1& lhs, const T2& rhs ) { - setResultType( Internal::compare( lhs, rhs ) ? ResultWas::Ok : ResultWas::ExpressionFailed ); - m_lhs = Catch::toString( lhs ); - m_rhs = Catch::toString( rhs ); - m_op = Internal::OperatorTraits::getName(); - return *this; + bool getIsFalse() const { + return m_isNot; } - template - ResultInfoBuilder& captureExpression( const T* lhs, int rhs ) { - return captureExpression( lhs, reinterpret_cast( rhs ) ); - } +private: + ResultData m_data; }; +template +ResultInfoBuilder& captureExpression( ResultInfoBuilder& builder, const T1& lhs, const T2& rhs ) { + return builder + .setResultType( Internal::compare( lhs, rhs ) ? ResultWas::Ok : ResultWas::ExpressionFailed ) + .setLhs( Catch::toString( lhs ) ) + .setRhs( Catch::toString( rhs ) ) + .setOp( Internal::OperatorTraits::getName() ); +} + +template +ResultInfoBuilder& captureExpression( ResultInfoBuilder& builder, const T* lhs, int rhs ) { + return captureExpression( builder, lhs, reinterpret_cast( rhs ) ); +} + +ResultInfoBuilder& captureBoolExpression( ResultInfoBuilder& builder, bool result ); + + } // end namespace Catch #endif // TWOBLUECUBES_CATCH_RESULTINFO_BUILDER_H_INCLUDED diff --git a/include/internal/catch_resultinfo_builder.hpp b/include/internal/catch_resultinfo_builder.hpp index 1421f520..d75e2c22 100644 --- a/include/internal/catch_resultinfo_builder.hpp +++ b/include/internal/catch_resultinfo_builder.hpp @@ -12,13 +12,6 @@ namespace Catch { - ResultInfoBuilder::ResultInfoBuilder( const char* expr, - bool isNot, - const SourceLineInfo& lineInfo, - const char* macroName ) - : ResultInfo( expr, ResultWas::Unknown, isNot, lineInfo, macroName, "" ) - {} - ResultInfoBuilder::ResultInfoBuilder() {} ResultInfoBuilder& ResultInfoBuilder::setResultType( ResultWas::OfType result ) { @@ -29,16 +22,34 @@ namespace Catch { m_result = ResultWas::Ok; else m_result = result; + m_data.resultType = m_result; + return *this; + } + ResultInfoBuilder& ResultInfoBuilder::setCapturedExpression( const std::string& capturedExpression ) { + m_expr = capturedExpression; + m_data.capturedExpression = capturedExpression; + return *this; + } + ResultInfoBuilder& ResultInfoBuilder::setIsFalse( bool isFalse ) { + m_isNot = isFalse; return *this; } ResultInfoBuilder& ResultInfoBuilder::setMessage( const std::string& message ) { m_message = message; + m_data.message = message; return *this; } ResultInfoBuilder& ResultInfoBuilder::setLineInfo( const SourceLineInfo& lineInfo ) { m_lineInfo = lineInfo; + m_data.lineInfo = lineInfo; + return *this; + } + + ResultInfoBuilder& ResultInfoBuilder::setMacroName( const std::string& macroName ) { + m_macroName = macroName; + m_data.macroName = macroName; return *this; } @@ -57,18 +68,38 @@ namespace Catch { return *this; } - ResultInfoBuilder& ResultInfoBuilder::setMacroName( const std::string& macroName ) { - m_macroName = macroName; + ResultInfoBuilder& captureBoolExpression( ResultInfoBuilder& builder, bool result ) { + return builder + .setLhs( Catch::toString( result ) ) + .setOp( builder.getIsFalse() ? "!" : "" ) + .setResultType( result ? ResultWas::Ok : ResultWas::ExpressionFailed ); + } + + const ResultInfo& ResultInfoBuilder::build() const + { + ResultData data = m_data; + data.reconstructedExpression = reconstructExpression(); return *this; } - ResultInfoBuilder& ResultInfoBuilder::captureBoolExpression( bool result ) { - m_lhs = Catch::toString( result ); - m_op = m_isNot ? "!" : ""; - setResultType( result ? ResultWas::Ok : ResultWas::ExpressionFailed ); - return *this; + std::string ResultInfoBuilder::reconstructExpression() const { + if( m_op == "" || m_isNot ) + return m_lhs.empty() ? m_expr : 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; + else + return "\n" + m_lhs + "\n" + m_op + "\n" + m_rhs + "\n\n"; + } + else + return "{can't expand - use " + m_data.macroName + "_FALSE( " + m_expr.substr(1) + " ) instead of " + m_data.macroName + "( " + m_expr + " ) for better diagnostics}"; } - + } // end namespace Catch #endif // TWOBLUECUBES_CATCH_RESULTINFO_BUILDER_HPP_INCLUDED diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index c144414d..ef446c3a 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -242,9 +242,9 @@ namespace Catch { private: ResultAction::Value actOnCurrentResult() { - testEnded( m_currentResult ); - m_lastResult = m_currentResult; - + m_lastResult = m_currentResult.build(); + testEnded( m_lastResult ); + m_currentResult = ResultInfoBuilder(); ResultAction::Value action = ResultAction::None;