mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 12:17:11 +01:00 
			
		
		
		
	Merge branch 'reevaluate' into dev-modernize
This commit is contained in:
		| @@ -122,8 +122,11 @@ CheckFileList(EXTERNAL_HEADERS ${HEADER_DIR}/external) | |||||||
| # Please keep these ordered alphabetically | # Please keep these ordered alphabetically | ||||||
| set(INTERNAL_HEADERS | set(INTERNAL_HEADERS | ||||||
|         ${HEADER_DIR}/internal/catch_approx.hpp |         ${HEADER_DIR}/internal/catch_approx.hpp | ||||||
|  |         ${HEADER_DIR}/internal/catch_assertionhandler.h | ||||||
|  |         ${HEADER_DIR}/internal/catch_assertioninfo.h | ||||||
|         ${HEADER_DIR}/internal/catch_assertionresult.h |         ${HEADER_DIR}/internal/catch_assertionresult.h | ||||||
|         ${HEADER_DIR}/internal/catch_capture.hpp |         ${HEADER_DIR}/internal/catch_capture.hpp | ||||||
|  |         ${HEADER_DIR}/internal/catch_capture_matchers.h | ||||||
|         ${HEADER_DIR}/internal/catch_clara.h |         ${HEADER_DIR}/internal/catch_clara.h | ||||||
|         ${HEADER_DIR}/internal/catch_commandline.hpp |         ${HEADER_DIR}/internal/catch_commandline.hpp | ||||||
|         ${HEADER_DIR}/internal/catch_common.h |         ${HEADER_DIR}/internal/catch_common.h | ||||||
| @@ -132,12 +135,11 @@ set(INTERNAL_HEADERS | |||||||
|         ${HEADER_DIR}/internal/catch_console_colour.hpp |         ${HEADER_DIR}/internal/catch_console_colour.hpp | ||||||
|         ${HEADER_DIR}/internal/catch_context.h |         ${HEADER_DIR}/internal/catch_context.h | ||||||
|         ${HEADER_DIR}/internal/catch_debugger.h |         ${HEADER_DIR}/internal/catch_debugger.h | ||||||
|  |         ${HEADER_DIR}/internal/catch_decomposer.h | ||||||
|         ${HEADER_DIR}/internal/catch_default_main.hpp |         ${HEADER_DIR}/internal/catch_default_main.hpp | ||||||
|         ${HEADER_DIR}/internal/catch_enforce.h |         ${HEADER_DIR}/internal/catch_enforce.h | ||||||
|         ${HEADER_DIR}/internal/catch_errno_guard.h |         ${HEADER_DIR}/internal/catch_errno_guard.h | ||||||
|         ${HEADER_DIR}/internal/catch_evaluate.hpp |  | ||||||
|         ${HEADER_DIR}/internal/catch_exception_translator_registry.h |         ${HEADER_DIR}/internal/catch_exception_translator_registry.h | ||||||
|         ${HEADER_DIR}/internal/catch_expression_lhs.hpp |  | ||||||
|         ${HEADER_DIR}/internal/catch_fatal_condition.h |         ${HEADER_DIR}/internal/catch_fatal_condition.h | ||||||
|         ${HEADER_DIR}/internal/catch_impl.hpp |         ${HEADER_DIR}/internal/catch_impl.hpp | ||||||
|         ${HEADER_DIR}/internal/catch_interfaces_capture.h |         ${HEADER_DIR}/internal/catch_interfaces_capture.h | ||||||
| @@ -162,7 +164,6 @@ set(INTERNAL_HEADERS | |||||||
|         ${HEADER_DIR}/internal/catch_reenable_warnings.h |         ${HEADER_DIR}/internal/catch_reenable_warnings.h | ||||||
|         ${HEADER_DIR}/internal/catch_reporter_registrars.hpp |         ${HEADER_DIR}/internal/catch_reporter_registrars.hpp | ||||||
|         ${HEADER_DIR}/internal/catch_reporter_registry.hpp |         ${HEADER_DIR}/internal/catch_reporter_registry.hpp | ||||||
|         ${HEADER_DIR}/internal/catch_result_builder.h |  | ||||||
|         ${HEADER_DIR}/internal/catch_result_type.h |         ${HEADER_DIR}/internal/catch_result_type.h | ||||||
|         ${HEADER_DIR}/internal/catch_run_context.hpp |         ${HEADER_DIR}/internal/catch_run_context.hpp | ||||||
|         ${HEADER_DIR}/internal/catch_benchmark.h |         ${HEADER_DIR}/internal/catch_benchmark.h | ||||||
| @@ -197,16 +198,18 @@ set(INTERNAL_HEADERS | |||||||
|         ) |         ) | ||||||
| set(IMPL_SOURCES | set(IMPL_SOURCES | ||||||
|         ${HEADER_DIR}/internal/catch_approx.cpp |         ${HEADER_DIR}/internal/catch_approx.cpp | ||||||
|  |         ${HEADER_DIR}/internal/catch_assertionhandler.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_assertionresult.cpp |         ${HEADER_DIR}/internal/catch_assertionresult.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_benchmark.cpp |         ${HEADER_DIR}/internal/catch_benchmark.cpp | ||||||
|  |         ${HEADER_DIR}/internal/catch_capture_matchers.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_commandline.cpp |         ${HEADER_DIR}/internal/catch_commandline.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_common.cpp |         ${HEADER_DIR}/internal/catch_common.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_config.cpp |         ${HEADER_DIR}/internal/catch_config.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_console_colour.cpp |         ${HEADER_DIR}/internal/catch_console_colour.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_context.cpp |         ${HEADER_DIR}/internal/catch_context.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_debugger.cpp |         ${HEADER_DIR}/internal/catch_debugger.cpp | ||||||
|  |         ${HEADER_DIR}/internal/catch_decomposer.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_errno_guard.cpp |         ${HEADER_DIR}/internal/catch_errno_guard.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_evaluate.cpp |  | ||||||
|         ${HEADER_DIR}/internal/catch_exception_translator_registry.cpp |         ${HEADER_DIR}/internal/catch_exception_translator_registry.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_fatal_condition.cpp |         ${HEADER_DIR}/internal/catch_fatal_condition.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_list.cpp |         ${HEADER_DIR}/internal/catch_list.cpp | ||||||
| @@ -217,7 +220,6 @@ set(IMPL_SOURCES | |||||||
|         ${HEADER_DIR}/internal/catch_notimplemented_exception.cpp |         ${HEADER_DIR}/internal/catch_notimplemented_exception.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_registry_hub.cpp |         ${HEADER_DIR}/internal/catch_registry_hub.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_interfaces_reporter.cpp |         ${HEADER_DIR}/internal/catch_interfaces_reporter.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_result_builder.cpp |  | ||||||
|         ${HEADER_DIR}/internal/catch_result_type.cpp |         ${HEADER_DIR}/internal/catch_result_type.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_run_context.cpp |         ${HEADER_DIR}/internal/catch_run_context.cpp | ||||||
|         ${HEADER_DIR}/internal/catch_section.cpp |         ${HEADER_DIR}/internal/catch_section.cpp | ||||||
|   | |||||||
| @@ -41,6 +41,10 @@ | |||||||
| #include "internal/catch_compiler_capabilities.h" | #include "internal/catch_compiler_capabilities.h" | ||||||
| #include "internal/catch_interfaces_tag_alias_registry.h" | #include "internal/catch_interfaces_tag_alias_registry.h" | ||||||
|  |  | ||||||
|  | #ifndef CATCH_CONFIG_DISABLE_MATCHERS | ||||||
|  | #include "internal/catch_capture_matchers.h" | ||||||
|  | #endif | ||||||
|  |  | ||||||
| // These files are included here so the single_include script doesn't put them | // These files are included here so the single_include script doesn't put them | ||||||
| // in the conditionally compiled sections | // in the conditionally compiled sections | ||||||
| #include "internal/catch_test_case_info.h" | #include "internal/catch_test_case_info.h" | ||||||
| @@ -72,8 +76,8 @@ | |||||||
|  |  | ||||||
| #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) | #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) | ||||||
| #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) | #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) | ||||||
| #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) |  | ||||||
| #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) | #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) | ||||||
|  | #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) | ||||||
| #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) | #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) | ||||||
| #endif// CATCH_CONFIG_DISABLE_MATCHERS | #endif// CATCH_CONFIG_DISABLE_MATCHERS | ||||||
| #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) | #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) | ||||||
| @@ -86,8 +90,8 @@ | |||||||
|  |  | ||||||
| #define CATCH_CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) | #define CATCH_CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) | ||||||
| #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) | #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) | ||||||
| #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) |  | ||||||
| #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) | #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) | ||||||
|  | #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) | ||||||
| #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) | #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) | ||||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS | #endif // CATCH_CONFIG_DISABLE_MATCHERS | ||||||
| #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) | #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) | ||||||
| @@ -132,8 +136,8 @@ | |||||||
|  |  | ||||||
| #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) | #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) | ||||||
| #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) | #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) | ||||||
| #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) |  | ||||||
| #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) | #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) | ||||||
|  | #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) | ||||||
| #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) | #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) | ||||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS | #endif // CATCH_CONFIG_DISABLE_MATCHERS | ||||||
| #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) | #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) | ||||||
| @@ -146,8 +150,8 @@ | |||||||
|  |  | ||||||
| #define CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) | #define CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) | ||||||
| #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) | #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) | ||||||
| #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) |  | ||||||
| #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) | #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) | ||||||
|  | #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) | ||||||
| #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) | #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) | ||||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS | #endif // CATCH_CONFIG_DISABLE_MATCHERS | ||||||
| #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) | #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) | ||||||
|   | |||||||
							
								
								
									
										147
									
								
								include/internal/catch_assertionhandler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								include/internal/catch_assertionhandler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | |||||||
|  | /* | ||||||
|  |  *  Created by Phil on 8/8/2017. | ||||||
|  |  *  Copyright 2017 Two Blue Cubes Ltd. All rights reserved. | ||||||
|  |  * | ||||||
|  |  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||||
|  |  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "catch_assertionhandler.h" | ||||||
|  | #include "catch_assertionresult.h" | ||||||
|  | #include "catch_interfaces_capture.h" | ||||||
|  | #include "catch_interfaces_runner.h" | ||||||
|  | #include "catch_interfaces_config.h" | ||||||
|  | #include "catch_context.h" | ||||||
|  | #include "catch_debugger.h" | ||||||
|  | #include "catch_interfaces_registry_hub.h" | ||||||
|  | #include "catch_capture_matchers.h" | ||||||
|  |  | ||||||
|  | #include <cassert> | ||||||
|  |  | ||||||
|  | namespace Catch { | ||||||
|  |  | ||||||
|  |     auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { | ||||||
|  |         expr.streamReconstructedExpression( os ); | ||||||
|  |         return os; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     LazyExpression::LazyExpression( bool isNegated ) | ||||||
|  |     :   m_isNegated( isNegated ) | ||||||
|  |     {} | ||||||
|  |  | ||||||
|  |     LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} | ||||||
|  |  | ||||||
|  |     LazyExpression::operator bool() const { | ||||||
|  |         return m_transientExpression != nullptr; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { | ||||||
|  |         if( lazyExpr.m_isNegated ) | ||||||
|  |             os << "!"; | ||||||
|  |  | ||||||
|  |         if( lazyExpr ) { | ||||||
|  |             if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) | ||||||
|  |                 os << "(" << *lazyExpr.m_transientExpression << ")"; | ||||||
|  |             else | ||||||
|  |                 os << *lazyExpr.m_transientExpression; | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             os << "{** error - unchecked empty expression requested **}"; | ||||||
|  |         } | ||||||
|  |         return os; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     AssertionHandler::AssertionHandler | ||||||
|  |         (   StringRef macroName, | ||||||
|  |             SourceLineInfo const& lineInfo, | ||||||
|  |             StringRef capturedExpression, | ||||||
|  |             ResultDisposition::Flags resultDisposition ) | ||||||
|  |     :   m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition } | ||||||
|  |     { | ||||||
|  |         getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); | ||||||
|  |     } | ||||||
|  |     AssertionHandler::~AssertionHandler() { | ||||||
|  |         if ( m_inExceptionGuard ) { | ||||||
|  |             handle( ResultWas::ThrewException, "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE" ); | ||||||
|  |             getCurrentContext().getResultCapture()->exceptionEarlyReported(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void AssertionHandler::handle( ITransientExpression const& expr ) { | ||||||
|  |  | ||||||
|  |         bool negated = isFalseTest( m_assertionInfo.resultDisposition ); | ||||||
|  |         bool result = expr.getResult() != negated; | ||||||
|  |  | ||||||
|  |         handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated ); | ||||||
|  |     } | ||||||
|  |     void AssertionHandler::handle( ResultWas::OfType resultType ) { | ||||||
|  |         handle( resultType, nullptr, false ); | ||||||
|  |     } | ||||||
|  |     void AssertionHandler::handle( ResultWas::OfType resultType, StringRef const& message ) { | ||||||
|  |         AssertionResultData data( resultType, LazyExpression( false ) ); | ||||||
|  |         data.message = message.c_str(); | ||||||
|  |         handle( data, nullptr ); | ||||||
|  |     } | ||||||
|  |     void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) { | ||||||
|  |         AssertionResultData data( resultType, LazyExpression( negated ) ); | ||||||
|  |         handle( data, expr ); | ||||||
|  |     } | ||||||
|  |     void AssertionHandler::handle( AssertionResultData const& resultData, ITransientExpression const* expr ) { | ||||||
|  |  | ||||||
|  |         getResultCapture().assertionRun(); | ||||||
|  |  | ||||||
|  |         AssertionResult assertionResult{ m_assertionInfo, resultData }; | ||||||
|  |         assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; | ||||||
|  |  | ||||||
|  |         getResultCapture().assertionEnded( assertionResult ); | ||||||
|  |  | ||||||
|  |         if( !assertionResult.isOk() ) { | ||||||
|  |             m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak(); | ||||||
|  |             m_shouldThrow = | ||||||
|  |                     getCurrentContext().getRunner()->aborting() || | ||||||
|  |                     (m_assertionInfo.resultDisposition & ResultDisposition::Normal); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     auto AssertionHandler::allowThrows() const -> bool { | ||||||
|  |         return getCurrentContext().getConfig()->allowThrows(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     auto AssertionHandler::shouldDebugBreak() const -> bool { | ||||||
|  |         return m_shouldDebugBreak; | ||||||
|  |     } | ||||||
|  |     void AssertionHandler::reactWithDebugBreak() const { | ||||||
|  |         if (m_shouldDebugBreak) { | ||||||
|  |             /////////////////////////////////////////////////////////////////// | ||||||
|  |             // To inspect the state during test, you need to go one level up the callstack | ||||||
|  |             // To go back to the test and change execution, jump over the reactWithoutDebugBreak() call | ||||||
|  |             /////////////////////////////////////////////////////////////////// | ||||||
|  |             CATCH_BREAK_INTO_DEBUGGER(); | ||||||
|  |         } | ||||||
|  |         reactWithoutDebugBreak(); | ||||||
|  |     } | ||||||
|  |     void AssertionHandler::reactWithoutDebugBreak() const { | ||||||
|  |         if( m_shouldThrow ) | ||||||
|  |             throw Catch::TestFailureException(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void AssertionHandler::useActiveException() { | ||||||
|  |         handle( ResultWas::ThrewException, Catch::translateActiveException().c_str() ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void AssertionHandler::setExceptionGuard() { | ||||||
|  |         assert( m_inExceptionGuard == false ); | ||||||
|  |         m_inExceptionGuard = true; | ||||||
|  |     } | ||||||
|  |     void AssertionHandler::unsetExceptionGuard() { | ||||||
|  |         assert( m_inExceptionGuard == true ); | ||||||
|  |         m_inExceptionGuard = false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // This is the overload that takes a string and infers the Equals matcher from it | ||||||
|  |     // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp | ||||||
|  |     void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString  ) { | ||||||
|  |         handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } // namespace Catch | ||||||
							
								
								
									
										73
									
								
								include/internal/catch_assertionhandler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								include/internal/catch_assertionhandler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | |||||||
|  | /* | ||||||
|  |  *  Created by Phil on 8/8/2017. | ||||||
|  |  *  Copyright 2017 Two Blue Cubes Ltd. All rights reserved. | ||||||
|  |  * | ||||||
|  |  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||||
|  |  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||||
|  |  */ | ||||||
|  | #ifndef TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED | ||||||
|  | #define TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED | ||||||
|  |  | ||||||
|  | #include "catch_decomposer.h" | ||||||
|  | #include "catch_assertioninfo.h" | ||||||
|  |  | ||||||
|  | namespace Catch { | ||||||
|  |  | ||||||
|  |     struct TestFailureException{}; | ||||||
|  |     struct AssertionResultData; | ||||||
|  |  | ||||||
|  |     class LazyExpression { | ||||||
|  |         friend class AssertionHandler; | ||||||
|  |         friend struct AssertionStats; | ||||||
|  |  | ||||||
|  |         ITransientExpression const* m_transientExpression = nullptr; | ||||||
|  |         bool m_isNegated; | ||||||
|  |     public: | ||||||
|  |         LazyExpression( bool isNegated ); | ||||||
|  |         LazyExpression( LazyExpression const& other ); | ||||||
|  |         LazyExpression& operator = ( LazyExpression const& ) = delete; | ||||||
|  |  | ||||||
|  |         explicit operator bool() const; | ||||||
|  |  | ||||||
|  |         friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     class AssertionHandler { | ||||||
|  |         AssertionInfo m_assertionInfo; | ||||||
|  |         bool m_shouldDebugBreak = false; | ||||||
|  |         bool m_shouldThrow = false; | ||||||
|  |         bool m_inExceptionGuard = false; | ||||||
|  |  | ||||||
|  |     public: | ||||||
|  |         AssertionHandler | ||||||
|  |             (   StringRef macroName, | ||||||
|  |                 SourceLineInfo const& lineInfo, | ||||||
|  |                 StringRef capturedExpression, | ||||||
|  |                 ResultDisposition::Flags resultDisposition ); | ||||||
|  |         ~AssertionHandler(); | ||||||
|  |  | ||||||
|  |         void handle( ITransientExpression const& expr ); | ||||||
|  |  | ||||||
|  |         template<typename T> | ||||||
|  |         void handle( ExprLhs<T> const& expr ) { | ||||||
|  |             handle( expr.makeUnaryExpr() ); | ||||||
|  |         } | ||||||
|  |         void handle( ResultWas::OfType resultType ); | ||||||
|  |         void handle( ResultWas::OfType resultType, StringRef const& message ); | ||||||
|  |         void handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ); | ||||||
|  |         void handle( AssertionResultData const& resultData, ITransientExpression const* expr ); | ||||||
|  |  | ||||||
|  |         auto shouldDebugBreak() const -> bool; | ||||||
|  |         auto allowThrows() const -> bool; | ||||||
|  |         void reactWithDebugBreak() const; | ||||||
|  |         void reactWithoutDebugBreak() const; | ||||||
|  |         void useActiveException(); | ||||||
|  |         void setExceptionGuard(); | ||||||
|  |         void unsetExceptionGuard(); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ); | ||||||
|  |  | ||||||
|  | } // namespace Catch | ||||||
|  |  | ||||||
|  | #endif // TWOBLUECUBES_CATCH_ASSERTIONHANDLER_H_INCLUDED | ||||||
							
								
								
									
										31
									
								
								include/internal/catch_assertioninfo.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								include/internal/catch_assertioninfo.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | /* | ||||||
|  |  *  Created by Phil on 8/8/2017. | ||||||
|  |  *  Copyright 2017 Two Blue Cubes Ltd. All rights reserved. | ||||||
|  |  * | ||||||
|  |  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||||
|  |  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||||
|  |  */ | ||||||
|  | #ifndef TWOBLUECUBES_CATCH_ASSERTIONINFO_H_INCLUDED | ||||||
|  | #define TWOBLUECUBES_CATCH_ASSERTIONINFO_H_INCLUDED | ||||||
|  |  | ||||||
|  | #include "catch_result_type.h" | ||||||
|  | #include "catch_common.h" | ||||||
|  | #include "catch_stringref.h" | ||||||
|  |  | ||||||
|  | namespace Catch { | ||||||
|  |  | ||||||
|  |     struct AssertionInfo | ||||||
|  |     { | ||||||
|  |         StringRef macroName; | ||||||
|  |         SourceLineInfo lineInfo; | ||||||
|  |         StringRef capturedExpression; | ||||||
|  |         ResultDisposition::Flags resultDisposition; | ||||||
|  |  | ||||||
|  |         // We want to delete this constructor but a compiler bug in 4.8 means | ||||||
|  |         // the struct is then treated as non-aggregate | ||||||
|  |         //AssertionInfo() = delete; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  | } // end namespace Catch | ||||||
|  |  | ||||||
|  | #endif // TWOBLUECUBES_CATCH_ASSERTIONINFO_H_INCLUDED | ||||||
| @@ -10,54 +10,24 @@ | |||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
|  |  | ||||||
|  |     std::string AssertionResultData::reconstructExpression() const { | ||||||
|  |  | ||||||
|     bool DecomposedExpression::isBinaryExpression() const { |         if( reconstructedExpression.empty() ) { | ||||||
|         return false; |             if( lazyExpression ) { | ||||||
|     } |                 // !TBD Use stringstream for now, but rework above to pass stream in | ||||||
|  |                 std::ostringstream oss; | ||||||
|     AssertionInfo::AssertionInfo(   char const * _macroName, |                 oss << lazyExpression; | ||||||
|                                     SourceLineInfo const& _lineInfo, |                 reconstructedExpression = oss.str(); | ||||||
|                                     char const * _capturedExpression, |  | ||||||
|                                     ResultDisposition::Flags _resultDisposition) |  | ||||||
|     :   macroName( _macroName ), |  | ||||||
|         lineInfo( _lineInfo ), |  | ||||||
|         capturedExpression( _capturedExpression ), |  | ||||||
|         resultDisposition( _resultDisposition ) |  | ||||||
|     {} |  | ||||||
|  |  | ||||||
|     void AssertionResultData::negate( bool parenthesize ) { |  | ||||||
|         negated = !negated; |  | ||||||
|         parenthesized = parenthesize; |  | ||||||
|         if( resultType == ResultWas::Ok ) |  | ||||||
|             resultType = ResultWas::ExpressionFailed; |  | ||||||
|         else if( resultType == ResultWas::ExpressionFailed ) |  | ||||||
|             resultType = ResultWas::Ok; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     std::string const& AssertionResultData::reconstructExpression() const { |  | ||||||
|         if( decomposedExpression != nullptr ) { |  | ||||||
|             decomposedExpression->reconstructExpression( reconstructedExpression ); |  | ||||||
|             if( parenthesized ) { |  | ||||||
|                 reconstructedExpression.insert( 0, 1, '(' ); |  | ||||||
|                 reconstructedExpression.append( 1, ')' ); |  | ||||||
|             } |             } | ||||||
|             if( negated ) { |  | ||||||
|                 reconstructedExpression.insert( 0, 1, '!' ); |  | ||||||
|             } |  | ||||||
|             decomposedExpression = nullptr; |  | ||||||
|         } |         } | ||||||
|         return reconstructedExpression; |         return reconstructedExpression; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     AssertionResult::AssertionResult() {} |  | ||||||
|  |  | ||||||
|     AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) |     AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) | ||||||
|     :   m_info( info ), |     :   m_info( info ), | ||||||
|         m_resultData( data ) |         m_resultData( data ) | ||||||
|     {} |     {} | ||||||
|  |  | ||||||
|     AssertionResult::~AssertionResult() {} |  | ||||||
|  |  | ||||||
|     // Result was a success |     // Result was a success | ||||||
|     bool AssertionResult::succeeded() const { |     bool AssertionResult::succeeded() const { | ||||||
|         return Catch::isOk( m_resultData.resultType ); |         return Catch::isOk( m_resultData.resultType ); | ||||||
| @@ -82,16 +52,16 @@ namespace Catch { | |||||||
|  |  | ||||||
|     std::string AssertionResult::getExpression() const { |     std::string AssertionResult::getExpression() const { | ||||||
|         if (isFalseTest(m_info.resultDisposition)) |         if (isFalseTest(m_info.resultDisposition)) | ||||||
|             return '!' + std::string(m_info.capturedExpression); |             return '!' + std::string(m_info.capturedExpression.c_str()); | ||||||
|         else |         else | ||||||
|             return std::string(m_info.capturedExpression); |             return std::string(m_info.capturedExpression.c_str()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     std::string AssertionResult::getExpressionInMacro() const { |     std::string AssertionResult::getExpressionInMacro() const { | ||||||
|         if( m_info.macroName[0] == 0 ) |         if( m_info.macroName[0] == 0 ) | ||||||
|             return std::string(m_info.capturedExpression); |             return std::string(m_info.capturedExpression.c_str()); | ||||||
|         else |         else | ||||||
|             return std::string(m_info.macroName) + "( " + m_info.capturedExpression + " )"; |             return std::string(m_info.macroName.c_str()) + "( " + m_info.capturedExpression.c_str() + " )"; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool AssertionResult::hasExpandedExpression() const { |     bool AssertionResult::hasExpandedExpression() const { | ||||||
| @@ -99,7 +69,10 @@ namespace Catch { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     std::string AssertionResult::getExpandedExpression() const { |     std::string AssertionResult::getExpandedExpression() const { | ||||||
|         return m_resultData.reconstructExpression(); |         std::string expr = m_resultData.reconstructExpression(); | ||||||
|  |         return expr.empty() | ||||||
|  |                 ? getExpression() | ||||||
|  |                 : expr; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     std::string AssertionResult::getMessage() const { |     std::string AssertionResult::getMessage() const { | ||||||
| @@ -110,15 +83,7 @@ namespace Catch { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     std::string AssertionResult::getTestMacroName() const { |     std::string AssertionResult::getTestMacroName() const { | ||||||
|         return m_info.macroName; |         return m_info.macroName.c_str(); | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void AssertionResult::discardDecomposedExpression() const { |  | ||||||
|         m_resultData.decomposedExpression = nullptr; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void AssertionResult::expandDecomposedExpression() const { |  | ||||||
|         m_resultData.reconstructExpression(); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } // end namespace Catch | } // end namespace Catch | ||||||
|   | |||||||
| @@ -9,71 +9,36 @@ | |||||||
| #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED | #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED | ||||||
|  |  | ||||||
| #include <string> | #include <string> | ||||||
|  | #include "catch_assertioninfo.h" | ||||||
| #include "catch_result_type.h" | #include "catch_result_type.h" | ||||||
| #include "catch_common.h" | #include "catch_common.h" | ||||||
|  | #include "catch_stringref.h" | ||||||
|  | #include "catch_assertionhandler.h" | ||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
|  |  | ||||||
|     struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; |  | ||||||
|  |  | ||||||
|     struct DecomposedExpression |  | ||||||
|     { |  | ||||||
|         DecomposedExpression() = default; |  | ||||||
|         DecomposedExpression( DecomposedExpression const& ) = default; |  | ||||||
|         DecomposedExpression& operator = ( DecomposedExpression const& ) = delete; |  | ||||||
|  |  | ||||||
|         virtual ~DecomposedExpression() = default; |  | ||||||
|         virtual bool isBinaryExpression() const; |  | ||||||
|         virtual void reconstructExpression( std::string& dest ) const = 0; |  | ||||||
|  |  | ||||||
|         // Only simple binary comparisons can be decomposed. |  | ||||||
|         // If more complex check is required then wrap sub-expressions in parentheses. |  | ||||||
|         template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& ); |  | ||||||
|         template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& ); |  | ||||||
|         template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& ); |  | ||||||
|         template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& ); |  | ||||||
|         template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& ); |  | ||||||
|         template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& ); |  | ||||||
|         template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& ); |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     struct AssertionInfo |  | ||||||
|     { |  | ||||||
|         AssertionInfo() = default; |  | ||||||
|         AssertionInfo(  char const * _macroName, |  | ||||||
|                         SourceLineInfo const& _lineInfo, |  | ||||||
|                         char const * _capturedExpression, |  | ||||||
|                         ResultDisposition::Flags _resultDisposition); |  | ||||||
|  |  | ||||||
|         char const * macroName = nullptr; |  | ||||||
|         SourceLineInfo lineInfo; |  | ||||||
|         char const * capturedExpression = nullptr; |  | ||||||
|         ResultDisposition::Flags resultDisposition = ResultDisposition::Normal; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     struct AssertionResultData |     struct AssertionResultData | ||||||
|     { |     { | ||||||
|         void negate( bool parenthesize ); |         AssertionResultData() = delete; | ||||||
|         std::string const& reconstructExpression() const; |  | ||||||
|  |         AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ) | ||||||
|  |         :   resultType( _resultType ), | ||||||
|  |             lazyExpression( _lazyExpression ) | ||||||
|  |         {} | ||||||
|  |  | ||||||
|         mutable DecomposedExpression const* decomposedExpression = nullptr; |  | ||||||
|         mutable std::string reconstructedExpression; |  | ||||||
|         std::string message; |  | ||||||
|         ResultWas::OfType resultType = ResultWas::Unknown; |         ResultWas::OfType resultType = ResultWas::Unknown; | ||||||
|         bool negated = false; |         std::string message; | ||||||
|         bool parenthesized = false; |  | ||||||
|  |         LazyExpression lazyExpression; | ||||||
|  |  | ||||||
|  |         std::string reconstructExpression() const; | ||||||
|  |         mutable std::string reconstructedExpression; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     class AssertionResult { |     class AssertionResult { | ||||||
|     public: |     public: | ||||||
|         AssertionResult(); |         AssertionResult() = delete; | ||||||
|         AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); |         AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); | ||||||
|         ~AssertionResult(); |  | ||||||
|  |  | ||||||
|         AssertionResult( AssertionResult const& )              = default; |  | ||||||
|         AssertionResult( AssertionResult && )                  = default; |  | ||||||
|         AssertionResult& operator = ( AssertionResult const& ) = default; |  | ||||||
|         AssertionResult& operator = ( AssertionResult && )     = default; |  | ||||||
|  |  | ||||||
|         bool isOk() const; |         bool isOk() const; | ||||||
|         bool succeeded() const; |         bool succeeded() const; | ||||||
| @@ -87,10 +52,8 @@ namespace Catch { | |||||||
|         std::string getMessage() const; |         std::string getMessage() const; | ||||||
|         SourceLineInfo getSourceInfo() const; |         SourceLineInfo getSourceInfo() const; | ||||||
|         std::string getTestMacroName() const; |         std::string getTestMacroName() const; | ||||||
|         void discardDecomposedExpression() const; |  | ||||||
|         void expandDecomposedExpression() const; |  | ||||||
|  |  | ||||||
|     protected: |     //protected: | ||||||
|         AssertionInfo m_info; |         AssertionInfo m_info; | ||||||
|         AssertionResultData m_resultData; |         AssertionResultData m_resultData; | ||||||
|     }; |     }; | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ | |||||||
|  |  | ||||||
| #include "catch_benchmark.h" | #include "catch_benchmark.h" | ||||||
| #include "catch_capture.hpp" | #include "catch_capture.hpp" | ||||||
|  | #include "catch_interfaces_reporter.h" | ||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,14 +8,9 @@ | |||||||
| #ifndef TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED | #ifndef TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED | ||||||
| #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED | #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED | ||||||
|  |  | ||||||
| #include "catch_result_builder.h" | #include "catch_assertionhandler.h" | ||||||
| #include "catch_message.h" | #include "catch_message.h" | ||||||
| #include "catch_interfaces_capture.h" | #include "catch_interfaces_capture.h" | ||||||
| #include "catch_debugger.h" |  | ||||||
| #include "catch_common.h" |  | ||||||
| #include "catch_tostring.h" |  | ||||||
| #include "catch_interfaces_runner.h" |  | ||||||
| #include "catch_compiler_capabilities.h" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #if defined(CATCH_CONFIG_FAST_COMPILE) | #if defined(CATCH_CONFIG_FAST_COMPILE) | ||||||
| @@ -23,43 +18,45 @@ | |||||||
| // We can speedup compilation significantly by breaking into debugger lower in | // We can speedup compilation significantly by breaking into debugger lower in | ||||||
| // the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER | // the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER | ||||||
| // macro in each assertion | // macro in each assertion | ||||||
| #define INTERNAL_CATCH_REACT( resultBuilder ) \ | #define INTERNAL_CATCH_REACT( handler ) \ | ||||||
|     resultBuilder.react(); |     handler.reactWithDebugBreak(); | ||||||
|  |  | ||||||
| /////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||||
| // Another way to speed-up compilation is to omit local try-catch for REQUIRE* | // Another way to speed-up compilation is to omit local try-catch for REQUIRE* | ||||||
| // macros. | // macros. | ||||||
| // This can potentially cause false negative, if the test code catches | // This can potentially cause false negative, if the test code catches | ||||||
| // the exception before it propagates back up to the runner. | // the exception before it propagates back up to the runner. | ||||||
| #define INTERNAL_CATCH_TRY | #define INTERNAL_CATCH_TRY( capturer ) capturer.setExceptionGuard(); | ||||||
| #define INTERNAL_CATCH_CATCH( capturer, disposition ) | #define INTERNAL_CATCH_CATCH( capturer ) capturer.unsetExceptionGuard(); | ||||||
|  |  | ||||||
| #else // CATCH_CONFIG_FAST_COMPILE | #else // CATCH_CONFIG_FAST_COMPILE | ||||||
|  |  | ||||||
|  | #include "catch_debugger.h" | ||||||
|  |  | ||||||
| /////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||||
| // In the event of a failure works out if the debugger needs to be invoked | // In the event of a failure works out if the debugger needs to be invoked | ||||||
| // and/or an exception thrown and takes appropriate action. | // and/or an exception thrown and takes appropriate action. | ||||||
| // This needs to be done as a macro so the debugger will stop in the user | // This needs to be done as a macro so the debugger will stop in the user | ||||||
| // source code rather than in Catch library code | // source code rather than in Catch library code | ||||||
| #define INTERNAL_CATCH_REACT( resultBuilder ) \ | #define INTERNAL_CATCH_REACT( handler ) \ | ||||||
|     if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ |     if( handler.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ | ||||||
|     resultBuilder.react();  |     handler.reactWithoutDebugBreak(); | ||||||
|  |  | ||||||
| #define INTERNAL_CATCH_TRY try | #define INTERNAL_CATCH_TRY( capturer ) try | ||||||
| #define INTERNAL_CATCH_CATCH( capturer, disposition ) catch(...) { capturer.useActiveException( disposition ); } | #define INTERNAL_CATCH_CATCH( capturer ) catch(...) { capturer.useActiveException(); } | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||||
| #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ | #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ | ||||||
|     do { \ |     do { \ | ||||||
|         Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ |         Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ | ||||||
|         INTERNAL_CATCH_TRY { \ |         INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ | ||||||
|             CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ |             CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ | ||||||
|             ( __catchResult <= __VA_ARGS__ ).endExpression(); \ |             catchAssertionHandler.handle( Catch::Decomposer() <= __VA_ARGS__ ); \ | ||||||
|             CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ |             CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ | ||||||
|         } INTERNAL_CATCH_CATCH( __catchResult, resultDisposition ) \ |         } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ | ||||||
|         INTERNAL_CATCH_REACT( __catchResult ) \ |         INTERNAL_CATCH_REACT( catchAssertionHandler ) \ | ||||||
|     } while( Catch::isTrue( false && static_cast<bool>( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look |     } while( Catch::isTrue( false && static_cast<bool>( !!(__VA_ARGS__) ) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look | ||||||
|     // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. |     // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. | ||||||
|  |  | ||||||
| @@ -76,117 +73,84 @@ | |||||||
| /////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||||
| #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ | #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ | ||||||
|     do { \ |     do { \ | ||||||
|         Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ |         Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition ); \ | ||||||
|         try { \ |         try { \ | ||||||
|             static_cast<void>(__VA_ARGS__); \ |             static_cast<void>(__VA_ARGS__); \ | ||||||
|             __catchResult.captureResult( Catch::ResultWas::Ok ); \ |             catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ | ||||||
|         } \ |         } \ | ||||||
|         catch( ... ) { \ |         catch( ... ) { \ | ||||||
|             __catchResult.useActiveException( resultDisposition ); \ |             catchAssertionHandler.useActiveException(); \ | ||||||
|         } \ |         } \ | ||||||
|         INTERNAL_CATCH_REACT( __catchResult ) \ |         INTERNAL_CATCH_REACT( catchAssertionHandler ) \ | ||||||
|     } while( Catch::alwaysFalse() ) |     } while( Catch::alwaysFalse() ) | ||||||
|  |  | ||||||
| /////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||||
| #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ | #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ | ||||||
|     do { \ |     do { \ | ||||||
|         Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition); \ |         Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__, resultDisposition); \ | ||||||
|         if( __catchResult.allowThrows() ) \ |         if( catchAssertionHandler.allowThrows() ) \ | ||||||
|             try { \ |             try { \ | ||||||
|                 static_cast<void>(__VA_ARGS__); \ |                 static_cast<void>(__VA_ARGS__); \ | ||||||
|                 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ |                 catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ | ||||||
|             } \ |             } \ | ||||||
|             catch( ... ) { \ |             catch( ... ) { \ | ||||||
|                 __catchResult.captureExpectedException( "" ); \ |                 catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ | ||||||
|             } \ |             } \ | ||||||
|         else \ |         else \ | ||||||
|             __catchResult.captureResult( Catch::ResultWas::Ok ); \ |             catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ | ||||||
|         INTERNAL_CATCH_REACT( __catchResult ) \ |         INTERNAL_CATCH_REACT( catchAssertionHandler ) \ | ||||||
|     } while( Catch::alwaysFalse() ) |     } while( Catch::alwaysFalse() ) | ||||||
|  |  | ||||||
| /////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||||
| #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ | #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ | ||||||
|     do { \ |     do { \ | ||||||
|         Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ |         Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ | ||||||
|         if( __catchResult.allowThrows() ) \ |         if( catchAssertionHandler.allowThrows() ) \ | ||||||
|             try { \ |             try { \ | ||||||
|                 static_cast<void>(expr); \ |                 static_cast<void>(expr); \ | ||||||
|                 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ |                 catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ | ||||||
|             } \ |             } \ | ||||||
|             catch( exceptionType const& ) { \ |             catch( exceptionType const& ) { \ | ||||||
|                 __catchResult.captureResult( Catch::ResultWas::Ok ); \ |                 catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ | ||||||
|             } \ |             } \ | ||||||
|             catch( ... ) { \ |             catch( ... ) { \ | ||||||
|                 __catchResult.useActiveException( resultDisposition ); \ |                 catchAssertionHandler.useActiveException(); \ | ||||||
|             } \ |             } \ | ||||||
|         else \ |         else \ | ||||||
|             __catchResult.captureResult( Catch::ResultWas::Ok ); \ |             catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ | ||||||
|         INTERNAL_CATCH_REACT( __catchResult ) \ |         INTERNAL_CATCH_REACT( catchAssertionHandler ) \ | ||||||
|     } while( Catch::alwaysFalse() ) |     } while( Catch::alwaysFalse() ) | ||||||
|  |  | ||||||
|  |  | ||||||
| /////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||||
| #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ | #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ | ||||||
|     do { \ |     do { \ | ||||||
|         Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ |         Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ | ||||||
|         __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ |         catchAssertionHandler.handle( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str().c_str() ); \ | ||||||
|         __catchResult.captureResult( messageType ); \ |         INTERNAL_CATCH_REACT( catchAssertionHandler ) \ | ||||||
|         INTERNAL_CATCH_REACT( __catchResult ) \ |  | ||||||
|     } while( Catch::alwaysFalse() ) |     } while( Catch::alwaysFalse() ) | ||||||
|  |  | ||||||
| /////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||||
| #define INTERNAL_CATCH_INFO( macroName, log ) \ | #define INTERNAL_CATCH_INFO( macroName, log ) \ | ||||||
|     Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; |     Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; | ||||||
|  |  | ||||||
| #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) |  | ||||||
| /////////////////////////////////////////////////////////////////////////////// |  | ||||||
| #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ |  | ||||||
|     do { \ |  | ||||||
|         Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ |  | ||||||
|         INTERNAL_CATCH_TRY { \ |  | ||||||
|             __catchResult.captureMatch( arg, matcher, #matcher ); \ |  | ||||||
|         } INTERNAL_CATCH_CATCH( __catchResult, resultDisposition ) \ |  | ||||||
|         INTERNAL_CATCH_REACT( __catchResult ) \ |  | ||||||
|     } while( Catch::alwaysFalse() ) |  | ||||||
|  |  | ||||||
| /////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // Although this is matcher-based, it can be used with just a string | ||||||
| #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ | #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ | ||||||
|     do { \ |     do { \ | ||||||
|         Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #matcher, resultDisposition); \ |         Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #matcher, resultDisposition ); \ | ||||||
|         if( __catchResult.allowThrows() ) \ |         if( catchAssertionHandler.allowThrows() ) \ | ||||||
|             try { \ |             try { \ | ||||||
|                 static_cast<void>(__VA_ARGS__); \ |                 static_cast<void>(__VA_ARGS__); \ | ||||||
|                 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ |                 catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ | ||||||
|             } \ |             } \ | ||||||
|             catch( ... ) { \ |             catch( ... ) { \ | ||||||
|                 __catchResult.captureExpectedException( matcher ); \ |                 handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \ | ||||||
|             } \ |             } \ | ||||||
|         else \ |         else \ | ||||||
|             __catchResult.captureResult( Catch::ResultWas::Ok ); \ |             catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ | ||||||
|         INTERNAL_CATCH_REACT( __catchResult ) \ |         INTERNAL_CATCH_REACT( catchAssertionHandler ) \ | ||||||
|     } while( Catch::alwaysFalse() ) |     } while( Catch::alwaysFalse() ) | ||||||
|  |  | ||||||
|  |  | ||||||
| /////////////////////////////////////////////////////////////////////////////// |  | ||||||
| #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, expr ) \ |  | ||||||
|     do { \ |  | ||||||
|         Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType ", " #matcher, resultDisposition ); \ |  | ||||||
|         if( __catchResult.allowThrows() ) \ |  | ||||||
|             try { \ |  | ||||||
|                 static_cast<void>(expr); \ |  | ||||||
|                 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ |  | ||||||
|             } \ |  | ||||||
|             catch( exceptionType const& ex ) { \ |  | ||||||
|                 __catchResult.captureMatch( ex, matcher, #matcher ); \ |  | ||||||
|             } \ |  | ||||||
|             catch( ... ) { \ |  | ||||||
|                 __catchResult.useActiveException( resultDisposition ); \ |  | ||||||
|             } \ |  | ||||||
|         else \ |  | ||||||
|             __catchResult.captureResult( Catch::ResultWas::Ok ); \ |  | ||||||
|         INTERNAL_CATCH_REACT( __catchResult ) \ |  | ||||||
|     } while( Catch::alwaysFalse() ) |  | ||||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED | #endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								include/internal/catch_capture_matchers.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								include/internal/catch_capture_matchers.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | /* | ||||||
|  |  *  Created by Phil on 9/8/2017. | ||||||
|  |  *  Copyright 2017 Two Blue Cubes Ltd. All rights reserved. | ||||||
|  |  * | ||||||
|  |  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||||
|  |  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||||
|  |  */ | ||||||
|  | #include "catch_capture_matchers.h" | ||||||
|  | #include "catch_interfaces_registry_hub.h" | ||||||
|  |  | ||||||
|  | namespace Catch { | ||||||
|  |  | ||||||
|  |     using StringMatcher = Matchers::Impl::MatcherBase<std::string>; | ||||||
|  |  | ||||||
|  |     // This is the general overload that takes a any string matcher | ||||||
|  |     // There is another overload, in catch_assertinhandler.h/.cpp, that only takes a string and infers | ||||||
|  |     // the Equals matcher (so the header does not mention matchers) | ||||||
|  |     void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString  ) { | ||||||
|  |         MatchExpr<std::string, StringMatcher const&> expr( Catch::translateActiveException(), matcher, matcherString ); | ||||||
|  |         handler.handle( expr ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } // namespace Catch | ||||||
							
								
								
									
										87
									
								
								include/internal/catch_capture_matchers.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								include/internal/catch_capture_matchers.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | |||||||
|  | /* | ||||||
|  |  *  Created by Phil on 9/8/2017 | ||||||
|  |  *  Copyright 2017 Two Blue Cubes Ltd. All rights reserved. | ||||||
|  |  * | ||||||
|  |  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||||
|  |  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||||
|  |  */ | ||||||
|  | #ifndef TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED | ||||||
|  | #define TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED | ||||||
|  |  | ||||||
|  | #include "catch_capture.hpp" | ||||||
|  | #include "catch_matchers.hpp" | ||||||
|  | #include "catch_matchers_string.h" | ||||||
|  |  | ||||||
|  | namespace Catch { | ||||||
|  |  | ||||||
|  |     template<typename ArgT, typename MatcherT> | ||||||
|  |     class MatchExpr : public ITransientExpression { | ||||||
|  |         ArgT const& m_arg; | ||||||
|  |         MatcherT m_matcher; | ||||||
|  |         StringRef m_matcherString; | ||||||
|  |         bool m_result; | ||||||
|  |     public: | ||||||
|  |         MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) | ||||||
|  |         :   m_arg( arg ), | ||||||
|  |             m_matcher( matcher ), | ||||||
|  |             m_matcherString( matcherString ), | ||||||
|  |             m_result( matcher.match( arg ) ) | ||||||
|  |         {} | ||||||
|  |  | ||||||
|  |         auto isBinaryExpression() const -> bool  override { return true; } | ||||||
|  |         auto getResult() const -> bool override { return m_result; } | ||||||
|  |  | ||||||
|  |         void streamReconstructedExpression( std::ostream &os ) const override { | ||||||
|  |             auto matcherAsString = m_matcher.toString(); | ||||||
|  |             os << Catch::Detail::stringify( m_arg ) << ' '; | ||||||
|  |             if( matcherAsString == Detail::unprintableString ) | ||||||
|  |                 os << m_matcherString.c_str(); | ||||||
|  |             else | ||||||
|  |                 os << matcherAsString; | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     using StringMatcher = Matchers::Impl::MatcherBase<std::string>; | ||||||
|  |  | ||||||
|  |     void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString  ); | ||||||
|  |  | ||||||
|  |     template<typename ArgT, typename MatcherT> | ||||||
|  |     auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString  ) -> MatchExpr<ArgT, MatcherT> { | ||||||
|  |         return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } // namespace Catch | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /////////////////////////////////////////////////////////////////////////////// | ||||||
|  | #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ | ||||||
|  |     do { \ | ||||||
|  |         Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ | ||||||
|  |         INTERNAL_CATCH_TRY( catchAssertionHandler ) { \ | ||||||
|  |             catchAssertionHandler.handle( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ | ||||||
|  |         } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ | ||||||
|  |         INTERNAL_CATCH_REACT( catchAssertionHandler ) \ | ||||||
|  |     } while( Catch::alwaysFalse() ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /////////////////////////////////////////////////////////////////////////////// | ||||||
|  | #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ | ||||||
|  |     do { \ | ||||||
|  |         Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, #__VA_ARGS__ ", " #exceptionType ", " #matcher, resultDisposition ); \ | ||||||
|  |         if( catchAssertionHandler.allowThrows() ) \ | ||||||
|  |             try { \ | ||||||
|  |                 static_cast<void>(__VA_ARGS__ ); \ | ||||||
|  |                 catchAssertionHandler.handle( Catch::ResultWas::DidntThrowException ); \ | ||||||
|  |             } \ | ||||||
|  |             catch( exceptionType const& ex ) { \ | ||||||
|  |                 catchAssertionHandler.handle( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \ | ||||||
|  |             } \ | ||||||
|  |             catch( ... ) { \ | ||||||
|  |                 catchAssertionHandler.useActiveException(); \ | ||||||
|  |             } \ | ||||||
|  |         else \ | ||||||
|  |             catchAssertionHandler.handle( Catch::ResultWas::Ok ); \ | ||||||
|  |         INTERNAL_CATCH_REACT( catchAssertionHandler ) \ | ||||||
|  |     } while( Catch::alwaysFalse() ) | ||||||
|  |  | ||||||
|  | #endif // TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED | ||||||
| @@ -15,7 +15,6 @@ | |||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
|  |  | ||||||
|     SourceLineInfo::SourceLineInfo() noexcept : file(""), line( 0 ){} |  | ||||||
|     SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) noexcept |     SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) noexcept | ||||||
|     :   file( _file ), |     :   file( _file ), | ||||||
|         line( _line ) |         line( _line ) | ||||||
|   | |||||||
| @@ -47,10 +47,10 @@ namespace Catch { | |||||||
|  |  | ||||||
|     struct SourceLineInfo { |     struct SourceLineInfo { | ||||||
|  |  | ||||||
|         SourceLineInfo() noexcept; |         SourceLineInfo() = delete; | ||||||
|         SourceLineInfo( char const* _file, std::size_t _line ) noexcept; |         SourceLineInfo( char const* _file, std::size_t _line ) noexcept; | ||||||
|  |  | ||||||
|         SourceLineInfo(SourceLineInfo const& other)          = default; |         SourceLineInfo( SourceLineInfo const& other )        = default; | ||||||
|         SourceLineInfo( SourceLineInfo && )                  = default; |         SourceLineInfo( SourceLineInfo && )                  = default; | ||||||
|         SourceLineInfo& operator = ( SourceLineInfo const& ) = default; |         SourceLineInfo& operator = ( SourceLineInfo const& ) = default; | ||||||
|         SourceLineInfo& operator = ( SourceLineInfo && )     = default; |         SourceLineInfo& operator = ( SourceLineInfo && )     = default; | ||||||
|   | |||||||
							
								
								
									
										22
									
								
								include/internal/catch_decomposer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								include/internal/catch_decomposer.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | /* | ||||||
|  |  *  Created by Phil Nash on 8/8/2017. | ||||||
|  |  *  Copyright 2017 Two Blue Cubes Ltd. All rights reserved. | ||||||
|  |  * | ||||||
|  |  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||||
|  |  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "catch_decomposer.h" | ||||||
|  | #include "catch_config.hpp" | ||||||
|  |  | ||||||
|  | namespace Catch { | ||||||
|  |  | ||||||
|  |     void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ) { | ||||||
|  |         if( lhs.size() + rhs.size() < 40 && | ||||||
|  |                 lhs.find('\n') == std::string::npos && | ||||||
|  |                 rhs.find('\n') == std::string::npos ) | ||||||
|  |             os << lhs << " " << op << " " << rhs; | ||||||
|  |         else | ||||||
|  |             os << lhs << "\n" << op << "\n" << rhs; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										164
									
								
								include/internal/catch_decomposer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								include/internal/catch_decomposer.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,164 @@ | |||||||
|  | /* | ||||||
|  |  *  Created by Phil Nash on 8/8/2017. | ||||||
|  |  *  Copyright 2017 Two Blue Cubes Ltd. All rights reserved. | ||||||
|  |  * | ||||||
|  |  *  Distributed under the Boost Software License, Version 1.0. (See accompanying | ||||||
|  |  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||||
|  |  */ | ||||||
|  | #ifndef TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED | ||||||
|  | #define TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED | ||||||
|  |  | ||||||
|  | #include "catch_tostring.h" | ||||||
|  | #include "catch_stringref.h" | ||||||
|  |  | ||||||
|  | #include <ostream> | ||||||
|  |  | ||||||
|  | #ifdef _MSC_VER | ||||||
|  | #pragma warning(push) | ||||||
|  | #pragma warning(disable:4389) // '==' : signed/unsigned mismatch | ||||||
|  | #pragma warning(disable:4018) // more "signed/unsigned mismatch" | ||||||
|  | #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | namespace Catch { | ||||||
|  |  | ||||||
|  |     struct ITransientExpression { | ||||||
|  |         virtual auto isBinaryExpression() const -> bool = 0; | ||||||
|  |         virtual auto getResult() const -> bool = 0; | ||||||
|  |         virtual void streamReconstructedExpression( std::ostream &os ) const = 0; | ||||||
|  |  | ||||||
|  |         // We don't actually need a virtual destructore, but many static analysers | ||||||
|  |         // complain if it's not here :-( | ||||||
|  |         virtual ~ITransientExpression() = default; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     void formatReconstructedExpression( std::ostream &os, std::string const& lhs, std::string const& op, std::string const& rhs ); | ||||||
|  |  | ||||||
|  |     template<typename LhsT, typename RhsT> | ||||||
|  |     class BinaryExpr  : public ITransientExpression { | ||||||
|  |         bool m_result; | ||||||
|  |         LhsT m_lhs; | ||||||
|  |         std::string m_op; | ||||||
|  |         RhsT m_rhs; | ||||||
|  |  | ||||||
|  |         auto isBinaryExpression() const -> bool override { return true; } | ||||||
|  |         auto getResult() const -> bool override { return m_result; } | ||||||
|  |  | ||||||
|  |         void streamReconstructedExpression( std::ostream &os ) const override { | ||||||
|  |             formatReconstructedExpression | ||||||
|  |                     ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     public: | ||||||
|  |         BinaryExpr( bool comparisionResult, LhsT lhs, StringRef op, RhsT rhs ) | ||||||
|  |         :   m_result( comparisionResult ), | ||||||
|  |             m_lhs( lhs ), | ||||||
|  |             m_op( op.c_str() ), | ||||||
|  |             m_rhs( rhs ) | ||||||
|  |         {} | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     template<typename LhsT> | ||||||
|  |     class UnaryExpr : public ITransientExpression { | ||||||
|  |         LhsT m_lhs; | ||||||
|  |  | ||||||
|  |         auto isBinaryExpression() const -> bool override { return false; } | ||||||
|  |         auto getResult() const -> bool override { return m_lhs ? true : false; } | ||||||
|  |  | ||||||
|  |         void streamReconstructedExpression( std::ostream &os ) const override { | ||||||
|  |             os << Catch::Detail::stringify( m_lhs ); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     public: | ||||||
|  |         UnaryExpr( LhsT lhs ) : m_lhs( lhs ) {} | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) | ||||||
|  |     template<typename LhsT, typename RhsT> | ||||||
|  |     auto compareEqual( LhsT lhs, RhsT&& rhs ) -> bool { return lhs == rhs; }; | ||||||
|  |     template<typename T> | ||||||
|  |     auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }; | ||||||
|  |     template<typename T> | ||||||
|  |     auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }; | ||||||
|  |  | ||||||
|  |     template<typename LhsT, typename RhsT> | ||||||
|  |     auto compareNotEqual( LhsT lhs, RhsT&& rhs ) -> bool { return lhs != rhs; }; | ||||||
|  |     template<typename T> | ||||||
|  |     auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }; | ||||||
|  |     template<typename T> | ||||||
|  |     auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     template<typename LhsT> | ||||||
|  |     class ExprLhs { | ||||||
|  |         LhsT m_lhs; | ||||||
|  |     public: | ||||||
|  |         ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} | ||||||
|  |  | ||||||
|  |         template<typename RhsT> | ||||||
|  |         auto operator == ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const { | ||||||
|  |             return BinaryExpr<LhsT, RhsT&>( compareEqual( m_lhs, rhs ), m_lhs, "==", rhs ); | ||||||
|  |         } | ||||||
|  |         auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const { | ||||||
|  |             return BinaryExpr<LhsT, bool>( m_lhs == rhs, m_lhs, "==", rhs ); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         template<typename RhsT> | ||||||
|  |         auto operator != ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const { | ||||||
|  |             return BinaryExpr<LhsT, RhsT&>( compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs ); | ||||||
|  |         } | ||||||
|  |         auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const { | ||||||
|  |             return BinaryExpr<LhsT, bool>( m_lhs != rhs, m_lhs, "!=", rhs ); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         template<typename RhsT> | ||||||
|  |         auto operator > ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const { | ||||||
|  |             return BinaryExpr<LhsT, RhsT&>( m_lhs > rhs, m_lhs, ">", rhs ); | ||||||
|  |         } | ||||||
|  |         template<typename RhsT> | ||||||
|  |         auto operator < ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const { | ||||||
|  |             return BinaryExpr<LhsT, RhsT&>( m_lhs < rhs, m_lhs, "<", rhs ); | ||||||
|  |         } | ||||||
|  |         template<typename RhsT> | ||||||
|  |         auto operator >= ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const { | ||||||
|  |             return BinaryExpr<LhsT, RhsT&>( m_lhs >= rhs, m_lhs, ">=", rhs ); | ||||||
|  |         } | ||||||
|  |         template<typename RhsT> | ||||||
|  |         auto operator <= ( RhsT&& rhs ) -> BinaryExpr<LhsT, RhsT&> const { | ||||||
|  |             return BinaryExpr<LhsT, RhsT&>( m_lhs <= rhs, m_lhs, "<=", rhs ); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         auto makeUnaryExpr() const -> UnaryExpr<LhsT> { | ||||||
|  |             return UnaryExpr<LhsT>( m_lhs ); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     void handleExpression( ITransientExpression const& expr ); | ||||||
|  |  | ||||||
|  |     template<typename T> | ||||||
|  |     void handleExpression( ExprLhs<T> const& expr ) { | ||||||
|  |         handleExpression( expr.makeUnaryExpr() ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     struct Decomposer { | ||||||
|  |         template<typename T> | ||||||
|  |         auto operator <= ( T& lhs ) -> ExprLhs<T&> { | ||||||
|  |             return ExprLhs<T&>( lhs ); | ||||||
|  |         } | ||||||
|  |         template<typename T> | ||||||
|  |         auto operator <= ( T const& lhs ) -> ExprLhs<T const&> { | ||||||
|  |             return ExprLhs<T const&>( lhs ); | ||||||
|  |         } | ||||||
|  |         auto operator <=( bool value ) -> ExprLhs<bool> { | ||||||
|  |             return ExprLhs<bool>( value ); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  | } // end namespace Catch | ||||||
|  |  | ||||||
|  | #ifdef _MSC_VER | ||||||
|  | #pragma warning(pop) | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif // TWOBLUECUBES_CATCH_DECOMPOSER_H_INCLUDED | ||||||
| @@ -1,38 +0,0 @@ | |||||||
| /* |  | ||||||
|  *  Created by Martin on 01/08/2017. |  | ||||||
|  * |  | ||||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying |  | ||||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #include "catch_evaluate.hpp" |  | ||||||
|  |  | ||||||
| #include "catch_enforce.h" |  | ||||||
|  |  | ||||||
| namespace Catch { |  | ||||||
| namespace Internal { |  | ||||||
|  |  | ||||||
|     const char* operatorName(Operator op) { |  | ||||||
|         switch (op) { |  | ||||||
|             case IsEqualTo: |  | ||||||
|                 return "=="; |  | ||||||
|             case IsNotEqualTo: |  | ||||||
|                 return "!="; |  | ||||||
|             case IsLessThan: |  | ||||||
|                 return "<"; |  | ||||||
|             case IsGreaterThan: |  | ||||||
|                 return ">"; |  | ||||||
|             case IsLessThanOrEqualTo: |  | ||||||
|                 return "<="; |  | ||||||
|             case IsGreaterThanOrEqualTo: |  | ||||||
|                 return ">="; |  | ||||||
|             default: |  | ||||||
|                 CATCH_ERROR("Attempting to translate unknown operator!"); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // nullptr_t support based on pull request #154 from Konstantin Baumann |  | ||||||
|     std::nullptr_t opCast(std::nullptr_t) { return nullptr; } |  | ||||||
|  |  | ||||||
| } // end of namespace Internal |  | ||||||
| } // end of namespace Catch |  | ||||||
| @@ -1,109 +0,0 @@ | |||||||
| /* |  | ||||||
|  *  Created by Phil on 04/03/2011. |  | ||||||
|  *  Copyright 2011 Two Blue Cubes Ltd. All rights reserved. |  | ||||||
|  * |  | ||||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying |  | ||||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |  | ||||||
|  */ |  | ||||||
| #ifndef TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED |  | ||||||
| #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED |  | ||||||
|  |  | ||||||
| #ifdef _MSC_VER |  | ||||||
| #pragma warning(push) |  | ||||||
| #pragma warning(disable:4389) // '==' : signed/unsigned mismatch |  | ||||||
| #pragma warning(disable:4018) // more "signed/unsigned mismatch" |  | ||||||
| #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #include <cstddef> |  | ||||||
|  |  | ||||||
| namespace Catch { |  | ||||||
| namespace Internal { |  | ||||||
|  |  | ||||||
|     enum Operator { |  | ||||||
|         IsEqualTo, |  | ||||||
|         IsNotEqualTo, |  | ||||||
|         IsLessThan, |  | ||||||
|         IsGreaterThan, |  | ||||||
|         IsLessThanOrEqualTo, |  | ||||||
|         IsGreaterThanOrEqualTo |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     const char* operatorName(Operator op); |  | ||||||
|  |  | ||||||
|     template<typename T> |  | ||||||
|     T& removeConst(T const &t) { return const_cast<T&>(t); } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     // So the compare overloads can be operator agnostic we convey the operator as a template |  | ||||||
|     // enum, which is used to specialise an Evaluator for doing the comparison. |  | ||||||
|     template<Operator Op> |  | ||||||
|     struct Evaluator{}; |  | ||||||
|  |  | ||||||
|     template<> |  | ||||||
|     struct Evaluator<IsEqualTo> { |  | ||||||
|         template<typename T1, typename T2> |  | ||||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs) { |  | ||||||
|             return bool(removeConst(lhs) == removeConst(rhs) ); |  | ||||||
|         } |  | ||||||
|         template<typename T> |  | ||||||
|         static bool evaluate( int lhs, T* rhs) { |  | ||||||
|             return reinterpret_cast<void const*>( lhs ) ==  rhs; |  | ||||||
|         } |  | ||||||
|         template<typename T> |  | ||||||
|         static bool evaluate( T* lhs, int rhs) { |  | ||||||
|             return lhs == reinterpret_cast<void const*>( rhs ); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     template<> |  | ||||||
|     struct Evaluator<IsNotEqualTo> { |  | ||||||
|         template<typename T1, typename T2> |  | ||||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { |  | ||||||
|             return bool(removeConst(lhs) != removeConst(rhs) ); |  | ||||||
|         } |  | ||||||
|         template<typename T> |  | ||||||
|         static bool evaluate( int lhs, T* rhs) { |  | ||||||
|             return reinterpret_cast<void const*>( lhs ) !=  rhs; |  | ||||||
|         } |  | ||||||
|         template<typename T> |  | ||||||
|         static bool evaluate( T* lhs, int rhs) { |  | ||||||
|             return lhs != reinterpret_cast<void const*>( rhs ); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     template<> |  | ||||||
|     struct Evaluator<IsLessThan> { |  | ||||||
|         template<typename T1, typename T2> |  | ||||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { |  | ||||||
|             return bool(removeConst(lhs) < removeConst(rhs) ); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     template<> |  | ||||||
|     struct Evaluator<IsGreaterThan> { |  | ||||||
|         template<typename T1, typename T2> |  | ||||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { |  | ||||||
|             return bool(removeConst(lhs) > removeConst(rhs) ); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     template<> |  | ||||||
|     struct Evaluator<IsGreaterThanOrEqualTo> { |  | ||||||
|         template<typename T1, typename T2> |  | ||||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { |  | ||||||
|             return bool(removeConst(lhs) >= removeConst(rhs) ); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     template<> |  | ||||||
|     struct Evaluator<IsLessThanOrEqualTo> { |  | ||||||
|         template<typename T1, typename T2> |  | ||||||
|         static bool evaluate( T1 const& lhs, T2 const& rhs ) { |  | ||||||
|             return bool(removeConst(lhs) <= removeConst(rhs) ); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
| } // end of namespace Internal |  | ||||||
| } // end of namespace Catch |  | ||||||
|  |  | ||||||
| #ifdef _MSC_VER |  | ||||||
| #pragma warning(pop) |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #endif // TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED |  | ||||||
| @@ -6,8 +6,8 @@ | |||||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | #include "catch_assertionhandler.h" | ||||||
| #include "catch_exception_translator_registry.h" | #include "catch_exception_translator_registry.h" | ||||||
| #include "catch_result_builder.h" |  | ||||||
|  |  | ||||||
| #ifdef __OBJC__ | #ifdef __OBJC__ | ||||||
| #import "Foundation/Foundation.h" | #import "Foundation/Foundation.h" | ||||||
|   | |||||||
| @@ -1,176 +0,0 @@ | |||||||
| /* |  | ||||||
|  *  Created by Phil on 11/5/2012. |  | ||||||
|  *  Copyright 2012 Two Blue Cubes Ltd. All rights reserved. |  | ||||||
|  * |  | ||||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying |  | ||||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |  | ||||||
|  */ |  | ||||||
| #ifndef TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED |  | ||||||
| #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED |  | ||||||
|  |  | ||||||
| #include "catch_result_builder.h" |  | ||||||
| #include "catch_evaluate.hpp" |  | ||||||
| #include "catch_tostring.h" |  | ||||||
|  |  | ||||||
| namespace Catch { |  | ||||||
|  |  | ||||||
| template<typename LhsT, Internal::Operator Op, typename RhsT> |  | ||||||
| class BinaryExpression; |  | ||||||
|  |  | ||||||
| template<typename ArgT, typename MatcherT> |  | ||||||
| class MatchExpression; |  | ||||||
|  |  | ||||||
| // Wraps the LHS of an expression and overloads comparison operators |  | ||||||
| // for also capturing those and RHS (if any) |  | ||||||
| template<typename T> |  | ||||||
| class ExpressionLhs : public DecomposedExpression { |  | ||||||
| public: |  | ||||||
|     ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} |  | ||||||
|  |  | ||||||
|     ExpressionLhs( ExpressionLhs const& ) = default; |  | ||||||
|     ExpressionLhs& operator = ( const ExpressionLhs& ) = delete; |  | ||||||
|  |  | ||||||
|     template<typename RhsT> |  | ||||||
|     BinaryExpression<T, Internal::IsEqualTo, RhsT const&> |  | ||||||
|     operator == ( RhsT const& rhs ) { |  | ||||||
|         return captureExpression<Internal::IsEqualTo>( rhs ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     template<typename RhsT> |  | ||||||
|     BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&> |  | ||||||
|     operator != ( RhsT const& rhs ) { |  | ||||||
|         return captureExpression<Internal::IsNotEqualTo>( rhs ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     template<typename RhsT> |  | ||||||
|     BinaryExpression<T, Internal::IsLessThan, RhsT const&> |  | ||||||
|     operator < ( RhsT const& rhs ) { |  | ||||||
|         return captureExpression<Internal::IsLessThan>( rhs ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     template<typename RhsT> |  | ||||||
|     BinaryExpression<T, Internal::IsGreaterThan, RhsT const&> |  | ||||||
|     operator > ( RhsT const& rhs ) { |  | ||||||
|         return captureExpression<Internal::IsGreaterThan>( rhs ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     template<typename RhsT> |  | ||||||
|     BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&> |  | ||||||
|     operator <= ( RhsT const& rhs ) { |  | ||||||
|         return captureExpression<Internal::IsLessThanOrEqualTo>( rhs ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     template<typename RhsT> |  | ||||||
|     BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&> |  | ||||||
|     operator >= ( RhsT const& rhs ) { |  | ||||||
|         return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) { |  | ||||||
|         return captureExpression<Internal::IsEqualTo>( rhs ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) { |  | ||||||
|         return captureExpression<Internal::IsNotEqualTo>( rhs ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void endExpression() { |  | ||||||
|         m_truthy = m_lhs ? true : false; |  | ||||||
|         m_rb |  | ||||||
|             .setResultType( m_truthy ) |  | ||||||
|             .endExpression( *this ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void reconstructExpression( std::string& dest ) const override { |  | ||||||
|         dest = ::Catch::Detail::stringify( m_lhs ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| private: |  | ||||||
|     template<Internal::Operator Op, typename RhsT> |  | ||||||
|     BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const { |  | ||||||
|         return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     template<Internal::Operator Op> |  | ||||||
|     BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const { |  | ||||||
|         return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| private: |  | ||||||
|     ResultBuilder& m_rb; |  | ||||||
|     T m_lhs; |  | ||||||
|     bool m_truthy = false; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template<typename LhsT, Internal::Operator Op, typename RhsT> |  | ||||||
| class BinaryExpression : public DecomposedExpression { |  | ||||||
| public: |  | ||||||
|     BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs ) |  | ||||||
|         : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {} |  | ||||||
|  |  | ||||||
|     BinaryExpression( BinaryExpression const& ) = default; |  | ||||||
|     BinaryExpression& operator = ( BinaryExpression const& ) = delete; |  | ||||||
|  |  | ||||||
|     void endExpression() const { |  | ||||||
|         m_rb |  | ||||||
|             .setResultType(  Internal::Evaluator<Op>::evaluate( m_lhs, m_rhs ) ) |  | ||||||
|             .endExpression( *this ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool isBinaryExpression() const override { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void reconstructExpression( std::string& dest ) const override { |  | ||||||
|         std::string lhs = ::Catch::Detail::stringify( m_lhs ); |  | ||||||
|         std::string rhs = ::Catch::Detail::stringify( m_rhs ); |  | ||||||
|         char delim = lhs.size() + rhs.size() < 40 && |  | ||||||
|                      lhs.find('\n') == std::string::npos && |  | ||||||
|                      rhs.find('\n') == std::string::npos ? ' ' : '\n'; |  | ||||||
|         dest.reserve( 7 + lhs.size() + rhs.size() ); |  | ||||||
|                    // 2 for spaces around operator |  | ||||||
|                    // 2 for operator |  | ||||||
|                    // 2 for parentheses (conditionally added later) |  | ||||||
|                    // 1 for negation (conditionally added later) |  | ||||||
|         dest = lhs; |  | ||||||
|         dest += delim; |  | ||||||
|         dest += Internal::operatorName(Op); |  | ||||||
|         dest += delim; |  | ||||||
|         dest += rhs; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| private: |  | ||||||
|     ResultBuilder& m_rb; |  | ||||||
|     LhsT m_lhs; |  | ||||||
|     RhsT m_rhs; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| template<typename ArgT, typename MatcherT> |  | ||||||
| class MatchExpression : public DecomposedExpression { |  | ||||||
| public: |  | ||||||
|     MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString ) |  | ||||||
|         : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {} |  | ||||||
|  |  | ||||||
|     bool isBinaryExpression() const override { |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void reconstructExpression( std::string& dest ) const override { |  | ||||||
|         std::string matcherAsString = m_matcher.toString(); |  | ||||||
|         dest = ::Catch::Detail::stringify( m_arg ); |  | ||||||
|         dest += ' '; |  | ||||||
|         if( matcherAsString == Detail::unprintableString ) |  | ||||||
|             dest += m_matcherString; |  | ||||||
|         else |  | ||||||
|             dest += matcherAsString; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| private: |  | ||||||
|     ArgT m_arg; |  | ||||||
|     MatcherT m_matcher; |  | ||||||
|     char const* m_matcherString; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| } // end namespace Catch |  | ||||||
|  |  | ||||||
| #endif // TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED |  | ||||||
| @@ -9,9 +9,6 @@ | |||||||
| #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED | #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED | ||||||
|  |  | ||||||
| #include <string> | #include <string> | ||||||
| #include "catch_result_type.h" |  | ||||||
| #include "catch_common.h" |  | ||||||
| #include "catch_interfaces_reporter.h" |  | ||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
|  |  | ||||||
| @@ -23,6 +20,8 @@ namespace Catch { | |||||||
|     struct MessageInfo; |     struct MessageInfo; | ||||||
|     class ScopedMessageBuilder; |     class ScopedMessageBuilder; | ||||||
|     struct Counts; |     struct Counts; | ||||||
|  |     struct BenchmarkInfo; | ||||||
|  |     struct BenchmarkStats; | ||||||
|  |  | ||||||
|     struct IResultCapture { |     struct IResultCapture { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -37,10 +37,12 @@ namespace Catch { | |||||||
|         infoMessages( _infoMessages ), |         infoMessages( _infoMessages ), | ||||||
|         totals( _totals ) |         totals( _totals ) | ||||||
|     { |     { | ||||||
|  |         assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression; | ||||||
|  |  | ||||||
|         if( assertionResult.hasMessage() ) { |         if( assertionResult.hasMessage() ) { | ||||||
|             // Copy message into messages list. |             // Copy message into messages list. | ||||||
|             // !TBD This should have been done earlier, somewhere |             // !TBD This should have been done earlier, somewhere | ||||||
|             MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); |             MessageBuilder builder( assertionResult.getTestMacroName().c_str(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); | ||||||
|             builder << assertionResult.getMessage(); |             builder << assertionResult.getMessage(); | ||||||
|             builder.m_info.message = builder.m_stream.str(); |             builder.m_info.message = builder.m_stream.str(); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,8 +5,6 @@ | |||||||
|  * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |  * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) |  | ||||||
|  |  | ||||||
| #include "catch_matchers.hpp" | #include "catch_matchers.hpp" | ||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
| @@ -26,5 +24,3 @@ using namespace Matchers; | |||||||
| using Matchers::Impl::MatcherBase; | using Matchers::Impl::MatcherBase; | ||||||
|  |  | ||||||
| } // namespace Catch | } // namespace Catch | ||||||
|  |  | ||||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS |  | ||||||
| @@ -8,8 +8,6 @@ | |||||||
| #ifndef TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED | #ifndef TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED | ||||||
| #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED | #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED | ||||||
|  |  | ||||||
| #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) |  | ||||||
|  |  | ||||||
| #include "catch_common.h" | #include "catch_common.h" | ||||||
|  |  | ||||||
| #include <string> | #include <string> | ||||||
| @@ -182,6 +180,4 @@ using Matchers::Impl::MatcherBase; | |||||||
|  |  | ||||||
| } // namespace Catch | } // namespace Catch | ||||||
|  |  | ||||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS |  | ||||||
|  |  | ||||||
| #endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED | #endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED | ||||||
|   | |||||||
| @@ -6,8 +6,6 @@ | |||||||
|  * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |  * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) |  | ||||||
|  |  | ||||||
| #include "catch_matchers_string.h" | #include "catch_matchers_string.h" | ||||||
| #include "catch_string_manip.h" | #include "catch_string_manip.h" | ||||||
|  |  | ||||||
| @@ -94,5 +92,3 @@ namespace Matchers { | |||||||
|  |  | ||||||
| } // namespace Matchers | } // namespace Matchers | ||||||
| } // namespace Catch | } // namespace Catch | ||||||
|  |  | ||||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS |  | ||||||
|   | |||||||
| @@ -8,8 +8,6 @@ | |||||||
| #ifndef TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED | #ifndef TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED | ||||||
| #define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED | #define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED | ||||||
|  |  | ||||||
| #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) |  | ||||||
|  |  | ||||||
| #include "catch_matchers.hpp" | #include "catch_matchers.hpp" | ||||||
|  |  | ||||||
| #include <string> | #include <string> | ||||||
| @@ -68,6 +66,4 @@ namespace Matchers { | |||||||
| } // namespace Matchers | } // namespace Matchers | ||||||
| } // namespace Catch | } // namespace Catch | ||||||
|  |  | ||||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS |  | ||||||
|  |  | ||||||
| #endif // TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED | #endif // TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED | ||||||
|   | |||||||
| @@ -8,9 +8,6 @@ | |||||||
| #ifndef TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED | #ifndef TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED | ||||||
| #define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED | #define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED | ||||||
|  |  | ||||||
| #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #include "catch_matchers.hpp" | #include "catch_matchers.hpp" | ||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
| @@ -115,6 +112,4 @@ namespace Matchers { | |||||||
| } // namespace Matchers | } // namespace Matchers | ||||||
| } // namespace Catch | } // namespace Catch | ||||||
|  |  | ||||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS |  | ||||||
|  |  | ||||||
| #endif // TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED | #endif // TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED | ||||||
|   | |||||||
| @@ -32,7 +32,19 @@ namespace Catch { | |||||||
|         static unsigned int globalCount; |         static unsigned int globalCount; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     struct MessageBuilder { |     struct MessageStream { | ||||||
|  |  | ||||||
|  |         template<typename T> | ||||||
|  |         MessageStream& operator << ( T const& value ) { | ||||||
|  |             m_stream << value; | ||||||
|  |             return *this; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // !TBD reuse a global/ thread-local stream | ||||||
|  |         std::ostringstream m_stream; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     struct MessageBuilder : MessageStream { | ||||||
|         MessageBuilder( std::string const& macroName, |         MessageBuilder( std::string const& macroName, | ||||||
|                         SourceLineInfo const& lineInfo, |                         SourceLineInfo const& lineInfo, | ||||||
|                         ResultWas::OfType type ); |                         ResultWas::OfType type ); | ||||||
| @@ -44,7 +56,6 @@ namespace Catch { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         MessageInfo m_info; |         MessageInfo m_info; | ||||||
|         std::ostringstream m_stream; |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     class ScopedMessage { |     class ScopedMessage { | ||||||
|   | |||||||
| @@ -11,8 +11,7 @@ | |||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
|  |  | ||||||
|     NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) |     NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) { | ||||||
|     :   m_lineInfo( lineInfo ) { |  | ||||||
|         std::ostringstream oss; |         std::ostringstream oss; | ||||||
|         oss << lineInfo << ": function "; |         oss << lineInfo << ": function "; | ||||||
|         oss << "not implemented"; |         oss << "not implemented"; | ||||||
|   | |||||||
| @@ -25,7 +25,6 @@ namespace Catch { | |||||||
|  |  | ||||||
|     private: |     private: | ||||||
|         std::string m_what; |         std::string m_what; | ||||||
|         SourceLineInfo m_lineInfo; |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| } // end namespace Catch | } // end namespace Catch | ||||||
|   | |||||||
| @@ -1,193 +0,0 @@ | |||||||
| /* |  | ||||||
|  *  Created by Phil on 28/5/2014. |  | ||||||
|  *  Copyright 2014 Two Blue Cubes Ltd. All rights reserved. |  | ||||||
|  * |  | ||||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying |  | ||||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| #include "catch_result_builder.h" |  | ||||||
| #include "catch_context.h" |  | ||||||
| #include "catch_interfaces_config.h" |  | ||||||
| #include "catch_interfaces_runner.h" |  | ||||||
| #include "catch_interfaces_capture.h" |  | ||||||
| #include "catch_interfaces_registry_hub.h" |  | ||||||
| #include "catch_matchers_string.h" |  | ||||||
| #include "catch_wildcard_pattern.hpp" |  | ||||||
| #include "catch_debugger.h" |  | ||||||
|  |  | ||||||
| #include <cassert> |  | ||||||
|  |  | ||||||
| namespace Catch { |  | ||||||
|  |  | ||||||
|     CopyableStream::CopyableStream( CopyableStream const& other ) { |  | ||||||
|         oss << other.oss.str(); |  | ||||||
|     } |  | ||||||
|     CopyableStream& CopyableStream::operator=( CopyableStream const& other ) { |  | ||||||
|         oss.str(std::string()); |  | ||||||
|         oss << other.oss.str(); |  | ||||||
|         return *this; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     ResultBuilder::ResultBuilder(   char const* macroName, |  | ||||||
|                                     SourceLineInfo const& lineInfo, |  | ||||||
|                                     char const* capturedExpression, |  | ||||||
|                                     ResultDisposition::Flags resultDisposition ) |  | ||||||
|     :   m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition) |  | ||||||
|     { |  | ||||||
|         getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     ResultBuilder::~ResultBuilder() { |  | ||||||
| #if defined(CATCH_CONFIG_FAST_COMPILE) |  | ||||||
|         if ( m_guardException ) { |  | ||||||
|             stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; |  | ||||||
|             captureResult( ResultWas::ThrewException ); |  | ||||||
|             getCurrentContext().getResultCapture()->exceptionEarlyReported(); |  | ||||||
|         } |  | ||||||
| #endif |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { |  | ||||||
|         m_data.resultType = result; |  | ||||||
|         return *this; |  | ||||||
|     } |  | ||||||
|     ResultBuilder& ResultBuilder::setResultType( bool result ) { |  | ||||||
|         m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; |  | ||||||
|         return *this; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void ResultBuilder::endExpression( DecomposedExpression const& expr ) { |  | ||||||
|         // Flip bool results if FalseTest flag is set |  | ||||||
|         if( isFalseTest( m_assertionInfo.resultDisposition ) ) { |  | ||||||
|             m_data.negate( expr.isBinaryExpression() ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         getResultCapture().assertionRun(); |  | ||||||
|  |  | ||||||
|         if(getCurrentContext().getConfig()->includeSuccessfulResults() |  | ||||||
|             || m_data.resultType != ResultWas::Ok) { |  | ||||||
|             AssertionResult result = build( expr ); |  | ||||||
|             handleResult( result ); |  | ||||||
|         } |  | ||||||
|         else |  | ||||||
|             getResultCapture().assertionPassed(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { |  | ||||||
|         m_assertionInfo.resultDisposition = resultDisposition; |  | ||||||
|         stream().oss << Catch::translateActiveException(); |  | ||||||
|         captureResult( ResultWas::ThrewException ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void ResultBuilder::captureResult( ResultWas::OfType resultType ) { |  | ||||||
|         setResultType( resultType ); |  | ||||||
|         captureExpression(); |  | ||||||
|     } |  | ||||||
| #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) |  | ||||||
|     void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { |  | ||||||
|         if( expectedMessage.empty() ) |  | ||||||
|             captureExpectedException( Matchers::Impl::MatchAllOf<std::string>() ); |  | ||||||
|         else |  | ||||||
|             captureExpectedException( Matchers::Equals( expectedMessage ) ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher ) { |  | ||||||
|  |  | ||||||
|         assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); |  | ||||||
|         AssertionResultData data = m_data; |  | ||||||
|         data.resultType = ResultWas::Ok; |  | ||||||
|         data.reconstructedExpression = m_assertionInfo.capturedExpression; |  | ||||||
|  |  | ||||||
|         std::string actualMessage = Catch::translateActiveException(); |  | ||||||
|         if( !matcher.match( actualMessage ) ) { |  | ||||||
|             data.resultType = ResultWas::ExpressionFailed; |  | ||||||
|             data.reconstructedExpression = std::move(actualMessage); |  | ||||||
|         } |  | ||||||
|         AssertionResult result( m_assertionInfo, data ); |  | ||||||
|         handleResult( result ); |  | ||||||
|     } |  | ||||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS |  | ||||||
|     void ResultBuilder::captureExpression() { |  | ||||||
|         AssertionResult result = build(); |  | ||||||
|         handleResult( result ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void ResultBuilder::handleResult( AssertionResult const& result ) |  | ||||||
|     { |  | ||||||
|         getResultCapture().assertionEnded( result ); |  | ||||||
|  |  | ||||||
|         if( !result.isOk() ) { |  | ||||||
|             if( getCurrentContext().getConfig()->shouldDebugBreak() ) |  | ||||||
|                 m_shouldDebugBreak = true; |  | ||||||
|             if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) |  | ||||||
|                 m_shouldThrow = true; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void ResultBuilder::react() { |  | ||||||
| #if defined(CATCH_CONFIG_FAST_COMPILE) |  | ||||||
|         if (m_shouldDebugBreak) { |  | ||||||
|             /////////////////////////////////////////////////////////////////// |  | ||||||
|             // To inspect the state during test, you need to go one level up the callstack |  | ||||||
|             // To go back to the test and change execution, jump over the throw statement |  | ||||||
|             /////////////////////////////////////////////////////////////////// |  | ||||||
|             CATCH_BREAK_INTO_DEBUGGER(); |  | ||||||
|         } |  | ||||||
| #endif |  | ||||||
|         if( m_shouldThrow ) |  | ||||||
|             throw Catch::TestFailureException(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } |  | ||||||
|     bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } |  | ||||||
|  |  | ||||||
|     AssertionResult ResultBuilder::build() const |  | ||||||
|     { |  | ||||||
|         return build( *this ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // CAVEAT: The returned AssertionResult stores a pointer to the argument expr, |  | ||||||
|     //         a temporary DecomposedExpression, which in turn holds references to |  | ||||||
|     //         operands, possibly temporary as well. |  | ||||||
|     //         It should immediately be passed to handleResult; if the expression |  | ||||||
|     //         needs to be reported, its string expansion must be composed before |  | ||||||
|     //         the temporaries are destroyed. |  | ||||||
|     AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const { |  | ||||||
|         assert( m_data.resultType != ResultWas::Unknown ); |  | ||||||
|         AssertionResultData data = m_data; |  | ||||||
|  |  | ||||||
|         if(m_usedStream) |  | ||||||
|             data.message = s_stream().oss.str(); |  | ||||||
|         data.decomposedExpression = &expr; // for lazy reconstruction |  | ||||||
|         return AssertionResult( m_assertionInfo, data ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void ResultBuilder::reconstructExpression( std::string& dest ) const { |  | ||||||
|         dest = m_assertionInfo.capturedExpression; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void ResultBuilder::setExceptionGuard() { |  | ||||||
|         m_guardException = true; |  | ||||||
|     } |  | ||||||
|     void ResultBuilder::unsetExceptionGuard() { |  | ||||||
|         m_guardException = false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     CopyableStream& ResultBuilder::stream() { |  | ||||||
|         if( !m_usedStream ) { |  | ||||||
|             m_usedStream = true; |  | ||||||
|             s_stream().oss.str(""); |  | ||||||
|         } |  | ||||||
|         return s_stream(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     CopyableStream& ResultBuilder::s_stream() { |  | ||||||
|         static CopyableStream s; |  | ||||||
|         return s; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } // end namespace Catch |  | ||||||
| @@ -1,118 +0,0 @@ | |||||||
| /* |  | ||||||
|  *  Created by Phil on 28/5/2014. |  | ||||||
|  *  Copyright 2014 Two Blue Cubes Ltd. All rights reserved. |  | ||||||
|  * |  | ||||||
|  *  Distributed under the Boost Software License, Version 1.0. (See accompanying |  | ||||||
|  *  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |  | ||||||
|  */ |  | ||||||
| #ifndef TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED |  | ||||||
| #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED |  | ||||||
|  |  | ||||||
| #include "catch_result_type.h" |  | ||||||
| #include "catch_assertionresult.h" |  | ||||||
| #include "catch_common.h" |  | ||||||
| #include "catch_matchers.hpp" |  | ||||||
|  |  | ||||||
| #include <sstream> |  | ||||||
|  |  | ||||||
| namespace Catch { |  | ||||||
|  |  | ||||||
|     struct TestFailureException{}; |  | ||||||
|  |  | ||||||
|     template<typename T> class ExpressionLhs; |  | ||||||
|  |  | ||||||
|     struct CopyableStream { |  | ||||||
|         CopyableStream() = default; |  | ||||||
|         CopyableStream( CopyableStream const& other ); |  | ||||||
|         CopyableStream& operator=( CopyableStream const& other ); |  | ||||||
|  |  | ||||||
|         std::ostringstream oss; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     class ResultBuilder : public DecomposedExpression { |  | ||||||
|     public: |  | ||||||
|         ResultBuilder(  char const* macroName, |  | ||||||
|                         SourceLineInfo const& lineInfo, |  | ||||||
|                         char const* capturedExpression, |  | ||||||
|                         ResultDisposition::Flags resultDisposition); |  | ||||||
|         ~ResultBuilder(); |  | ||||||
|  |  | ||||||
|         template<typename T> |  | ||||||
|         ExpressionLhs<T const&> operator <= ( T const& operand ); |  | ||||||
|         ExpressionLhs<bool> operator <= ( bool value ); |  | ||||||
|  |  | ||||||
|         template<typename T> |  | ||||||
|         ResultBuilder& operator << ( T const& value ) { |  | ||||||
|             stream().oss << value; |  | ||||||
|             return *this; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         ResultBuilder& setResultType( ResultWas::OfType result ); |  | ||||||
|         ResultBuilder& setResultType( bool result ); |  | ||||||
|  |  | ||||||
|         void endExpression( DecomposedExpression const& expr ); |  | ||||||
|  |  | ||||||
|         void reconstructExpression( std::string& dest ) const override; |  | ||||||
|  |  | ||||||
|         AssertionResult build() const; |  | ||||||
|         AssertionResult build( DecomposedExpression const& expr ) const; |  | ||||||
|  |  | ||||||
|         void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); |  | ||||||
|         void captureResult( ResultWas::OfType resultType ); |  | ||||||
|         void captureExpression(); |  | ||||||
| #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) |  | ||||||
|         void captureExpectedException( std::string const& expectedMessage ); |  | ||||||
|         void captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher ); |  | ||||||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS |  | ||||||
|         void handleResult( AssertionResult const& result ); |  | ||||||
|         void react(); |  | ||||||
|         bool shouldDebugBreak() const; |  | ||||||
|         bool allowThrows() const; |  | ||||||
|  |  | ||||||
|         template<typename ArgT, typename MatcherT> |  | ||||||
|         void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ); |  | ||||||
|  |  | ||||||
|         void setExceptionGuard(); |  | ||||||
|         void unsetExceptionGuard(); |  | ||||||
|  |  | ||||||
|     private: |  | ||||||
|         AssertionInfo m_assertionInfo; |  | ||||||
|         AssertionResultData m_data; |  | ||||||
|  |  | ||||||
|         CopyableStream& stream(); |  | ||||||
|         static CopyableStream& s_stream(); |  | ||||||
|  |  | ||||||
|         bool m_shouldDebugBreak = false; |  | ||||||
|         bool m_shouldThrow = false; |  | ||||||
|         bool m_guardException = false; |  | ||||||
|         bool m_usedStream = false; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
| } // namespace Catch |  | ||||||
|  |  | ||||||
| // Include after due to circular dependency: |  | ||||||
| #include "catch_expression_lhs.hpp" |  | ||||||
|  |  | ||||||
| namespace Catch { |  | ||||||
|  |  | ||||||
|     template<typename T> |  | ||||||
|     ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) { |  | ||||||
|         return ExpressionLhs<T const&>( *this, operand ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) { |  | ||||||
|         return ExpressionLhs<bool>( *this, value ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     template<typename ArgT, typename MatcherT> |  | ||||||
|     void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher, |  | ||||||
|                                              char const* matcherString ) { |  | ||||||
|         MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString ); |  | ||||||
|         setResultType( matcher.match( arg ) ); |  | ||||||
|         endExpression( expr ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } // namespace Catch |  | ||||||
|  |  | ||||||
| #endif // TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED |  | ||||||
| @@ -32,10 +32,12 @@ namespace Catch { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) |     RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) | ||||||
|         : m_runInfo(_config->name()), |     :   m_runInfo(_config->name()), | ||||||
|         m_context(getCurrentMutableContext()), |         m_context(getCurrentMutableContext()), | ||||||
|         m_config(_config), |         m_config(_config), | ||||||
|         m_reporter(std::move(reporter)) { |         m_reporter(std::move(reporter)), | ||||||
|  |         m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal } | ||||||
|  |     { | ||||||
|         m_context.setRunner(this); |         m_context.setRunner(this); | ||||||
|         m_context.setConfig(m_config); |         m_context.setConfig(m_config); | ||||||
|         m_context.setResultCapture(this); |         m_context.setResultCapture(this); | ||||||
| @@ -118,7 +120,7 @@ namespace Catch { | |||||||
|         static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); |         static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); | ||||||
|  |  | ||||||
|         // Reset working state |         // Reset working state | ||||||
|         m_lastAssertionInfo = AssertionInfo("", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}", m_lastAssertionInfo.resultDisposition); |         m_lastAssertionInfo = { "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}", m_lastAssertionInfo.resultDisposition }; | ||||||
|         m_lastResult = result; |         m_lastResult = result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -193,7 +195,7 @@ namespace Catch { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     const AssertionResult * RunContext::getLastResult() const { |     const AssertionResult * RunContext::getLastResult() const { | ||||||
|         return &m_lastResult; |         return &(*m_lastResult); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RunContext::exceptionEarlyReported() { |     void RunContext::exceptionEarlyReported() { | ||||||
| @@ -203,7 +205,7 @@ namespace Catch { | |||||||
|     void RunContext::handleFatalErrorCondition(std::string const & message) { |     void RunContext::handleFatalErrorCondition(std::string const & message) { | ||||||
|         // Don't rebuild the result -- the stringification itself can cause more fatal errors |         // Don't rebuild the result -- the stringification itself can cause more fatal errors | ||||||
|         // Instead, fake a result data. |         // Instead, fake a result data. | ||||||
|         AssertionResultData tempResult; |         AssertionResultData tempResult( ResultWas::Unknown, { false } ); | ||||||
|         tempResult.resultType = ResultWas::FatalErrorCondition; |         tempResult.resultType = ResultWas::FatalErrorCondition; | ||||||
|         tempResult.message = message; |         tempResult.message = message; | ||||||
|         AssertionResult result(m_lastAssertionInfo, tempResult); |         AssertionResult result(m_lastAssertionInfo, tempResult); | ||||||
| @@ -261,7 +263,7 @@ namespace Catch { | |||||||
|         double duration = 0; |         double duration = 0; | ||||||
|         m_shouldReportUnexpected = true; |         m_shouldReportUnexpected = true; | ||||||
|         try { |         try { | ||||||
|             m_lastAssertionInfo = AssertionInfo("TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal); |             m_lastAssertionInfo = { "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal }; | ||||||
|  |  | ||||||
|             seedRng(*m_config); |             seedRng(*m_config); | ||||||
|  |  | ||||||
| @@ -281,7 +283,11 @@ namespace Catch { | |||||||
|             // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions |             // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions | ||||||
|             // are reported without translation at the point of origin. |             // are reported without translation at the point of origin. | ||||||
|             if (m_shouldReportUnexpected) { |             if (m_shouldReportUnexpected) { | ||||||
|                 makeUnexpectedResultBuilder().useActiveException(); |                 AssertionHandler | ||||||
|  |                     ( m_lastAssertionInfo.macroName, | ||||||
|  |                       m_lastAssertionInfo.lineInfo, | ||||||
|  |                       m_lastAssertionInfo.capturedExpression, | ||||||
|  |                       m_lastAssertionInfo.resultDisposition ).useActiveException(); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         m_testCaseTracker->close(); |         m_testCaseTracker->close(); | ||||||
| @@ -307,13 +313,6 @@ namespace Catch { | |||||||
|         fatalConditionHandler.reset(); |         fatalConditionHandler.reset(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ResultBuilder RunContext::makeUnexpectedResultBuilder() const { |  | ||||||
|         return ResultBuilder(m_lastAssertionInfo.macroName, |  | ||||||
|                              m_lastAssertionInfo.lineInfo, |  | ||||||
|                              m_lastAssertionInfo.capturedExpression, |  | ||||||
|                              m_lastAssertionInfo.resultDisposition); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RunContext::handleUnfinishedSections() { |     void RunContext::handleUnfinishedSections() { | ||||||
|         // If sections ended prematurely due to an exception we stored their |         // If sections ended prematurely due to an exception we stored their | ||||||
|         // infos here so we can tear them down outside the unwind process. |         // infos here so we can tear them down outside the unwind process. | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ | |||||||
| #include "catch_test_spec.hpp" | #include "catch_test_spec.hpp" | ||||||
| #include "catch_test_case_tracker.hpp" | #include "catch_test_case_tracker.hpp" | ||||||
| #include "catch_timer.h" | #include "catch_timer.h" | ||||||
| #include "catch_result_builder.h" | #include "catch_assertionhandler.h" | ||||||
| #include "catch_fatal_condition.h" | #include "catch_fatal_condition.h" | ||||||
|  |  | ||||||
| #include <string> | #include <string> | ||||||
| @@ -117,15 +117,13 @@ namespace Catch { | |||||||
|  |  | ||||||
|     private: |     private: | ||||||
|  |  | ||||||
|         ResultBuilder makeUnexpectedResultBuilder() const; |  | ||||||
|  |  | ||||||
|         void handleUnfinishedSections(); |         void handleUnfinishedSections(); | ||||||
|  |  | ||||||
|         TestRunInfo m_runInfo; |         TestRunInfo m_runInfo; | ||||||
|         IMutableContext& m_context; |         IMutableContext& m_context; | ||||||
|         TestCase const* m_activeTestCase = nullptr; |         TestCase const* m_activeTestCase = nullptr; | ||||||
|         ITracker* m_testCaseTracker; |         ITracker* m_testCaseTracker; | ||||||
|         AssertionResult m_lastResult; |         Option<AssertionResult> m_lastResult; | ||||||
|  |  | ||||||
|         IConfigPtr m_config; |         IConfigPtr m_config; | ||||||
|         Totals m_totals; |         Totals m_totals; | ||||||
|   | |||||||
| @@ -18,10 +18,7 @@ | |||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
|     void prepareExpandedExpression(AssertionResult& result) { |     void prepareExpandedExpression(AssertionResult& result) { | ||||||
|         if (result.isOk()) |         result.getExpandedExpression(); | ||||||
|             result.discardDecomposedExpression(); |  | ||||||
|         else |  | ||||||
|             result.expandDecomposedExpression(); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Because formatting using c++ streams is stateful, drop down to C is required |     // Because formatting using c++ streams is stateful, drop down to C is required | ||||||
|   | |||||||
| @@ -193,14 +193,14 @@ namespace Catch { | |||||||
|  |  | ||||||
|         bool assertionEnded(AssertionStats const& assertionStats) override { |         bool assertionEnded(AssertionStats const& assertionStats) override { | ||||||
|             assert(!m_sectionStack.empty()); |             assert(!m_sectionStack.empty()); | ||||||
|             SectionNode& sectionNode = *m_sectionStack.back(); |  | ||||||
|             sectionNode.assertions.push_back(assertionStats); |  | ||||||
|             // AssertionResult holds a pointer to a temporary DecomposedExpression, |             // AssertionResult holds a pointer to a temporary DecomposedExpression, | ||||||
|             // which getExpandedExpression() calls to build the expression string. |             // which getExpandedExpression() calls to build the expression string. | ||||||
|             // Our section stack copy of the assertionResult will likely outlive the |             // Our section stack copy of the assertionResult will likely outlive the | ||||||
|             // temporary, so it must be expanded or discarded now to avoid calling |             // temporary, so it must be expanded or discarded now to avoid calling | ||||||
|             // a destroyed object later. |             // a destroyed object later. | ||||||
|             prepareExpandedExpression(sectionNode.assertions.back().assertionResult); |             prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) ); | ||||||
|  |             SectionNode& sectionNode = *m_sectionStack.back(); | ||||||
|  |             sectionNode.assertions.push_back(assertionStats); | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|         void sectionEnded(SectionStats const& sectionStats) override { |         void sectionEnded(SectionStats const& sectionStats) override { | ||||||
|   | |||||||
| @@ -499,7 +499,7 @@ ExceptionTests.cpp:<line number> | |||||||
| ExceptionTests.cpp:<line number>: FAILED: | ExceptionTests.cpp:<line number>: FAILED: | ||||||
|   REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) |   REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) | ||||||
| with expansion: | with expansion: | ||||||
|   expected exception |   "expected exception" equals: "should fail" | ||||||
|  |  | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| Nice descriptive name | Nice descriptive name | ||||||
|   | |||||||
| @@ -1428,6 +1428,8 @@ ExceptionTests.cpp:<line number> | |||||||
| ExceptionTests.cpp:<line number>: | ExceptionTests.cpp:<line number>: | ||||||
| PASSED: | PASSED: | ||||||
|   REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) |   REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) | ||||||
|  | with expansion: | ||||||
|  |   "expected exception" equals: "expected exception" | ||||||
|  |  | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| Exception messages can be tested for | Exception messages can be tested for | ||||||
| @@ -1439,6 +1441,8 @@ ExceptionTests.cpp:<line number> | |||||||
| ExceptionTests.cpp:<line number>: | ExceptionTests.cpp:<line number>: | ||||||
| PASSED: | PASSED: | ||||||
|   REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) ) |   REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) ) | ||||||
|  | with expansion: | ||||||
|  |   "expected exception" equals: "expected exception" (case insensitive) | ||||||
|  |  | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| Exception messages can be tested for | Exception messages can be tested for | ||||||
| @@ -1450,18 +1454,26 @@ ExceptionTests.cpp:<line number> | |||||||
| ExceptionTests.cpp:<line number>: | ExceptionTests.cpp:<line number>: | ||||||
| PASSED: | PASSED: | ||||||
|   REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) ) |   REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) ) | ||||||
|  | with expansion: | ||||||
|  |   "expected exception" starts with: "expected" | ||||||
|  |  | ||||||
| ExceptionTests.cpp:<line number>: | ExceptionTests.cpp:<line number>: | ||||||
| PASSED: | PASSED: | ||||||
|   REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) ) |   REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) ) | ||||||
|  | with expansion: | ||||||
|  |   "expected exception" ends with: "exception" | ||||||
|  |  | ||||||
| ExceptionTests.cpp:<line number>: | ExceptionTests.cpp:<line number>: | ||||||
| PASSED: | PASSED: | ||||||
|   REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) ) |   REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) ) | ||||||
|  | with expansion: | ||||||
|  |   "expected exception" contains: "except" | ||||||
|  |  | ||||||
| ExceptionTests.cpp:<line number>: | ExceptionTests.cpp:<line number>: | ||||||
| PASSED: | PASSED: | ||||||
|   REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) ) |   REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) ) | ||||||
|  | with expansion: | ||||||
|  |   "expected exception" contains: "except" (case insensitive) | ||||||
|  |  | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| Expected exceptions that don't throw or unexpected exceptions fail the test | Expected exceptions that don't throw or unexpected exceptions fail the test | ||||||
| @@ -1986,11 +1998,13 @@ ExceptionTests.cpp:<line number> | |||||||
| ExceptionTests.cpp:<line number>: | ExceptionTests.cpp:<line number>: | ||||||
| PASSED: | PASSED: | ||||||
|   REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) |   REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) | ||||||
|  | with expansion: | ||||||
|  |   "expected exception" equals: "expected exception" | ||||||
|  |  | ||||||
| ExceptionTests.cpp:<line number>: FAILED: | ExceptionTests.cpp:<line number>: FAILED: | ||||||
|   REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) |   REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) | ||||||
| with expansion: | with expansion: | ||||||
|   expected exception |   "expected exception" equals: "should fail" | ||||||
|  |  | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| Nice descriptive name | Nice descriptive name | ||||||
|   | |||||||
| @@ -311,7 +311,7 @@ MatchersTests.cpp:<line number> | |||||||
|       </failure> |       </failure> | ||||||
|     </testcase> |     </testcase> | ||||||
|     <testcase classname="<exe-name>.global" name="Mismatching exception messages failing the test" time="{duration}"> |     <testcase classname="<exe-name>.global" name="Mismatching exception messages failing the test" time="{duration}"> | ||||||
|       <failure message="expected exception" type="REQUIRE_THROWS_WITH"> |       <failure message=""expected exception" equals: "should fail"" type="REQUIRE_THROWS_WITH"> | ||||||
| ExceptionTests.cpp:<line number> | ExceptionTests.cpp:<line number> | ||||||
|       </failure> |       </failure> | ||||||
|     </testcase> |     </testcase> | ||||||
|   | |||||||
| @@ -1646,7 +1646,7 @@ | |||||||
|             thisThrows(), "expected exception" |             thisThrows(), "expected exception" | ||||||
|           </Original> |           </Original> | ||||||
|           <Expanded> |           <Expanded> | ||||||
|             thisThrows(), "expected exception" |             "expected exception" equals: "expected exception" | ||||||
|           </Expanded> |           </Expanded> | ||||||
|         </Expression> |         </Expression> | ||||||
|         <OverallResults successes="1" failures="0" expectedFailures="0"/> |         <OverallResults successes="1" failures="0" expectedFailures="0"/> | ||||||
| @@ -1657,7 +1657,7 @@ | |||||||
|             thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) |             thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) | ||||||
|           </Original> |           </Original> | ||||||
|           <Expanded> |           <Expanded> | ||||||
|             thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) |             "expected exception" equals: "expected exception" (case insensitive) | ||||||
|           </Expanded> |           </Expanded> | ||||||
|         </Expression> |         </Expression> | ||||||
|         <OverallResults successes="1" failures="0" expectedFailures="0"/> |         <OverallResults successes="1" failures="0" expectedFailures="0"/> | ||||||
| @@ -1668,7 +1668,7 @@ | |||||||
|             thisThrows(), StartsWith( "expected" ) |             thisThrows(), StartsWith( "expected" ) | ||||||
|           </Original> |           </Original> | ||||||
|           <Expanded> |           <Expanded> | ||||||
|             thisThrows(), StartsWith( "expected" ) |             "expected exception" starts with: "expected" | ||||||
|           </Expanded> |           </Expanded> | ||||||
|         </Expression> |         </Expression> | ||||||
|         <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/<exe-name>/ExceptionTests.cpp" > |         <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/<exe-name>/ExceptionTests.cpp" > | ||||||
| @@ -1676,7 +1676,7 @@ | |||||||
|             thisThrows(), EndsWith( "exception" ) |             thisThrows(), EndsWith( "exception" ) | ||||||
|           </Original> |           </Original> | ||||||
|           <Expanded> |           <Expanded> | ||||||
|             thisThrows(), EndsWith( "exception" ) |             "expected exception" ends with: "exception" | ||||||
|           </Expanded> |           </Expanded> | ||||||
|         </Expression> |         </Expression> | ||||||
|         <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/<exe-name>/ExceptionTests.cpp" > |         <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/<exe-name>/ExceptionTests.cpp" > | ||||||
| @@ -1684,7 +1684,7 @@ | |||||||
|             thisThrows(), Contains( "except" ) |             thisThrows(), Contains( "except" ) | ||||||
|           </Original> |           </Original> | ||||||
|           <Expanded> |           <Expanded> | ||||||
|             thisThrows(), Contains( "except" ) |             "expected exception" contains: "except" | ||||||
|           </Expanded> |           </Expanded> | ||||||
|         </Expression> |         </Expression> | ||||||
|         <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/<exe-name>/ExceptionTests.cpp" > |         <Expression success="true" type="REQUIRE_THROWS_WITH" filename="projects/<exe-name>/ExceptionTests.cpp" > | ||||||
| @@ -1692,7 +1692,7 @@ | |||||||
|             thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) |             thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) | ||||||
|           </Original> |           </Original> | ||||||
|           <Expanded> |           <Expanded> | ||||||
|             thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) |             "expected exception" contains: "except" (case insensitive) | ||||||
|           </Expanded> |           </Expanded> | ||||||
|         </Expression> |         </Expression> | ||||||
|         <OverallResults successes="4" failures="0" expectedFailures="0"/> |         <OverallResults successes="4" failures="0" expectedFailures="0"/> | ||||||
| @@ -2172,7 +2172,7 @@ | |||||||
|           thisThrows(), "expected exception" |           thisThrows(), "expected exception" | ||||||
|         </Original> |         </Original> | ||||||
|         <Expanded> |         <Expanded> | ||||||
|           thisThrows(), "expected exception" |           "expected exception" equals: "expected exception" | ||||||
|         </Expanded> |         </Expanded> | ||||||
|       </Expression> |       </Expression> | ||||||
|       <Expression success="false" type="REQUIRE_THROWS_WITH" filename="projects/<exe-name>/ExceptionTests.cpp" > |       <Expression success="false" type="REQUIRE_THROWS_WITH" filename="projects/<exe-name>/ExceptionTests.cpp" > | ||||||
| @@ -2180,7 +2180,7 @@ | |||||||
|           thisThrows(), "should fail" |           thisThrows(), "should fail" | ||||||
|         </Original> |         </Original> | ||||||
|         <Expanded> |         <Expanded> | ||||||
|           expected exception |           "expected exception" equals: "should fail" | ||||||
|         </Expanded> |         </Expanded> | ||||||
|       </Expression> |       </Expression> | ||||||
|       <OverallResult success="false"/> |       <OverallResult success="false"/> | ||||||
|   | |||||||
| @@ -43,7 +43,9 @@ bool templated_tests(T t) { | |||||||
|     REQUIRE_THROWS(throws_int(true)); |     REQUIRE_THROWS(throws_int(true)); | ||||||
|     CHECK_THROWS_AS(throws_int(true), int); |     CHECK_THROWS_AS(throws_int(true), int); | ||||||
|     REQUIRE_NOTHROW(throws_int(false)); |     REQUIRE_NOTHROW(throws_int(false)); | ||||||
|  | #ifndef CATCH_CONFIG_DISABLE_MATCHERS | ||||||
|     REQUIRE_THAT("aaa", Catch::EndsWith("aaa")); |     REQUIRE_THAT("aaa", Catch::EndsWith("aaa")); | ||||||
|  | #endif | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -181,6 +181,8 @@ TEST_CASE( "Unexpected exceptions can be translated", "[.][failing][!throws]"  ) | |||||||
|         throw double( 3.14 ); |         throw double( 3.14 ); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #ifndef CATCH_CONFIG_DISABLE_MATCHERS | ||||||
|  |  | ||||||
| TEST_CASE( "Exception messages can be tested for", "[!throws]" ) { | TEST_CASE( "Exception messages can be tested for", "[!throws]" ) { | ||||||
|     using namespace Catch::Matchers; |     using namespace Catch::Matchers; | ||||||
|     SECTION( "exact match" ) |     SECTION( "exact match" ) | ||||||
| @@ -195,6 +197,8 @@ TEST_CASE( "Exception messages can be tested for", "[!throws]" ) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
| TEST_CASE( "Mismatching exception messages failing the test", "[.][failing][!throws]" ) { | TEST_CASE( "Mismatching exception messages failing the test", "[.][failing][!throws]" ) { | ||||||
|     REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); |     REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); | ||||||
|     REQUIRE_THROWS_WITH( thisThrows(), "should fail" ); |     REQUIRE_THROWS_WITH( thisThrows(), "should fail" ); | ||||||
|   | |||||||
| @@ -8,6 +8,8 @@ | |||||||
|  |  | ||||||
| #include "catch.hpp" | #include "catch.hpp" | ||||||
|  |  | ||||||
|  | #ifndef CATCH_CONFIG_DISABLE_MATCHERS | ||||||
|  |  | ||||||
| inline const char* testStringForMatching() | inline const char* testStringForMatching() | ||||||
| { | { | ||||||
|     return "this string contains 'abc' as a substring"; |     return "this string contains 'abc' as a substring"; | ||||||
| @@ -223,3 +225,5 @@ TEST_CASE("Exception matchers that fail", "[matchers][exceptions][!throws][.fail | |||||||
|         REQUIRE_THROWS_MATCHES(throws(4), SpecialException, ExceptionMatcher{ 1 }); |         REQUIRE_THROWS_MATCHES(throws(4), SpecialException, ExceptionMatcher{ 1 }); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #endif // CATCH_CONFIG_DISABLE_MATCHERS | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ using namespace Catch; | |||||||
| //} | //} | ||||||
|  |  | ||||||
| Catch::TestCaseTracking::NameAndLocation makeNAL( std::string const& name ) { | Catch::TestCaseTracking::NameAndLocation makeNAL( std::string const& name ) { | ||||||
|     return Catch::TestCaseTracking::NameAndLocation( name, Catch::SourceLineInfo() ); |     return Catch::TestCaseTracking::NameAndLocation( name, Catch::SourceLineInfo("",0) ); | ||||||
| } | } | ||||||
|  |  | ||||||
| TEST_CASE( "Tracker" ) { | TEST_CASE( "Tracker" ) { | ||||||
|   | |||||||
| @@ -11,8 +11,6 @@ | |||||||
|  |  | ||||||
| TEST_CASE( "Tag alias can be registered against tag patterns" ) { | TEST_CASE( "Tag alias can be registered against tag patterns" ) { | ||||||
|  |  | ||||||
|     using namespace Catch::Matchers; |  | ||||||
|  |  | ||||||
|     Catch::TagAliasRegistry registry; |     Catch::TagAliasRegistry registry; | ||||||
|  |  | ||||||
|     registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 2 ) ); |     registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 2 ) ); | ||||||
| @@ -24,11 +22,14 @@ TEST_CASE( "Tag alias can be registered against tag patterns" ) { | |||||||
|             FAIL( "expected exception" ); |             FAIL( "expected exception" ); | ||||||
|         } |         } | ||||||
|         catch( std::exception& ex ) { |         catch( std::exception& ex ) { | ||||||
|  | #ifndef CATCH_CONFIG_DISABLE_MATCHERS | ||||||
|             std::string what = ex.what(); |             std::string what = ex.what(); | ||||||
|  |             using namespace Catch::Matchers; | ||||||
|             CHECK_THAT( what, Contains( "[@zzz]" ) ); |             CHECK_THAT( what, Contains( "[@zzz]" ) ); | ||||||
|             CHECK_THAT( what, Contains( "file" ) ); |             CHECK_THAT( what, Contains( "file" ) ); | ||||||
|             CHECK_THAT( what, Contains( "2" ) ); |             CHECK_THAT( what, Contains( "2" ) ); | ||||||
|             CHECK_THAT( what, Contains( "10" ) ); |             CHECK_THAT( what, Contains( "10" ) ); | ||||||
|  | #endif | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -47,7 +47,9 @@ inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ | |||||||
|  |  | ||||||
| TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) { | TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) { | ||||||
|  |  | ||||||
|  | #ifndef CATCH_CONFIG_DISABLE_MATCHERS | ||||||
|     using namespace Catch::Matchers; |     using namespace Catch::Matchers; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     Catch::ConfigData config; |     Catch::ConfigData config; | ||||||
|     auto cli = Catch::makeCommandLineParser(config); |     auto cli = Catch::makeCommandLineParser(config); | ||||||
| @@ -153,7 +155,9 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" | |||||||
|             auto result = cli.parse({"test", "-x", "oops"}); |             auto result = cli.parse({"test", "-x", "oops"}); | ||||||
|             CHECK(!result); |             CHECK(!result); | ||||||
|  |  | ||||||
|  | #ifndef CATCH_CONFIG_DISABLE_MATCHERS | ||||||
|             REQUIRE_THAT(result.errorMessage(), Contains("convert") && Contains("oops")); |             REQUIRE_THAT(result.errorMessage(), Contains("convert") && Contains("oops")); | ||||||
|  | #endif | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -225,7 +229,9 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" | |||||||
|         SECTION( "error" ) { |         SECTION( "error" ) { | ||||||
|             auto result = cli.parse({"test", "--use-colour", "wrong"}); |             auto result = cli.parse({"test", "--use-colour", "wrong"}); | ||||||
|             CHECK( !result ); |             CHECK( !result ); | ||||||
|  | #ifndef CATCH_CONFIG_DISABLE_MATCHERS | ||||||
|             CHECK_THAT( result.errorMessage(), Contains( "colour mode must be one of" ) ); |             CHECK_THAT( result.errorMessage(), Contains( "colour mode must be one of" ) ); | ||||||
|  | #endif | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash