diff --git a/Test/TestMain.cpp b/Test/TestMain.cpp index 78b978fa..7ddcc23c 100644 --- a/Test/TestMain.cpp +++ b/Test/TestMain.cpp @@ -20,7 +20,7 @@ TEST_CASE( "selftest/main", "Runs all Catch self tests and checks their results" runner.runMatching( "./succeeding/*" ); INFO( runner.getOutput() ); - CHECK( runner.getSuccessCount() == 212 ); + CHECK( runner.getSuccessCount() == 213 ); CHECK( runner.getFailureCount() == 0 ); runner.runMatching( "./failing/*" ); diff --git a/Test/TrickyTests.cpp b/Test/TrickyTests.cpp index 69e54bb0..6078733d 100644 --- a/Test/TrickyTests.cpp +++ b/Test/TrickyTests.cpp @@ -24,7 +24,12 @@ namespace Catch } } -TEST_CASE( "./succeeding/Tricky/std::pair", "Parsing a std::pair" ) +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "./succeeding/Tricky/std::pair", + "Parsing a std::pair" +) { std::pair aNicePair( 1, 2 ); @@ -33,7 +38,12 @@ TEST_CASE( "./succeeding/Tricky/std::pair", "Parsing a std::pair" ) } -TEST_CASE( "./succeeding/Tricky/complex lhs", "Where the LHS is not a simple value" ) +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "./inprogress/succeeding/Tricky/complex lhs", + "Where the LHS is not a simple value" +) { int a = 1; int b = 2; @@ -45,13 +55,18 @@ TEST_CASE( "./succeeding/Tricky/complex lhs", "Where the LHS is not a simple val struct Opaque { int val; - bool operator ==( const Opaque& o ) + bool operator ==( const Opaque& o ) const { return val == o.val; } }; -TEST_CASE( "./failing/Tricky/non streamable type", "A failing expression with a non streamable type is still captured" ) +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "./failing/Tricky/non streamable type", + "A failing expression with a non streamable type is still captured" +) { Opaque o1, o2; @@ -61,3 +76,28 @@ TEST_CASE( "./failing/Tricky/non streamable type", "A failing expression with a CHECK( &o1 == &o2 ); CHECK( o1 == o2 ); } + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "./failing/string literals", + "string literals of different sizes can be compared" +) +{ + REQUIRE( std::string( "first" ) == "second" ); + +} + +/////////////////////////////////////////////////////////////////////////////// +TEST_CASE +( + "./succeeding/side-effects", + "An expression with side-effects should only be evaluated once" +) +{ + int i = 7; + + REQUIRE( i++ == 7 ); + REQUIRE( i++ == 8 ); + +} diff --git a/internal/catch_capture.hpp b/internal/catch_capture.hpp index 10da8901..35c84732 100644 --- a/internal/catch_capture.hpp +++ b/internal/catch_capture.hpp @@ -145,6 +145,15 @@ inline std::string toString oss << value; return oss.str(); } + +/////////////////////////////////////////////////////////////////////////////// +inline std::string toString +( + bool value +) +{ + return value ? "true" : "false"; +} class TestFailureException { @@ -169,9 +178,10 @@ public: bool isNot, const char* filename, std::size_t line, - const char* macroName + const char* macroName, + const char* message = "" ) - : ResultInfo( expr, ResultWas::Unknown, isNot, filename, line, macroName ) + : ResultInfo( expr, ResultWas::Unknown, isNot, filename, line, macroName, message ) { } @@ -216,127 +226,119 @@ private: friend class Expression; /////////////////////////////////////////////////////////////////////////// - void setLhs + MutableResultInfo& captureBoolExpression ( - const std::string& lhs + bool result ) { - m_lhs = lhs; - } - - /////////////////////////////////////////////////////////////////////////// - MutableResultInfo& setRhs - ( - const std::string& op, - const std::string& rhs - ) - { - m_op = op; - m_rhs = rhs; + m_lhs = toString( result ); + m_op = m_isNot ? "!" : ""; + setResultType( result ? ResultWas::Ok : ResultWas::ExpressionFailed ); return *this; } /////////////////////////////////////////////////////////////////////////// template - MutableResultInfo& setExpressionComponents + MutableResultInfo& captureExpression ( const T1& lhs, const T2& rhs ) { setResultType( compare( lhs, rhs ) ? ResultWas::Ok : ResultWas::ExpressionFailed ); + m_lhs = toString( lhs ); m_rhs = toString( rhs ); m_op = OperatorTraits::getName(); return *this; } }; - template - class Expression +template +class Expression +{ +public: + /////////////////////////////////////////////////////////////////////////// + Expression + ( + MutableResultInfo& result, + const T& lhs + ) + : m_result( result ), + m_lhs( lhs ) { - public: - /////////////////////////////////////////////////////////////////////////// - Expression - ( - MutableResultInfo& result, - const T& lhs - ) - : m_result( result ), - m_lhs( lhs ) - { - } - - /////////////////////////////////////////////////////////////////////////// - template - MutableResultInfo& operator == - ( - const RhsT& rhs - ) - { - return m_result.setExpressionComponents( m_lhs, rhs ); - } - - /////////////////////////////////////////////////////////////////////////// - template - MutableResultInfo& operator != - ( - const RhsT& rhs - ) - { - return m_result.setExpressionComponents( m_lhs, rhs ); - } - - /////////////////////////////////////////////////////////////////////////// - template - MutableResultInfo& operator < - ( - const RhsT& rhs - ) - { - return m_result.setExpressionComponents( m_lhs, rhs ); - } - - /////////////////////////////////////////////////////////////////////////// - template - MutableResultInfo& operator > - ( - const RhsT& rhs - ) - { - return m_result.setExpressionComponents( m_lhs, rhs ); - } - - /////////////////////////////////////////////////////////////////////////// - template - MutableResultInfo& operator <= - ( - const RhsT& rhs - ) - { - return m_result.setExpressionComponents( m_lhs, rhs ); - } - - /////////////////////////////////////////////////////////////////////////// - template - MutableResultInfo& operator >= - ( - const RhsT& rhs - ) - { - return m_result.setExpressionComponents( m_lhs, rhs ); - } + } + + /////////////////////////////////////////////////////////////////////////// + template + MutableResultInfo& operator == + ( + const RhsT& rhs + ) + { + return m_result.captureExpression( m_lhs, rhs ); + } + + /////////////////////////////////////////////////////////////////////////// + template + MutableResultInfo& operator != + ( + const RhsT& rhs + ) + { + return m_result.captureExpression( m_lhs, rhs ); + } + + /////////////////////////////////////////////////////////////////////////// + template + MutableResultInfo& operator < + ( + const RhsT& rhs + ) + { + return m_result.captureExpression( m_lhs, rhs ); + } + + /////////////////////////////////////////////////////////////////////////// + template + MutableResultInfo& operator > + ( + const RhsT& rhs + ) + { + return m_result.captureExpression( m_lhs, rhs ); + } + + /////////////////////////////////////////////////////////////////////////// + template + MutableResultInfo& operator <= + ( + const RhsT& rhs + ) + { + return m_result.captureExpression( m_lhs, rhs ); + } + + /////////////////////////////////////////////////////////////////////////// + template + MutableResultInfo& operator >= + ( + const RhsT& rhs + ) + { + return m_result.captureExpression( m_lhs, rhs ); + } - /////////////////////////////////////////////////////////////////////////// - operator MutableResultInfo& - () - { - return m_result; - } - - private: - MutableResultInfo& m_result; - const T& m_lhs; - }; + /////////////////////////////////////////////////////////////////////////// + operator MutableResultInfo& + () + { + return m_result.captureBoolExpression( m_lhs ); + } + +private: + MutableResultInfo& m_result; + const T& m_lhs; +}; class ResultBuilder { @@ -345,11 +347,11 @@ public: /////////////////////////////////////////////////////////////////////////// ResultBuilder ( - const char* expr, - bool isNot, const char* filename, std::size_t line, - const char* macroName + const char* macroName, + const char* expr = "", + bool isNot = false ) : m_result( expr, isNot, filename, line, macroName ) {} @@ -363,90 +365,41 @@ public: { Expression expr( m_result, operand ); - m_result.setLhs( toString( operand ) ); return expr; } -/* + /////////////////////////////////////////////////////////////////////////// template - ResultBuilder& operator->* + ResultBuilder& operator << ( - const T & operand - ) + const T & value + ) { - m_result.setLhs( toString( operand ) ); + m_messageStream << value; return *this; } - */ + /////////////////////////////////////////////////////////////////////////// - template - MutableResultInfo& operator == + ResultBuilder& setResultType ( - const RhsT& rhs + ResultWas::OfType resultType ) { - return m_result.setRhs( "==", toString( rhs ) ); - } - - /////////////////////////////////////////////////////////////////////////// - template - MutableResultInfo& operator != - ( - const RhsT& rhs - ) - { - return m_result.setRhs( "!=", toString( rhs ) ); - } - - /////////////////////////////////////////////////////////////////////////// - template - MutableResultInfo& operator < - ( - const RhsT& rhs - ) - { - return m_result.setRhs( "<", toString( rhs ) ); - } - - /////////////////////////////////////////////////////////////////////////// - template - MutableResultInfo& operator > - ( - const RhsT& rhs - ) - { - return m_result.setRhs( ">", toString( rhs ) ); - } - - /////////////////////////////////////////////////////////////////////////// - template - MutableResultInfo& operator <= - ( - const RhsT& rhs - ) - { - return m_result.setRhs( "<=", toString( rhs ) ); - } - - /////////////////////////////////////////////////////////////////////////// - template - MutableResultInfo& operator >= - ( - const RhsT& rhs - ) - { - return m_result.setRhs( ">=", toString( rhs ) ); - } - + m_result.setResultType( resultType ); + return *this; + } + /////////////////////////////////////////////////////////////////////////// operator MutableResultInfo& () { + m_result.setMessage( m_messageStream.str() ); return m_result; } private: - MutableResultInfo m_result; + MutableResultInfo m_result; + std::ostringstream m_messageStream; }; @@ -565,7 +518,7 @@ inline bool isTrue } // end namespace Catch /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_ACCEPT_RESULT( result, stopOnFailure ) \ +#define INTERNAL_CATCH_ACCEPT_RESULT2( result, stopOnFailure ) \ if( Catch::ResultAction::Value action = Catch::Hub::getResultCapture().acceptResult( result ) ) \ { \ if( action == Catch::ResultAction::DebugFailed ) BreakIntoDebugger(); \ @@ -574,22 +527,22 @@ inline bool isTrue /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ) \ - { \ - Catch::Hub::getResultCapture().acceptExpression( Catch::ResultBuilder( #expr, isNot, __FILE__, __LINE__, macroName )->*expr ); \ - INTERNAL_CATCH_ACCEPT_RESULT( expr, stopOnFailure ) \ - } + Catch::Hub::getResultCapture().acceptExpression( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr, isNot )->*expr ); /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_THROWS( expr, exceptionType, nothrow, stopOnFailure, macroName ) \ - Catch::Hub::getResultCapture().acceptExpression( Catch::ResultBuilder( #expr, false, __FILE__, __LINE__, macroName ) ); \ try \ { \ + using namespace Catch; \ expr; \ - INTERNAL_CATCH_ACCEPT_RESULT( nothrow, stopOnFailure ) \ + ResultWas::OfType resultType = ( nothrow ) ? ResultWas::Ok : ResultWas::DidntThrowException; \ + Hub::getResultCapture().acceptExpression( ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( resultType ) ); \ } \ catch( exceptionType ) \ { \ - INTERNAL_CATCH_ACCEPT_RESULT( !(nothrow), stopOnFailure ) \ + using namespace Catch; \ + ResultWas::OfType resultType = ( nothrow ) ? ResultWas::ThrewException : ResultWas::Ok; \ + Hub::getResultCapture().acceptExpression( ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( resultType ) ); \ } /////////////////////////////////////////////////////////////////////////////// @@ -597,20 +550,18 @@ inline bool isTrue INTERNAL_CATCH_THROWS( expr, exceptionType, nothrow, stopOnFailure, macroName ) \ catch( ... ) \ { \ - INTERNAL_CATCH_ACCEPT_RESULT( false, stopOnFailure ) \ + using namespace Catch; \ + ResultWas::OfType resultType = ( nothrow ) ? ResultWas::ThrewException : ResultWas::Ok; \ + Hub::getResultCapture().acceptExpression( ResultBuilder( __FILE__, __LINE__, macroName, #expr ).setResultType( resultType ) ); \ } /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \ - { \ - std::ostringstream INTERNAL_CATCH_UNIQUE_NAME( strm ); \ - INTERNAL_CATCH_UNIQUE_NAME( strm ) << reason; \ - Catch::Hub::getResultCapture().acceptExpression( Catch::MutableResultInfo( "", false, __FILE__, __LINE__, macroName ) ); \ - Catch::Hub::getResultCapture().acceptMessage( INTERNAL_CATCH_UNIQUE_NAME( strm ).str() ); \ - INTERNAL_CATCH_ACCEPT_RESULT( resultType, stopOnFailure ) \ - } + Catch::Hub::getResultCapture().acceptExpression( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName ) << reason ).setResultType( resultType ) ); /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_SCOPED_INFO( log ) Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); INTERNAL_CATCH_UNIQUE_NAME( info ) << log +#define INTERNAL_CATCH_SCOPED_INFO( log ) \ + Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \ + INTERNAL_CATCH_UNIQUE_NAME( info ) << log #endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED diff --git a/internal/catch_interfaces_capture.h b/internal/catch_interfaces_capture.h index a030f65a..82d8d2d6 100644 --- a/internal/catch_interfaces_capture.h +++ b/internal/catch_interfaces_capture.h @@ -56,7 +56,7 @@ namespace Catch virtual ResultAction::Value acceptResult ( ResultWas::OfType result ) = 0; - virtual void acceptExpression + virtual ResultAction::Value acceptExpression ( const MutableResultInfo& resultInfo ) = 0; virtual void acceptMessage diff --git a/internal/catch_resultinfo.hpp b/internal/catch_resultinfo.hpp index 9ddb2730..bbb82631 100644 --- a/internal/catch_resultinfo.hpp +++ b/internal/catch_resultinfo.hpp @@ -38,13 +38,15 @@ namespace Catch bool isNot, const char* filename, std::size_t line, - const char* macroName + const char* macroName, + const char* message ) : m_macroName( macroName ), m_filename( filename ), m_line( line ), m_expr( expr ), m_op( isNotExpression( expr ) ? "!" : "" ), + m_message( message ), m_result( result ), m_isNot( isNot ), m_expressionIncomplete( false ) diff --git a/internal/catch_runner_impl.hpp b/internal/catch_runner_impl.hpp index acf9a41a..657682df 100644 --- a/internal/catch_runner_impl.hpp +++ b/internal/catch_runner_impl.hpp @@ -458,12 +458,22 @@ namespace Catch } /////////////////////////////////////////////////////////////////////////// - virtual void acceptExpression + virtual ResultAction::Value acceptExpression ( const MutableResultInfo& resultInfo ) { m_currentResult = resultInfo; + testEnded( m_currentResult ); + + bool ok = m_currentResult.ok(); + m_currentResult = MutableResultInfo(); + if( ok ) + return ResultAction::None; + else if( shouldDebugBreak() ) + return ResultAction::DebugFailed; + else + return ResultAction::Failed; } ///////////////////////////////////////////////////////////////////////////