diff --git a/.gitignore b/.gitignore index 541f1be6..9c61780b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,5 @@ Debug Release *.user *.xcuserstate -/Test/Test.xcodeproj/xcuserdata/ -.DS_Store \ No newline at end of file +.DS_Store +xcuserdata \ No newline at end of file diff --git a/include/catch.hpp b/include/catch.hpp index d314d3c2..7697c231 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -53,6 +53,8 @@ #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CHECK" ) #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CHECKED_ELSE" ) #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CHECK_THROWS" ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" ) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 738b8214..2449f60b 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -687,6 +687,16 @@ inline bool isTrue INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr, isNot )->*expr ), stopOnFailure ); \ if( Catch::isTrue( false ) ){ bool internal_catch_dummyResult = ( expr ); Catch::isTrue( internal_catch_dummyResult ); } +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, isNot, stopOnFailure, macroName ) \ + INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \ + if( Catch::Hub::getResultCapture().getLastResult()->ok() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, isNot, stopOnFailure, macroName ) \ + INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \ + if( !Catch::Hub::getResultCapture().getLastResult()->ok() ) + /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \ try \ diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h index f3a530d6..e74563ef 100644 --- a/include/internal/catch_interfaces_capture.h +++ b/include/internal/catch_interfaces_capture.h @@ -20,6 +20,7 @@ namespace Catch class TestCaseInfo; class ScopedInfo; class MutableResultInfo; + class ResultInfo; struct IResultCapture { @@ -66,6 +67,8 @@ namespace Catch ) = 0; virtual std::string getCurrentTestName + () const = 0; + virtual const ResultInfo* getLastResult () const = 0; }; diff --git a/include/internal/catch_resultinfo.hpp b/include/internal/catch_resultinfo.hpp index 258cc47c..f9da25a8 100644 --- a/include/internal/catch_resultinfo.hpp +++ b/include/internal/catch_resultinfo.hpp @@ -63,10 +63,11 @@ namespace Catch } /////////////////////////////////////////////////////////////////////////// - virtual ~ResultInfo + virtual ~ResultInfo () - { - } + { + } + /////////////////////////////////////////////////////////////////////////// bool ok () diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index 0bb28203..17ef47fe 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -548,6 +548,14 @@ namespace Catch ? m_runningTest->getTestCaseInfo().getName() : ""; } + + /////////////////////////////////////////////////////////////////////////// + virtual const ResultInfo* getLastResult + () + const + { + return &m_lastResult; + } private: @@ -556,10 +564,10 @@ namespace Catch () { testEnded( m_currentResult ); + m_lastResult = m_currentResult; - bool ok = m_currentResult.ok(); m_currentResult = MutableResultInfo(); - if( ok ) + if( m_lastResult.ok() ) return ResultAction::None; else if( shouldDebugBreak() ) return ResultAction::DebugFailed; @@ -612,6 +620,7 @@ namespace Catch private: RunningTest* m_runningTest; MutableResultInfo m_currentResult; + ResultInfo m_lastResult; const Config& m_config; std::size_t m_successes; diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 0a4d1bb9..60a57350 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -121,3 +121,39 @@ TEST_CASE( "./failing/info", "sends information to INFO" ) CAPTURE( i ); REQUIRE( false ); } + +inline bool testCheckedIf( bool flag ) +{ + CHECKED_IF( flag ) + return true; + else + return false; +} + +TEST_CASE( "./succeeding/checkedif", "" ) +{ + REQUIRE( testCheckedIf( true ) ); +} + +TEST_CASE( "./failing/checkedif", "" ) +{ + REQUIRE( testCheckedIf( false ) ); +} + +inline bool testCheckedElse( bool flag ) +{ + CHECKED_ELSE( flag ) + return false; + + return true; +} + +TEST_CASE( "./succeeding/checkedelse", "" ) +{ + REQUIRE( testCheckedElse( true ) ); +} + +TEST_CASE( "./failing/checkedelse", "" ) +{ + REQUIRE( testCheckedElse( false ) ); +} diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 0ca760e5..868f0f60 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -47,7 +47,7 @@ TEST_CASE( "selftest/main", "Runs all Catch self tests and checks their results" "Number of 'succeeding' tests is fixed" ) { runner.runMatching( "./succeeding/*" ); - CHECK( runner.getSuccessCount() == 258 ); + CHECK( runner.getSuccessCount() == 262 ); CHECK( runner.getFailureCount() == 0 ); } @@ -56,7 +56,7 @@ TEST_CASE( "selftest/main", "Runs all Catch self tests and checks their results" { runner.runMatching( "./failing/*" ); CHECK( runner.getSuccessCount() == 0 ); - CHECK( runner.getFailureCount() == 64 ); + CHECK( runner.getFailureCount() == 68 ); } } } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index c808f605..3b2f8d8f 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -701,10 +701,11 @@ namespace Catch } /////////////////////////////////////////////////////////////////////////// - virtual ~ResultInfo + virtual ~ResultInfo () - { - } + { + } + /////////////////////////////////////////////////////////////////////////// bool ok () @@ -844,6 +845,7 @@ namespace Catch class TestCaseInfo; class ScopedInfo; class MutableResultInfo; + class ResultInfo; struct IResultCapture { @@ -891,6 +893,8 @@ namespace Catch virtual std::string getCurrentTestName () const = 0; + virtual const ResultInfo* getLastResult + () const = 0; }; } @@ -1869,6 +1873,16 @@ inline bool isTrue INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ResultBuilder( __FILE__, __LINE__, macroName, #expr, isNot )->*expr ), stopOnFailure ); \ if( Catch::isTrue( false ) ){ bool internal_catch_dummyResult = ( expr ); Catch::isTrue( internal_catch_dummyResult ); } +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( expr, isNot, stopOnFailure, macroName ) \ + INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \ + if( Catch::Hub::getResultCapture().getLastResult()->ok() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( expr, isNot, stopOnFailure, macroName ) \ + INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \ + if( !Catch::Hub::getResultCapture().getLastResult()->ok() ) + /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \ try \ @@ -2786,7 +2800,9 @@ namespace Catch #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED +#import #import + #include // NB. Any general catch headers included here must be included @@ -4143,6 +4159,14 @@ namespace Catch : ""; } + /////////////////////////////////////////////////////////////////////////// + virtual const ResultInfo* getLastResult + () + const + { + return &m_lastResult; + } + private: /////////////////////////////////////////////////////////////////////////// @@ -4150,10 +4174,10 @@ namespace Catch () { testEnded( m_currentResult ); + m_lastResult = m_currentResult; - bool ok = m_currentResult.ok(); m_currentResult = MutableResultInfo(); - if( ok ) + if( m_lastResult.ok() ) return ResultAction::None; else if( shouldDebugBreak() ) return ResultAction::DebugFailed; @@ -4206,6 +4230,7 @@ namespace Catch private: RunningTest* m_runningTest; MutableResultInfo m_currentResult; + ResultInfo m_lastResult; const Config& m_config; std::size_t m_successes; @@ -6208,6 +6233,8 @@ int main (int argc, char * const argv[]) #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CHECK" ) #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CHECK_FALSE" ) +#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CHECKED_IF" ) +#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CHECKED_ELSE" ) #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CHECK_THROWS" ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" )