Merge branch 'reevaluate' into dev-modernize

This commit is contained in:
Phil Nash 2017-08-10 16:18:05 +01:00
commit 97c06ca6fb
45 changed files with 726 additions and 901 deletions

View File

@ -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

View File

@ -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__ )

View 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

View 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

View 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

View File

@ -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;
oss << lazyExpression;
reconstructedExpression = oss.str();
} }
AssertionInfo::AssertionInfo( char const * _macroName,
SourceLineInfo const& _lineInfo,
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

View File

@ -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;
}; };

View File

@ -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 {

View File

@ -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

View 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

View 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

View File

@ -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 )

View File

@ -47,7 +47,7 @@ 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;

View 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;
}
}

View 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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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 {

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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";

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -35,7 +35,9 @@ namespace Catch {
: 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.

View File

@ -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;

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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="&quot;expected exception&quot; equals: &quot;should fail&quot;" type="REQUIRE_THROWS_WITH">
ExceptionTests.cpp:<line number> ExceptionTests.cpp:<line number>
</failure> </failure>
</testcase> </testcase>

View File

@ -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"/>

View File

@ -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;
} }

View File

@ -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" );

View File

@ -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

View File

@ -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" ) {

View File

@ -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
} }
} }

View File

@ -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
} }
} }
} }