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

summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorPhil Nash2017-02-28 14:19:09 +0000
committerPhil Nash2017-02-28 14:19:09 +0000
commit0952b76e16f91922d5353073b5a3ac7341aac006 (patch)
treef29d82725c8417282f9716ca39e82362cc740327
parentbbeb192ec952e3317971a9aa7eaa8640dd782624 (diff)
downloadcatch3-1.8.0.tar.gz
v1.8.0 releasev1.8.0
-rw-r--r--README.md4
-rw-r--r--docs/release-notes.md43
-rw-r--r--include/internal/catch_version.hpp2
-rw-r--r--single_include/catch.hpp794
4 files changed, 547 insertions, 296 deletions
diff --git a/README.md b/README.md
index 501ce6e3..b6c70d52 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
![catch logo](catch-logo-small.png)
-*v1.7.2*
+*v1.8.0*
Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=master)](https://travis-ci.org/philsquared/Catch)
-<a href="https://github.com/philsquared/Catch/releases/download/v1.7.2/catch.hpp">The latest, single header, version can be downloaded directly using this link</a>
+<a href="https://github.com/philsquared/Catch/releases/download/v1.8.0/catch.hpp">The latest, single header, version can be downloaded directly using this link</a>
## What's the Catch?
diff --git a/docs/release-notes.md b/docs/release-notes.md
index e1bd19d2..6922468f 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -1,3 +1,40 @@
+# 1.8.0
+
+### New features/ minor changes
+
+* Matchers have new, simpler (and documented) interface.
+ * Catch provides string and vector matchers.
+ * For details see [Matchers documentation](docs/matchers.md).
+* Changed console reporter test duration reporting format (#322)
+ * Old format: `Some simple comparisons between doubles completed in 0.000123s`
+ * New format: `xxx.123s: Some simple comparisons between doubles` _(There will always be exactly 3 decimal places)_
+* Added opt-in leak detection under MSVC + Windows (#439)
+ * Enable it by compiling Catch's main with `CATCH_CONFIG_WINDOWS_CRTDBG`
+* Introduced new compile-time flag, `CATCH_CONFIG_FAST_COMPILE`, trading features for compilation speed.
+ * Moves debug breaks out of tests and into implementation, speeding up compilation time by ~XX%
+ * _More changes are coming_
+* Added [TAP (Test Anything Protocol)](https://testanything.org/) and [Automake](https://www.gnu.org/software/automake/manual/html_node/Log-files-generation-and-test-results-recording.html#Log-files-generation-and-test-results-recording) reporters.
+ * These are not present in the default single-include header and need to be downloaded from GitHub separately.
+ * For details see [documentation about integrating with build systems](docs/build-systems.md).
+* XML reporter now reports filename as part of the `Section` and `TestCase` tags.
+* `Approx` now supports an optional margin of absolute error
+ * It has also received [new documentation]().
+
+### Fixes
+* Silenced C4312 ("conversion from int to 'ClassName *") warnings in the evaluate layer.
+* Fixed C4512 ("assignment operator could not be generated") warnings under VS2013.
+* Cygwin compatibility fixes
+ * Signal handling is no longer compiled by default.
+ * Usage of `gettimeofday` inside Catch should no longer cause compilation errors.
+* Improved `-Wparentheses` supression for gcc (#674)
+ * When compiled with gcc 4.8 or newer, the supression is localized to assertions only
+ * Otherwise it is supressed for the whole TU
+* Fixed test spec parser issue (with escapes in multiple names)
+
+### Other
+* Various documentation fixes and improvements
+
+
# 1.7.2
### Fixes and minor improvements
@@ -31,9 +68,6 @@ Other:
* Fixed possible infinite recursion in Windows SEH.
* Fixed possible compilation error caused by Catch's operator overloads being ambiguous in regards to user-defined templated operators.
-# Older versions
-Release notes were not maintained prior to v1.6.0, but you should be able to work them out from the Git history
-
## 1.7.0
### Features/ Changes:
@@ -102,6 +136,9 @@ Release notes were not maintained prior to v1.6.0, but you should be able to wor
* Tweaks and changes to scripts - particularly for Approval test - to make them more portable
+# Older versions
+Release notes were not maintained prior to v1.6.0, but you should be able to work them out from the Git history
+
---
[Home](Readme.md)
diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp
index 1041e303..3c3593fa 100644
--- a/include/internal/catch_version.hpp
+++ b/include/internal/catch_version.hpp
@@ -37,7 +37,7 @@ namespace Catch {
return os;
}
- Version libraryVersion( 1, 7, 2, "", 0 );
+ Version libraryVersion( 1, 8, 0, "", 0 );
}
diff --git a/single_include/catch.hpp b/single_include/catch.hpp
index 2a09fd19..abba8388 100644
--- a/single_include/catch.hpp
+++ b/single_include/catch.hpp
@@ -1,6 +1,6 @@
/*
- * Catch v1.7.2
- * Generated: 2017-02-13 15:57:33.350226
+ * Catch v1.8.0
+ * Generated: 2017-02-28 14:16:45.289179
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@@ -40,6 +40,12 @@
#elif defined __GNUC__
# pragma GCC diagnostic ignored "-Wvariadic-macros"
# pragma GCC diagnostic ignored "-Wunused-variable"
+
+ // For newer version we can use __Pragma to disable the warnings locally
+# if __GNUC__ == 4 && __GNUC_MINOR__ >= 4 && __GNUC_MINOR__ <= 7
+# pragma GCC diagnostic ignored "-Wparentheses"
+# endif
+
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wpadded"
#endif
@@ -82,6 +88,7 @@
// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
+// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
// ****************
// Note to maintainers: if new toggles are added please document them
// in configuration.md, too
@@ -117,12 +124,26 @@
# endif
# if defined(CATCH_CPP11_OR_GREATER)
-# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
+# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
+ _Pragma( "clang diagnostic push" ) \
+ _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
+# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
+ _Pragma( "clang diagnostic pop" )
# endif
#endif // __clang__
////////////////////////////////////////////////////////////////////////////////
+// Cygwin
+#ifdef __CYGWIN__
+
+# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
+# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
+# endif
+
+#endif // __CYGWIN__
+
+////////////////////////////////////////////////////////////////////////////////
// Borland
#ifdef __BORLANDC__
@@ -144,12 +165,20 @@
// GCC
#ifdef __GNUC__
+# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)
+# define CATCH_GCC_HAS_NEW_PRAGMA
+# endif
+
# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
# endif
-# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER)
-# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
+# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_GCC_HAS_NEW_PRAGMA)
+# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
+ _Pragma( "GCC diagnostic push" ) \
+ _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
+# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
+ _Pragma( "GCC diagnostic pop" )
# endif
// - otherwise more recent versions define __cplusplus >= 201103L
@@ -290,9 +319,14 @@
#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
# define CATCH_CONFIG_WINDOWS_SEH
#endif
+// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
+#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
+# define CATCH_CONFIG_POSIX_SIGNALS
+#endif
#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
+# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
#endif
// noexcept support:
@@ -871,6 +905,9 @@ namespace Catch {
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& );
+
+ private:
+ DecomposedExpression& operator = (DecomposedExpression const&);
};
struct AssertionInfo
@@ -967,313 +1004,153 @@ namespace Catch {
namespace Matchers {
namespace Impl {
- namespace Generic {
- template<typename ExpressionT> class AllOf;
- template<typename ExpressionT> class AnyOf;
- template<typename ExpressionT> class Not;
- }
-
- template<typename ExpressionT>
- struct Matcher : SharedImpl<IShared>
- {
- typedef ExpressionT ExpressionType;
-
- virtual ~Matcher() {}
- virtual Ptr<Matcher> clone() const = 0;
- virtual bool match( ExpressionT const& expr ) const = 0;
- virtual std::string toString() const = 0;
-
- Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const;
- Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const;
- Generic::Not<ExpressionT> operator ! () const;
- };
-
- template<typename DerivedT, typename ExpressionT>
- struct MatcherImpl : Matcher<ExpressionT> {
+ template<typename ArgT> struct MatchAllOf;
+ template<typename ArgT> struct MatchAnyOf;
+ template<typename ArgT> struct MatchNotOf;
- virtual Ptr<Matcher<ExpressionT> > clone() const {
- return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
- }
- };
-
- namespace Generic {
- template<typename ExpressionT>
- class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> {
+ class MatcherUntypedBase {
public:
- explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {}
- Not( Not const& other ) : m_matcher( other.m_matcher ) {}
-
- virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE {
- return !m_matcher->match( expr );
+ std::string toString() const {
+ if( m_cachedToString.empty() )
+ m_cachedToString = describe();
+ return m_cachedToString;
}
- virtual std::string toString() const CATCH_OVERRIDE {
- return "not " + m_matcher->toString();
- }
+ protected:
+ virtual std::string describe() const = 0;
+ mutable std::string m_cachedToString;
private:
- Ptr< Matcher<ExpressionT> > m_matcher;
+ MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
};
- template<typename ExpressionT>
- class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
- public:
+ template<typename ObjectT, typename ComparatorT = ObjectT>
+ struct MatcherBase : MatcherUntypedBase {
- AllOf() {}
- AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
+ virtual bool match( ObjectT const& arg ) const = 0;
- AllOf& add( Matcher<ExpressionT> const& matcher ) {
- m_matchers.push_back( matcher.clone() );
- return *this;
- }
- virtual bool match( ExpressionT const& expr ) const
- {
- for( std::size_t i = 0; i < m_matchers.size(); ++i )
- if( !m_matchers[i]->match( expr ) )
+ MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const;
+ MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
+ MatchNotOf<ComparatorT> operator ! () const;
+ };
+
+ template<typename ArgT>
+ struct MatchAllOf : MatcherBase<ArgT> {
+ virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
+ for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+ if (!m_matchers[i]->match(arg))
return false;
+ }
return true;
}
- virtual std::string toString() const {
- std::ostringstream oss;
- oss << "( ";
+ virtual std::string describe() const CATCH_OVERRIDE {
+ std::string description;
+ description.reserve( 4 + m_matchers.size()*32 );
+ description += "( ";
for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
if( i != 0 )
- oss << " and ";
- oss << m_matchers[i]->toString();
+ description += " and ";
+ description += m_matchers[i]->toString();
}
- oss << " )";
- return oss.str();
+ description += " )";
+ return description;
}
- AllOf operator && ( Matcher<ExpressionT> const& other ) const {
- AllOf allOfExpr( *this );
- allOfExpr.add( other );
- return allOfExpr;
+ MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
+ m_matchers.push_back( &other );
+ return *this;
}
- private:
- std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
+ std::vector<MatcherBase<ArgT> const*> m_matchers;
};
+ template<typename ArgT>
+ struct MatchAnyOf : MatcherBase<ArgT> {
- template<typename ExpressionT>
- class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
- public:
-
- AnyOf() {}
- AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
-
- AnyOf& add( Matcher<ExpressionT> const& matcher ) {
- m_matchers.push_back( matcher.clone() );
- return *this;
- }
- virtual bool match( ExpressionT const& expr ) const
- {
- for( std::size_t i = 0; i < m_matchers.size(); ++i )
- if( m_matchers[i]->match( expr ) )
+ virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
+ for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+ if (m_matchers[i]->match(arg))
return true;
+ }
return false;
}
- virtual std::string toString() const {
- std::ostringstream oss;
- oss << "( ";
+ virtual std::string describe() const CATCH_OVERRIDE {
+ std::string description;
+ description.reserve( 4 + m_matchers.size()*32 );
+ description += "( ";
for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
if( i != 0 )
- oss << " or ";
- oss << m_matchers[i]->toString();
+ description += " or ";
+ description += m_matchers[i]->toString();
}
- oss << " )";
- return oss.str();
+ description += " )";
+ return description;
}
- AnyOf operator || ( Matcher<ExpressionT> const& other ) const {
- AnyOf anyOfExpr( *this );
- anyOfExpr.add( other );
- return anyOfExpr;
- }
-
- private:
- std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
- };
-
- } // namespace Generic
-
- template<typename ExpressionT>
- Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const {
- Generic::AllOf<ExpressionT> allOfExpr;
- allOfExpr.add( *this );
- allOfExpr.add( other );
- return allOfExpr;
- }
-
- template<typename ExpressionT>
- Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const {
- Generic::AnyOf<ExpressionT> anyOfExpr;
- anyOfExpr.add( *this );
- anyOfExpr.add( other );
- return anyOfExpr;
- }
-
- template<typename ExpressionT>
- Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const {
- return Generic::Not<ExpressionT>( *this );
- }
-
- namespace StdString {
-
- inline std::string makeString( std::string const& str ) { return str; }
- inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
-
- struct CasedString
- {
- CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
- : m_caseSensitivity( caseSensitivity ),
- m_str( adjustString( str ) )
- {}
- std::string adjustString( std::string const& str ) const {
- return m_caseSensitivity == CaseSensitive::No
- ? toLower( str )
- : str;
-
- }
- std::string toStringSuffix() const
- {
- return m_caseSensitivity == CaseSensitive::No
- ? " (case insensitive)"
- : std::string();
- }
- CaseSensitive::Choice m_caseSensitivity;
- std::string m_str;
- };
-
- struct Equals : MatcherImpl<Equals, std::string> {
- Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
- : m_data( str, caseSensitivity )
- {}
- Equals( Equals const& other ) : m_data( other.m_data ){}
-
- virtual ~Equals();
-
- virtual bool match( std::string const& expr ) const {
- return m_data.m_str == m_data.adjustString( expr );;
- }
- virtual std::string toString() const {
- return "equals: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
+ MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
+ m_matchers.push_back( &other );
+ return *this;
}
- CasedString m_data;
+ std::vector<MatcherBase<ArgT> const*> m_matchers;
};
- struct Contains : MatcherImpl<Contains, std::string> {
- Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
- : m_data( substr, caseSensitivity ){}
- Contains( Contains const& other ) : m_data( other.m_data ){}
+ template<typename ArgT>
+ struct MatchNotOf : MatcherBase<ArgT> {
- virtual ~Contains();
+ MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
- virtual bool match( std::string const& expr ) const {
- return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos;
+ virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
+ return !m_underlyingMatcher.match( arg );
}
- virtual std::string toString() const {
- return "contains: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
- }
-
- CasedString m_data;
- };
-
- struct StartsWith : MatcherImpl<StartsWith, std::string> {
- StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
- : m_data( substr, caseSensitivity ){}
-
- StartsWith( StartsWith const& other ) : m_data( other.m_data ){}
- virtual ~StartsWith();
-
- virtual bool match( std::string const& expr ) const {
- 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();
+ virtual std::string describe() const CATCH_OVERRIDE {
+ return "not " + m_underlyingMatcher.toString();
}
-
- CasedString m_data;
+ MatcherBase<ArgT> const& m_underlyingMatcher;
};
- struct EndsWith : MatcherImpl<EndsWith, std::string> {
- EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
- : m_data( substr, caseSensitivity ){}
- EndsWith( EndsWith const& other ) : m_data( other.m_data ){}
-
- virtual ~EndsWith();
-
- virtual bool match( std::string const& expr ) const {
- 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();
- }
+ template<typename ObjectT, typename ComparatorT>
+ MatchAllOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator && ( MatcherBase const& other ) const {
+ return MatchAllOf<ComparatorT>() && *this && other;
+ }
+ template<typename ObjectT, typename ComparatorT>
+ MatchAnyOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator || ( MatcherBase const& other ) const {
+ return MatchAnyOf<ComparatorT>() || *this || other;
+ }
+ template<typename ObjectT, typename ComparatorT>
+ MatchNotOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator ! () const {
+ return MatchNotOf<ComparatorT>( *this );
+ }
- CasedString m_data;
- };
- } // namespace StdString
} // namespace Impl
// The following functions create the actual matcher objects.
// This allows the types to be inferred
- template<typename ExpressionT>
- inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) {
- return Impl::Generic::Not<ExpressionT>( m );
- }
-
- template<typename ExpressionT>
- inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
- Impl::Matcher<ExpressionT> const& m2 ) {
- return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
- }
- template<typename ExpressionT>
- inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
- Impl::Matcher<ExpressionT> const& m2,
- Impl::Matcher<ExpressionT> const& m3 ) {
- return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
- }
- template<typename ExpressionT>
- inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
- Impl::Matcher<ExpressionT> const& m2 ) {
- return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
- }
- template<typename ExpressionT>
- inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
- Impl::Matcher<ExpressionT> const& m2,
- Impl::Matcher<ExpressionT> const& m3 ) {
- return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
- }
-
- inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
- return Impl::StdString::Equals( str, caseSensitivity );
- }
- inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
- return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity );
- }
- inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
- return Impl::StdString::Contains( substr, caseSensitivity );
- }
- inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
- return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity );
+ // - deprecated: prefer ||, && and !
+ template<typename T>
+ inline Impl::MatchNotOf<T> Not( Impl::MatcherBase<T> const& underlyingMatcher ) {
+ return Impl::MatchNotOf<T>( underlyingMatcher );
}
- inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
- return Impl::StdString::StartsWith( substr );
+ template<typename T>
+ inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
+ return Impl::MatchAllOf<T>() && m1 && m2;
}
- inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
- return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
+ template<typename T>
+ inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
+ return Impl::MatchAllOf<T>() && m1 && m2 && m3;
}
- inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
- return Impl::StdString::EndsWith( substr );
+ template<typename T>
+ inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
+ return Impl::MatchAnyOf<T>() || m1 || m2;
}
- inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
- return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
+ template<typename T>
+ inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
+ return Impl::MatchAnyOf<T>() || m1 || m2 || m3;
}
} // namespace Matchers
using namespace Matchers;
+using Matchers::Impl::MatcherBase;
} // namespace Catch
@@ -1328,7 +1205,7 @@ namespace Catch {
void captureResult( ResultWas::OfType resultType );
void captureExpression();
void captureExpectedException( std::string const& expectedMessage );
- void captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher );
+ void captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher );
void handleResult( AssertionResult const& result );
void react();
bool shouldDebugBreak() const;
@@ -1358,6 +1235,7 @@ namespace Catch {
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
+#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
#endif
#include <cstddef>
@@ -1874,6 +1752,8 @@ class ExpressionLhs : public DecomposedExpression {
public:
ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
+ ExpressionLhs& operator = ( const ExpressionLhs& );
+
template<typename RhsT>
BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
operator == ( RhsT const& rhs ) {
@@ -1952,6 +1832,8 @@ public:
BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs )
: m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {}
+ BinaryExpression& operator = ( BinaryExpression& );
+
void endExpression() const {
m_rb
.setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
@@ -2246,6 +2128,14 @@ namespace Catch {
}
+#if defined(CATCH_CONFIG_FAST_COMPILE)
+///////////////////////////////////////////////////////////////////////////////
+// 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
+// macro in each assertion
+#define INTERNAL_CATCH_REACT( resultBuilder ) \
+ resultBuilder.react();
+#else
///////////////////////////////////////////////////////////////////////////////
// In the event of a failure works out if the debugger needs to be invoked
// and/or an exception thrown and takes appropriate action.
@@ -2254,6 +2144,7 @@ namespace Catch {
#define INTERNAL_CATCH_REACT( resultBuilder ) \
if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
resultBuilder.react();
+#endif
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
@@ -2262,6 +2153,7 @@ namespace Catch {
try { \
CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
( __catchResult <= expr ).endExpression(); \
+ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
} \
catch( ... ) { \
__catchResult.useActiveException( resultDisposition ); \
@@ -2825,12 +2717,14 @@ namespace Detail {
public:
explicit Approx ( double value )
: m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
+ m_margin( 0.0 ),
m_scale( 1.0 ),
m_value( value )
{}
Approx( Approx const& other )
: m_epsilon( other.m_epsilon ),
+ m_margin( other.m_margin ),
m_scale( other.m_scale ),
m_value( other.m_value )
{}
@@ -2842,6 +2736,7 @@ namespace Detail {
Approx operator()( double value ) {
Approx approx( value );
approx.epsilon( m_epsilon );
+ approx.margin( m_margin );
approx.scale( m_scale );
return approx;
}
@@ -2851,7 +2746,11 @@ namespace Detail {
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 std::fabs( lhs_v - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs_v), std::fabs(rhs.m_value) ) );
+ bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value)));
+ if (relativeOK) {
+ return true;
+ }
+ return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin;
}
template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
@@ -2895,7 +2794,11 @@ namespace Detail {
#else
friend bool operator == ( double lhs, Approx const& rhs ) {
// Thanks to Richard Harris for his help refining this formula
- return std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) );
+ bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) );
+ if (relativeOK) {
+ return true;
+ }
+ return std::fabs(lhs - rhs.m_value) < rhs.m_margin;
}
friend bool operator == ( Approx const& lhs, double rhs ) {
@@ -2936,6 +2839,11 @@ namespace Detail {
return *this;
}
+ Approx& margin( double newMargin ) {
+ m_margin = newMargin;
+ return *this;
+ }
+
Approx& scale( double newScale ) {
m_scale = newScale;
return *this;
@@ -2949,6 +2857,7 @@ namespace Detail {
private:
double m_epsilon;
+ double m_margin;
double m_scale;
double m_value;
};
@@ -2961,6 +2870,153 @@ inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
} // end namespace Catch
+// #included from: internal/catch_matchers_string.h
+#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
+
+namespace Catch {
+namespace Matchers {
+
+ namespace StdString {
+
+ struct CasedString
+ {
+ CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
+ std::string adjustString( std::string const& str ) const;
+ std::string caseSensitivitySuffix() const;
+
+ CaseSensitive::Choice m_caseSensitivity;
+ std::string m_str;
+ };
+
+ struct StringMatcherBase : MatcherBase<std::string> {
+ StringMatcherBase( std::string operation, CasedString const& comparator );
+ virtual std::string describe() const CATCH_OVERRIDE;
+
+ CasedString m_comparator;
+ std::string m_operation;
+ };
+
+ struct EqualsMatcher : StringMatcherBase {
+ EqualsMatcher( CasedString const& comparator );
+ virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
+ };
+ struct ContainsMatcher : StringMatcherBase {
+ ContainsMatcher( CasedString const& comparator );
+ virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
+ };
+ struct StartsWithMatcher : StringMatcherBase {
+ StartsWithMatcher( CasedString const& comparator );
+ virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
+ };
+ struct EndsWithMatcher : StringMatcherBase {
+ EndsWithMatcher( CasedString const& comparator );
+ virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
+ };
+
+ } // namespace StdString
+
+ // The following functions create the actual matcher objects.
+ // This allows the types to be inferred
+
+ StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+ StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+ StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+ StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
+
+} // namespace Matchers
+} // namespace Catch
+
+// #included from: internal/catch_matchers_vector.h
+#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
+
+namespace Catch {
+namespace Matchers {
+
+ namespace Vector {
+
+ template<typename T>
+ struct ContainsElementMatcher : MatcherBase<std::vector<T>, T> {
+
+ ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
+
+ bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
+ return std::find(v.begin(), v.end(), m_comparator) != v.end();
+ }
+
+ virtual std::string describe() const CATCH_OVERRID