Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/single_include
diff options
context:
space:
mode:
authorMartin Hořeňovský2017-02-01 21:47:43 +0100
committerMartin Hořeňovský2017-02-01 21:47:43 +0100
commitce37f48ffad2401e6c23a54cae3f015c01fdc200 (patch)
tree5b7d22f7e1d7a3fdadca159aa3fa3fd3f1c64e4e /single_include
parent090fc74cca847b54446ae96eb220d55b7f42df3c (diff)
downloadcatch3-1.7.0.tar.gz
v1.7.0 buildv1.7.0
Diffstat (limited to 'single_include')
-rw-r--r--single_include/catch.hpp1065
1 files changed, 703 insertions, 362 deletions
diff --git a/single_include/catch.hpp b/single_include/catch.hpp
index 6bcdd045..99c93f17 100644
--- a/single_include/catch.hpp
+++ b/single_include/catch.hpp
@@ -1,6 +1,6 @@
/*
- * Catch v1.6.1
- * Generated: 2017-01-20 12:33:53.497767
+ * Catch v1.7.0
+ * Generated: 2017-02-01 21:32:13.239291
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@@ -74,6 +74,8 @@
// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
+// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported?
+// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported?
// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
@@ -167,6 +169,7 @@
#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
+#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
#endif
#endif // _MSC_VER
@@ -235,6 +238,9 @@
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE)
# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
# endif
+# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS)
+# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
+# endif
#endif // __cplusplus >= 201103L
@@ -275,6 +281,9 @@
#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_SHUFFLE
#endif
+# if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_TYPE_TRAITS
+# endif
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
@@ -377,7 +386,10 @@ namespace Catch {
}
bool startsWith( std::string const& s, std::string const& prefix );
+ bool startsWith( std::string const& s, char prefix );
bool endsWith( std::string const& s, std::string const& suffix );
+ bool endsWith( std::string const& s, char suffix );
+ bool contains( std::string const& s, std::string const& infix );
bool contains( std::string const& s, std::string const& infix );
void toLowerInPlace( std::string& s );
std::string toLower( std::string const& s );
@@ -397,8 +409,8 @@ namespace Catch {
SourceLineInfo();
SourceLineInfo( char const* _file, std::size_t _line );
- SourceLineInfo( SourceLineInfo const& other );
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
+ SourceLineInfo(SourceLineInfo const& other) = default;
SourceLineInfo( SourceLineInfo && ) = default;
SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
SourceLineInfo& operator = ( SourceLineInfo && ) = default;
@@ -407,15 +419,16 @@ namespace Catch {
bool operator == ( SourceLineInfo const& other ) const;
bool operator < ( SourceLineInfo const& other ) const;
- std::string file;
+ char const* file;
std::size_t line;
};
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
// This is just here to avoid compiler warnings with macro constants and boolean literals
- inline bool alwaysTrue( std::size_t = 0 ) { return true; }
- inline bool alwaysFalse( std::size_t = 0 ) { return false; }
+ inline bool isTrue( bool value ){ return value; }
+ inline bool alwaysTrue() { return true; }
+ inline bool alwaysFalse() { return false; }
void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
@@ -841,6 +854,27 @@ namespace Catch {
namespace Catch {
+ struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
+
+ struct DecomposedExpression
+ {
+ virtual ~DecomposedExpression() {}
+ virtual bool isBinaryExpression() const {
+ return false;
+ }
+ 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() {}
@@ -857,11 +891,41 @@ namespace Catch {
struct AssertionResultData
{
- AssertionResultData() : resultType( ResultWas::Unknown ) {}
+ AssertionResultData() : decomposedExpression( CATCH_NULL )
+ , resultType( ResultWas::Unknown )
+ , negated( false )
+ , parenthesized( false ) {}
+
+ void 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& reconstructExpression() const {
+ if( decomposedExpression != CATCH_NULL ) {
+ decomposedExpression->reconstructExpression( reconstructedExpression );
+ if( parenthesized ) {
+ reconstructedExpression.insert( 0, 1, '(' );
+ reconstructedExpression.append( 1, ')' );
+ }
+ if( negated ) {
+ reconstructedExpression.insert( 0, 1, '!' );
+ }
+ decomposedExpression = CATCH_NULL;
+ }
+ return reconstructedExpression;
+ }
- std::string reconstructedExpression;
+ mutable DecomposedExpression const* decomposedExpression;
+ mutable std::string reconstructedExpression;
std::string message;
ResultWas::OfType resultType;
+ bool negated;
+ bool parenthesized;
};
class AssertionResult {
@@ -888,6 +952,8 @@ namespace Catch {
std::string getMessage() const;
SourceLineInfo getSourceInfo() const;
std::string getTestMacroName() const;
+ void discardDecomposedExpression() const;
+ void expandDecomposedExpression() const;
protected:
AssertionInfo m_info;
@@ -1074,7 +1140,7 @@ namespace Matchers {
{
return m_caseSensitivity == CaseSensitive::No
? " (case insensitive)"
- : "";
+ : std::string();
}
CaseSensitive::Choice m_caseSensitivity;
std::string m_str;
@@ -1092,7 +1158,7 @@ namespace Matchers {
return m_data.m_str == m_data.adjustString( expr );;
}
virtual std::string toString() const {
- return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
+ return "equals: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
}
CasedString m_data;
@@ -1109,7 +1175,7 @@ namespace Matchers {
return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos;
}
virtual std::string toString() const {
- return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
+ return "contains: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
}
CasedString m_data;
@@ -1127,7 +1193,7 @@ namespace Matchers {
return startsWith( m_data.adjustString( expr ), m_data.m_str );
}
virtual std::string toString() const {
- return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
+ return "starts with: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
}
CasedString m_data;
@@ -1144,7 +1210,7 @@ namespace Matchers {
return endsWith( m_data.adjustString( expr ), m_data.m_str );
}
virtual std::string toString() const {
- return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
+ return "ends with: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
}
CasedString m_data;
@@ -1219,22 +1285,20 @@ namespace Catch {
template<typename T> class ExpressionLhs;
- struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
-
struct CopyableStream {
CopyableStream() {}
CopyableStream( CopyableStream const& other ) {
oss << other.oss.str();
}
CopyableStream& operator=( CopyableStream const& other ) {
- oss.str("");
+ oss.str(std::string());
oss << other.oss.str();
return *this;
}
std::ostringstream oss;
};
- class ResultBuilder {
+ class ResultBuilder : public DecomposedExpression {
public:
ResultBuilder( char const* macroName,
SourceLineInfo const& lineInfo,
@@ -1252,19 +1316,15 @@ namespace Catch {
return *this;
}
- template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
- template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
-
ResultBuilder& setResultType( ResultWas::OfType result );
ResultBuilder& setResultType( bool result );
- ResultBuilder& setLhs( std::string const& lhs );
- ResultBuilder& setRhs( std::string const& rhs );
- ResultBuilder& setOp( std::string const& op );
- void endExpression();
+ void endExpression( DecomposedExpression const& expr );
+
+ virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE;
- std::string reconstructExpression() const;
AssertionResult build() const;
+ AssertionResult build( DecomposedExpression const& expr ) const;
void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
void captureResult( ResultWas::OfType resultType );
@@ -1276,14 +1336,12 @@ namespace Catch {
bool shouldDebugBreak() const;
bool allowThrows() const;
+ template<typename ArgT, typename MatcherT>
+ void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString );
+
private:
AssertionInfo m_assertionInfo;
AssertionResultData m_data;
- struct ExprComponents {
- ExprComponents() : testFalse( false ) {}
- bool testFalse;
- std::string lhs, rhs, op;
- } m_exprComponents;
CopyableStream m_stream;
bool m_shouldDebugBreak;
@@ -1805,90 +1863,155 @@ std::string toString( T const& value ) {
namespace Catch {
-// Wraps the LHS of an expression and captures the operator and RHS (if any) -
-// wrapping them all in a ResultBuilder object
-template<typename T>
-class ExpressionLhs {
- ExpressionLhs& operator = ( ExpressionLhs const& );
-# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
- ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
-# endif
+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 ) {}
-# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
- ExpressionLhs( ExpressionLhs const& ) = default;
- ExpressionLhs( ExpressionLhs && ) = default;
-# endif
+ ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
template<typename RhsT>
- ResultBuilder& operator == ( RhsT const& rhs ) {
+ BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
+ operator == ( RhsT const& rhs ) const {
return captureExpression<Internal::IsEqualTo>( rhs );
}
template<typename RhsT>
- ResultBuilder& operator != ( RhsT const& rhs ) {
+ BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&>
+ operator != ( RhsT const& rhs ) const {
return captureExpression<Internal::IsNotEqualTo>( rhs );
}
template<typename RhsT>
- ResultBuilder& operator < ( RhsT const& rhs ) {
+ BinaryExpression<T, Internal::IsLessThan, RhsT const&>
+ operator < ( RhsT const& rhs ) const {
return captureExpression<Internal::IsLessThan>( rhs );
}
template<typename RhsT>
- ResultBuilder& operator > ( RhsT const& rhs ) {
+ BinaryExpression<T, Internal::IsGreaterThan, RhsT const&>
+ operator > ( RhsT const& rhs ) const {
return captureExpression<Internal::IsGreaterThan>( rhs );
}
template<typename RhsT>
- ResultBuilder& operator <= ( RhsT const& rhs ) {
+ BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&>
+ operator <= ( RhsT const& rhs ) const {
return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
}
template<typename RhsT>
- ResultBuilder& operator >= ( RhsT const& rhs ) {
+ BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&>
+ operator >= ( RhsT const& rhs ) const {
return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
}
- ResultBuilder& operator == ( bool rhs ) {
+ BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) const {
return captureExpression<Internal::IsEqualTo>( rhs );
}
- ResultBuilder& operator != ( bool rhs ) {
+ BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) const {
return captureExpression<Internal::IsNotEqualTo>( rhs );
}
void endExpression() {
- bool value = m_lhs ? true : false;
+ m_truthy = m_lhs ? true : false;
m_rb
- .setLhs( Catch::toString( value ) )
- .setResultType( value )
- .endExpression();
+ .setResultType( m_truthy )
+ .endExpression( *this );
}
- // Only simple binary expressions are allowed on the LHS.
- // If more complex compositions are required then place the sub expression in parentheses
- template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
- template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
- template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
- template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
- template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
- template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
+ virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
+ dest = Catch::toString( m_truthy );
+ }
private:
template<Internal::Operator Op, typename RhsT>
- ResultBuilder& captureExpression( RhsT const& rhs ) {
- return m_rb
- .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
- .setLhs( Catch::toString( m_lhs ) )
- .setRhs( Catch::toString( rhs ) )
- .setOp( Internal::OperatorTraits<Op>::getName() );
+ 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;
+};
+
+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 ) {}
+
+ void endExpression() const {
+ m_rb
+ .setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
+ .endExpression( *this );
+ }
+
+ virtual bool isBinaryExpression() const CATCH_OVERRIDE {
+ return true;
+ }
+
+ virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
+ std::string lhs = Catch::toString( m_lhs );
+ std::string rhs = Catch::toString( 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::OperatorTraits<Op>::getName();
+ 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 ) {}
+
+ virtual bool isBinaryExpression() const CATCH_OVERRIDE {
+ return true;
+ }
+
+ virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
+ std::string matcherAsString = m_matcher.toString();
+ dest = Catch::toString( 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
@@ -1905,6 +2028,14 @@ namespace Catch {
return ExpressionLhs<bool>( *this, value );
}
+ template<typename ArgT, typename MatcherT>
+ inline 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
// #included from: catch_message.h
@@ -2034,14 +2165,12 @@ namespace Catch{
// The following code snippet based on:
// http://cocoawithlove.com/2008/03/break-into-debugger.html
- #ifdef DEBUG
- #if defined(__ppc64__) || defined(__ppc__)
- #define CATCH_TRAP() \
- __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
- : : : "memory","r0","r3","r4" )
- #else
- #define CATCH_TRAP() _asm__("int $3\n" : : )
- #endif
+ #if defined(__ppc64__) || defined(__ppc__)
+ #define CATCH_TRAP() \
+ __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
+ : : : "memory","r0","r3","r4" )
+ #else
+ #define CATCH_TRAP() __asm__("int $3\n" : : )
#endif
#elif defined(CATCH_PLATFORM_LINUX)
@@ -2098,10 +2227,11 @@ namespace Catch {
( __catchResult <= expr ).endExpression(); \
} \
catch( ... ) { \
- __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
+ __catchResult.useActiveException( resultDisposition ); \
} \
INTERNAL_CATCH_REACT( __catchResult ) \
- } while( Catch::alwaysFalse( sizeof(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
+ } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr 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 &&.
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
@@ -2118,7 +2248,7 @@ namespace Catch {
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
try { \
- expr; \
+ static_cast<void>(expr); \
__catchResult.captureResult( Catch::ResultWas::Ok ); \
} \
catch( ... ) { \
@@ -2133,7 +2263,7 @@ namespace Catch {
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
if( __catchResult.allowThrows() ) \
try { \
- expr; \
+ static_cast<void>(expr); \
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
} \
catch( ... ) { \
@@ -2150,7 +2280,7 @@ namespace Catch {
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
if( __catchResult.allowThrows() ) \
try { \
- expr; \
+ static_cast<void>(expr); \
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
} \
catch( exceptionType ) { \
@@ -2192,13 +2322,7 @@ namespace Catch {
do { \
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
try { \
- std::string matcherAsString = (matcher).toString(); \
- __catchResult \
- .setLhs( Catch::toString( arg ) ) \
- .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
- .setOp( "matches" ) \
- .setResultType( (matcher).match( arg ) ); \
- __catchResult.captureExpression(); \
+ __catchResult.captureMatch( arg, matcher, #matcher ); \
} catch( ... ) { \
__catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
} \
@@ -2651,6 +2775,10 @@ namespace Catch {
#include <cmath>
#include <limits>
+#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
+#include <type_traits>
+#endif
+
namespace Catch {
namespace Detail {
@@ -2679,6 +2807,53 @@ namespace Detail {
return approx;
}
+#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator == ( const T& lhs, Approx const& rhs ) {
+ // Thanks to Richard Harris for his help refining this formula
+ auto lhs_v = double(lhs);
+ return fabs( lhs_v - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs_v), fabs(rhs.m_value) ) );
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator == ( Approx const& lhs, const T& rhs ) {
+ return operator==( rhs, lhs );
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator != ( T lhs, Approx const& rhs ) {
+ return !operator==( lhs, rhs );
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator != ( Approx const& lhs, T rhs ) {
+ return !operator==( rhs, lhs );
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator <= ( T lhs, Approx const& rhs )
+ {
+ return double(lhs) < rhs.m_value || lhs == rhs;
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator <= ( Approx const& lhs, T rhs )
+ {
+ return lhs.m_value < double(rhs) || lhs == rhs;
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator >= ( T lhs, Approx const& rhs )
+ {
+ return double(lhs) > rhs.m_value || lhs == rhs;
+ }
+
+ template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
+ friend bool operator >= ( Approx const& lhs, T rhs )
+ {
+ return lhs.m_value > double(rhs) || lhs == rhs;
+ }
+#else
friend bool operator == ( double lhs, Approx const& rhs ) {
// Thanks to Richard Harris for his help refining this formula
return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
@@ -2715,6 +2890,7 @@ namespace Detail {
{
return lhs.m_value > rhs || lhs == rhs;
}
+#endif
Approx& epsilon( double newEpsilon ) {
m_epsilon = newEpsilon;
@@ -2870,7 +3046,8 @@ namespace Catch {
IsHidden = 1 << 1,
ShouldFail = 1 << 2,
MayFail = 1 << 3,
- Throws = 1 << 4
+ Throws = 1 << 4,
+ NonPortable = 1 << 5
};
TestCaseInfo( std::string const& _name,
@@ -3182,11 +3359,11 @@ namespace Catch
m_wildcard( NoWildcard ),
m_pattern( adjustCase( pattern ) )
{
- if( startsWith( m_pattern, "*" ) ) {
+ if( startsWith( m_pattern, '*' ) ) {
m_pattern = m_pattern.substr( 1 );
m_wildcard = WildcardAtStart;
}
- if( endsWith( m_pattern, "*" ) ) {
+ if( endsWith( m_pattern, '*' ) ) {
m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
}
@@ -3373,6 +3550,8 @@ namespace Catch {
m_start = start;
}
void escape() {
+ if( m_mode == None )
+ m_start = m_pos;
m_mode = EscapedName;
m_escapeChars.push_back( m_pos );
}
@@ -3381,7 +3560,7 @@ namespace Catch {
void addPattern() {
std::string token = subString();
for( size_t i = 0; i < m_escapeChars.size(); ++i )
- token = token.substr( 0, m_escapeChars[i] ) + token.substr( m_escapeChars[i]+1 );
+ token = token.substr( 0, m_escapeChars[i]-i ) + token.substr( m_escapeChars[i]+1-i );
m_escapeChars.clear();
if( startsWith( token, "exclude:" ) ) {
m_exclusion = true;
@@ -3468,6 +3647,8 @@ namespace Catch {
virtual RunTests::InWhatOrder runOrder() const = 0;
virtual unsigned int rngSeed() const = 0;
virtual UseColour::YesOrNo useColour() const = 0;
+ virtual std::vector<std::string> const& getSectionsToRun() const = 0;
+
};
}
@@ -3594,6 +3775,7 @@ namespace Catch {
std::vector<std::string> reporterNames;
std::vector<std::string> testsOrTags;
+ std::vector<std::string> sectionsToRun;
};
class Config : public SharedImpl<IConfig> {
@@ -3634,7 +3816,8 @@ namespace Catch {
bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
- std::vector<std::string> getReporterNames() const { return m_data.reporterNames; }
+ std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; }
+ std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; }
int abortAfter() const { return m_data.abortAfter; }
@@ -4724,13 +4907,14 @@ namespace Catch {
config.abortAfter = x;
}
inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
+ inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); }
inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
inline void addWarning( ConfigData& config, std::string const& _warning ) {
if( _warning == "NoAssertions" )
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
else
- throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
+ throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' );
}
inline void setOrder( ConfigData& config, std::string const& order ) {
if( startsWith( "declared", order ) )
@@ -4740,7 +4924,7 @@ namespace Catch {
else if( startsWith( "random", order ) )
config.runOrder = RunTests::InRandomOrder;
else
- throw std::runtime_error( "Unrecognised ordering: '" + order + "'" );
+ throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' );
}
inline void setRngSeed( ConfigData& config, std::string const& seed ) {
if( seed == "time" ) {
@@ -4786,10 +4970,10 @@ namespace Catch {
std::string line;
while( std::getline( f, line ) ) {
line = trim(line);
- if( !line.empty() && !startsWith( line, "#" ) ) {
- if( !startsWith( line, "\"" ) )
- line = "\"" + line + "\"";
- addTestOrTags( config, line + "," );
+ if( !line.empty() && !startsWith( line, '#' ) ) {
+ if( !startsWith( line, '"' ) )
+ line = '"' + line + '"';
+ addTestOrTags( config, line + ',' );
}
}
}
@@ -4877,6 +5061,10 @@ namespace Catch {
.describe( "adds a tag for the filename" )
.bind( &ConfigData::filenamesAsTags );
+ cli["-c"]["--section"]
+ .describe( "specify section to run" )
+ .bind( &addSectionToRun, "section name" );
+
// Less common commands which don't have a short form
cli["--list-test-names-only"]
.describe( "list all/matching test cases names only" )
@@ -4949,19 +5137,16 @@ namespace Tbc {
TextAttributes()
: initialIndent( std::string::npos ),
indent( 0 ),
- width( consoleWidth-1 ),
- tabChar( '\t' )
+ width( consoleWidth-1 )
{}
TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
- TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
std::size_t initialIndent; // indent of first line, or npos
std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
std::size_t width; // maximum width of text, including indent. Longer text will wrap
- char tabChar; // If this char is seen the indent is changed to current pos
};
class Text {
@@ -4969,62 +5154,76 @@ namespace Tbc {
Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
: attr( _attr )
{
- std::string wrappableChars = " [({.,/|\\-";
- std::size_t indent = _attr.initialIndent != std::string::npos
- ? _attr.initialIndent
- : _attr.indent;
- std::string remainder = _str;
+ const std::string wrappableBeforeChars = "[({<\t";
+ const std::string wrappableAfterChars = "])}>-,./|\\";
+ const std::string wrappableInsteadOfChars = " \n\r";
+ std::string indent = _attr.initialIndent != std::string::npos
+ ? std::string( _attr.initialIndent, ' ' )
+ : std::string( _attr.indent, ' ' );
+
+ typedef std::string::const_iterator iterator;
+ iterator it = _str.begin();
+ const iterator strEnd = _str.end();
+
+ while( it != strEnd ) {
- while( !remainder.empty() ) {
if( lines.size() >= 1000 ) {
lines.push_back( "... message truncated due to excessive size" );
return;
}
- std::size_t tabPos = std::string::npos;
- std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
- std::size_t pos = remainder.find_first_of( '\n' );
- if( pos <= width ) {
- width = pos;
- }
- pos = remainder.find_last_of( _attr.tabChar, width );
- if( pos != std::string::npos ) {
- tabPos = pos;
- if( remainder[width] == '\n' )
- width--;
- remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
- }
- if( width == remainder.size() ) {
- spliceLine( indent, remainder, width );
- }
- else if( remainder[width] == '\n' ) {
- spliceLine( indent, remainder, width );
- if( width <= 1 || remainder.size() != 1 )
- remainder = remainder.substr( 1 );
- indent = _attr.indent;
- }
- else {
- pos = remainder.find_last_of( wrappableChars, width );
- if( pos != std::string::npos && pos > 0 ) {
- spliceLine( indent, remainder, pos );
- if( remainder[0] == ' ' )
- remainder = remainder.substr( 1 );
+ std::string suffix;
+ std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
+ iterator itEnd = it+width;
+ iterator itNext = _str.end(