diff --git a/.gitignore b/.gitignore index f017e9e09f..2f6440be05 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ Build cmake-build-* benchmark-dir .conan/test_package/build +_*/ +.vscode/ diff --git a/docs/matchers.md b/docs/matchers.md index adbd4ce7bf..c21a0beaf2 100644 --- a/docs/matchers.md +++ b/docs/matchers.md @@ -76,9 +76,9 @@ used only during reporting of the result. It's easy to provide your own matchers to extend Catch or just to work with your own types. You need to provide two things: -1. A matcher class, derived from `Catch::MatcherBase` - where `T` is the type being tested. +1. A matcher class, derived from `Catch::MatcherBase`. The constructor takes and stores any arguments needed (e.g. something to compare against) and you must -override two methods: `match()` and `describe()`. +provide two methods: `match()` and `describe()`. 2. A simple builder function. This is what is actually called from the test code and allows overloading. Here's an example for asserting that an integer falls within a given range @@ -86,13 +86,13 @@ Here's an example for asserting that an integer falls within a given range ```c++ // The matcher class -class IntRange : public Catch::MatcherBase { +class IntRange : public Catch::MatcherBase { int m_begin, m_end; public: IntRange( int begin, int end ) : m_begin( begin ), m_end( end ) {} // Performs the test for this matcher - virtual bool match( int const& i ) const override { + bool match( int const& i ) const { return i >= m_begin && i <= m_end; } @@ -100,7 +100,7 @@ public: // include any provided data (the begin/ end in this case) and // be written as if it were stating a fact (in the output it will be // preceded by the value under test). - virtual std::string describe() const { + std::string describe() const { std::ostringstream ss; ss << "is between " << m_begin << " and " << m_end; return ss.str(); diff --git a/examples/207-Rpt-TeamCityReporter.cpp b/examples/207-Rpt-TeamCityReporter.cpp index d28460f400..35a954a870 100644 --- a/examples/207-Rpt-TeamCityReporter.cpp +++ b/examples/207-Rpt-TeamCityReporter.cpp @@ -85,30 +85,25 @@ struct MyException: public std::runtime_error // prevent -Wweak-vtables: MyException::~MyException() = default; -struct MyExceptionMatcher : Catch::MatcherBase< std::runtime_error > +struct MyExceptionMatcher : Catch::MatcherBase { std::string m_text; MyExceptionMatcher( char const * text ) : m_text( text ) {} - - ~MyExceptionMatcher() override; - bool match( std::runtime_error const & arg ) const override + bool match( std::runtime_error const & arg ) const { return m_text == arg.what() ; } - std::string describe() const override + std::string describe() const { return "it's me"; } }; -// prevent -Wweak-vtables: -MyExceptionMatcher::~MyExceptionMatcher() = default; - TEST_CASE( "TeamCity failing check-throws-matches", "[teamcity]" ) { CHECK_THROWS_MATCHES( throw MyException("hello"), MyException, MyExceptionMatcher("world") ); diff --git a/include/internal/catch_capture_matchers.cpp b/include/internal/catch_capture_matchers.cpp deleted file mode 100644 index 6f320449a2..0000000000 --- a/include/internal/catch_capture_matchers.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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; - - // This is the general overload that takes a any string matcher - // There is another overload, in catch_assertionhandler.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 const& matcherString ) { - std::string exceptionMessage = Catch::translateActiveException(); - MatchExpr expr( exceptionMessage, matcher, matcherString ); - handler.handleExpr( expr ); - } - -} // namespace Catch diff --git a/include/internal/catch_capture_matchers.h b/include/internal/catch_capture_matchers.h index 0ced01d578..60687e14fd 100644 --- a/include/internal/catch_capture_matchers.h +++ b/include/internal/catch_capture_matchers.h @@ -15,18 +15,19 @@ #include "catch_matchers_string.h" #include "catch_matchers_vector.h" #include "catch_stringref.h" +#include "catch_interfaces_registry_hub.h" namespace Catch { template class MatchExpr : public ITransientExpression { - ArgT const& m_arg; + ArgT m_arg; MatcherT m_matcher; StringRef m_matcherString; public: - MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) + MatchExpr( ArgT arg, MatcherT const& matcher, StringRef const& matcherString ) : ITransientExpression{ true, matcher.match( arg ) }, - m_arg( arg ), + m_arg( std::forward(arg) ), m_matcher( matcher ), m_matcherString( matcherString ) {} @@ -41,13 +42,20 @@ namespace Catch { } }; - using StringMatcher = Matchers::Impl::MatcherBase; - - void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ); + // This is the general overload that takes a any string matcher + // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers + // the Equals matcher (so the header does not mention matchers) + template, StringMatcher>::value>::type> + void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ) { + std::string exceptionMessage = Catch::translateActiveException(); + MatchExpr expr( exceptionMessage, matcher, matcherString ); + handler.handleExpr( expr ); + } template - auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr { - return MatchExpr( arg, matcher, matcherString ); + auto makeMatchExpr( ArgT && arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr { + return MatchExpr( std::forward(arg), matcher, matcherString ); } } // namespace Catch diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index e474562204..9dca50d981 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -83,6 +83,23 @@ namespace Catch { T const& operator + ( T const& value, StreamEndStop ) { return value; } + + // backported index_sequnce + template + struct indexSequence + { }; + + template + struct indexSequenceHelper : public indexSequenceHelper + { }; + + template + struct indexSequenceHelper<0U, Next ... > + { using type = indexSequence; }; + + template + using makeIndexSequence = typename indexSequenceHelper::type; + } #define CATCH_INTERNAL_LINEINFO \ diff --git a/include/internal/catch_matchers.cpp b/include/internal/catch_matchers.cpp deleted file mode 100644 index 32104a1123..0000000000 --- a/include/internal/catch_matchers.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Created by Phil Nash on 19/07/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_matchers.h" - -namespace Catch { -namespace Matchers { - namespace Impl { - - std::string MatcherUntypedBase::toString() const { - if( m_cachedToString.empty() ) - m_cachedToString = describe(); - return m_cachedToString; - } - - MatcherUntypedBase::~MatcherUntypedBase() = default; - - } // namespace Impl -} // namespace Matchers - -using namespace Matchers; -using Matchers::Impl::MatcherBase; - -} // namespace Catch diff --git a/include/internal/catch_matchers.h b/include/internal/catch_matchers.h index aebd4c2394..7af89aee2b 100644 --- a/include/internal/catch_matchers.h +++ b/include/internal/catch_matchers.h @@ -17,138 +17,286 @@ namespace Catch { namespace Matchers { namespace Impl { - template struct MatchAllOf; - template struct MatchAnyOf; - template struct MatchNotOf; + template struct MatchAllOf; + template struct MatchAnyOf; + template struct MatchNotOf; - class MatcherUntypedBase { + template + class MatcherBase { public: - MatcherUntypedBase() = default; - MatcherUntypedBase ( MatcherUntypedBase const& ) = default; - MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete; + MatcherBase() = default; + MatcherBase ( MatcherBase const& ) = default; + MatcherBase& operator = ( MatcherBase const& ) = delete; std::string toString() const; + template + MatchAllOf operator && ( Other const& other ) const; + + template + MatchAnyOf operator || ( Other const& other ) const; + + MatchNotOf operator ! () const; + + Derived const& derived() const { return static_cast(*this); } + protected: - virtual ~MatcherUntypedBase(); - virtual std::string describe() const = 0; mutable std::string m_cachedToString; }; -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wnon-virtual-dtor" -#endif + template + std::string MatcherBase::toString() const { + if( m_cachedToString.empty() ) + m_cachedToString = derived().describe(); + return m_cachedToString; + } - template - struct MatcherMethod { - virtual bool match( ObjectT const& arg ) const = 0; - }; + template + using Tuple = std::tuple::type>::type ...>; -#ifdef __clang__ -# pragma clang diagnostic pop -#endif + template + struct MatchAllOf : MatcherBase> { + MatchAllOf( Matchers const &... matchers ) : m_matchers{matchers...} + {} - template - struct MatcherBase : MatcherUntypedBase, MatcherMethod { + // need Dummy type as in https://stackoverflow.com/a/10178791/621176 + template + struct match_helper + { + match_helper( Tuple const& matchers ); + template + bool operator()( ArgT && arg ) const; - MatchAllOf operator && ( MatcherBase const& other ) const; - MatchAnyOf operator || ( MatcherBase const& other ) const; - MatchNotOf operator ! () const; - }; + Tuple const& m_matchers; + }; - template - struct MatchAllOf : MatcherBase { - bool match( ArgT const& arg ) const override { - for( auto matcher : m_matchers ) { - if (!matcher->match(arg)) - return false; - } - return true; + template + bool match( ArgT && arg ) const { + return match_helper<0>{m_matchers}(std::forward(arg)); } - std::string describe() const override { + + template + struct describe_helper{ + describe_helper( Tuple const& matchers ); + + void operator()( std::string &description ) const; + + Tuple const& m_matchers; + }; + + std::string describe() const { std::string description; - description.reserve( 4 + m_matchers.size()*32 ); + description.reserve( 4 + sizeof...(Matchers)*32 ); description += "( "; - bool first = true; - for( auto matcher : m_matchers ) { - if( first ) - first = false; - else - description += " and "; - description += matcher->toString(); - } + describe_helper<0>{m_matchers}(description); description += " )"; return description; } - MatchAllOf& operator && ( MatcherBase const& other ) { - m_matchers.push_back( &other ); - return *this; + template + MatchAllOf and_helper(Other const &other, indexSequence) { + return {std::get(m_matchers)..., other}; + } + + template + MatchAllOf operator && ( Other const& other ) { + return and_helper(other, makeIndexSequence()); } - std::vector const*> m_matchers; + Tuple m_matchers; }; - template - struct MatchAnyOf : MatcherBase { - bool match( ArgT const& arg ) const override { - for( auto matcher : m_matchers ) { - if (matcher->match(arg)) - return true; - } + template + template + MatchAllOf::match_helper::match_helper( Tuple const& matchers ) : m_matchers{matchers} + {} + + template + template + template + bool MatchAllOf::match_helper::operator()( ArgT && arg ) const { + if (!std::get(m_matchers).match(std::forward(arg))) { return false; } - std::string describe() const override { + + return match_helper{m_matchers}(std::forward(arg)); + } + + template + template + struct MatchAllOf::match_helper + { + match_helper( Tuple const& ) {} + + template + bool operator()( ArgT && ) const { + return true; + } + }; + + template + template + MatchAllOf::describe_helper::describe_helper( Tuple const& matchers ) : m_matchers{matchers} + {} + + template + template + void MatchAllOf::describe_helper::operator()( std::string &description ) const { + if (I > 0) { + description += " and "; + } + + description += std::get(m_matchers).describe(); + + describe_helper{m_matchers}(description); + } + + template + template + struct MatchAllOf::describe_helper + { + describe_helper( Tuple const& ) {} + + void operator()( std::string & ) const {} + }; + + template + struct MatchAnyOf : MatcherBase> { + MatchAnyOf( Matchers const &... matchers ) : m_matchers{matchers...} + {} + + template + struct match_helper + { + match_helper( Tuple const& matchers ); + + template + bool operator()( ArgT && arg ) const; + + Tuple const& m_matchers; + }; + + template + bool match( ArgT && arg ) const { + return match_helper<0>{m_matchers}(std::forward(arg)); + } + + template + struct describe_helper{ + describe_helper( Tuple const& matchers ); + + void operator()( std::string &description ) const; + + Tuple const& m_matchers; + }; + + std::string describe() const { std::string description; - description.reserve( 4 + m_matchers.size()*32 ); + description.reserve( 4 + sizeof...(Matchers)*32 ); description += "( "; - bool first = true; - for( auto matcher : m_matchers ) { - if( first ) - first = false; - else - description += " or "; - description += matcher->toString(); - } + describe_helper<0>{m_matchers}(description); description += " )"; return description; } - MatchAnyOf& operator || ( MatcherBase const& other ) { - m_matchers.push_back( &other ); - return *this; + template + MatchAnyOf or_helper(Other const &other, indexSequence) { + return {std::get(m_matchers)..., other}; + } + + template + MatchAnyOf operator || ( Other const& other ) { + return or_helper(other, makeIndexSequence()); } - std::vector const*> m_matchers; + Tuple m_matchers; }; + template + template + MatchAnyOf::match_helper::match_helper( Tuple const& matchers ) : m_matchers{matchers} + {} + + template + template template - struct MatchNotOf : MatcherBase { + bool MatchAnyOf::match_helper::operator()( ArgT && arg ) const { + if (std::get(m_matchers).match(std::forward(arg))) { + return true; + } - MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} + return match_helper{m_matchers}(std::forward(arg)); + } + + template + template + struct MatchAnyOf::match_helper + { + match_helper( Tuple const& ) {} + + template + bool operator()( ArgT && ) const { + return false; + } + }; + + template + template + MatchAnyOf::describe_helper::describe_helper( Tuple const& matchers ) : m_matchers{matchers} + {} - bool match( ArgT const& arg ) const override { - return !m_underlyingMatcher.match( arg ); + template + template + void MatchAnyOf::describe_helper::operator()( std::string &description ) const { + if (I > 0) { + description += " or "; } + + description += std::get(m_matchers).describe(); + + describe_helper{m_matchers}(description); + } - std::string describe() const override { + template + template + struct MatchAnyOf::describe_helper + { + describe_helper( Tuple const& ) {} + + void operator()( std::string & ) const {} + }; + + template + struct MatchNotOf : MatcherBase> { + + MatchNotOf( Matcher const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} + + template + bool match( ArgT && arg ) const { + return !m_underlyingMatcher.match( std::forward(arg) ); + } + + std::string describe() const { return "not " + m_underlyingMatcher.toString(); } - MatcherBase const& m_underlyingMatcher; + Matcher const& m_underlyingMatcher; }; - template - MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const { - return MatchAllOf() && *this && other; + template + template + MatchAllOf MatcherBase::operator && ( Other const& other ) const { + return {derived(), other}; } - template - MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const { - return MatchAnyOf() || *this || other; + + template + template + MatchAnyOf MatcherBase::operator || ( Other const& other ) const { + return {derived(), other}; } - template - MatchNotOf MatcherBase::operator ! () const { - return MatchNotOf( *this ); + + template + MatchNotOf MatcherBase::operator ! () const { + return {derived()}; } } // namespace Impl diff --git a/include/internal/catch_matchers_floating.h b/include/internal/catch_matchers_floating.h index ee077526b6..10ac829770 100644 --- a/include/internal/catch_matchers_floating.h +++ b/include/internal/catch_matchers_floating.h @@ -19,19 +19,19 @@ namespace Matchers { enum class FloatingPointKind : uint8_t; - struct WithinAbsMatcher : MatcherBase { + struct WithinAbsMatcher : MatcherBase { WithinAbsMatcher(double target, double margin); - bool match(double const& matchee) const override; - std::string describe() const override; + bool match(double const& matchee) const ; + std::string describe() const ; private: double m_target; double m_margin; }; - struct WithinUlpsMatcher : MatcherBase { + struct WithinUlpsMatcher : MatcherBase { WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType); - bool match(double const& matchee) const override; - std::string describe() const override; + bool match(double const& matchee) const ; + std::string describe() const ; private: double m_target; int m_ulps; diff --git a/include/internal/catch_matchers_generic.hpp b/include/internal/catch_matchers_generic.hpp index 7c4f9f1dd2..523e90f5de 100644 --- a/include/internal/catch_matchers_generic.hpp +++ b/include/internal/catch_matchers_generic.hpp @@ -21,22 +21,21 @@ namespace Detail { std::string finalizeDescription(const std::string& desc); } -template -class PredicateMatcher : public MatcherBase { - std::function m_predicate; +template +class PredicateMatcher : public MatcherBase>, PredicateF { std::string m_description; public: - PredicateMatcher(std::function const& elem, std::string const& descr) - :m_predicate(std::move(elem)), - m_description(Detail::finalizeDescription(descr)) + PredicateMatcher( PredicateF const& predicateF, std::string const& descr ) + : PredicateF{predicateF}, m_description(Detail::finalizeDescription(descr)) {} - bool match( T const& item ) const override { - return m_predicate(item); + template + bool match( ArgT && item ) const { + return (*this)(std::forward(item)); } - std::string describe() const override { + std::string describe() const { return m_description; } }; @@ -47,9 +46,14 @@ class PredicateMatcher : public MatcherBase { // The user has to explicitly specify type to the function, because // infering std::function is hard (but possible) and // requires a lot of TMP. - template - Generic::PredicateMatcher Predicate(std::function const& predicate, std::string const& description = "") { - return Generic::PredicateMatcher(predicate, description); + template::value>::type> + Generic::PredicateMatcher Predicate(PredicateF &&predicateF, std::string const& description = "") { + return Generic::PredicateMatcher(predicateF, description); + } + + template + Generic::PredicateMatcher> Predicate(bool(&predicateF)(const ArgT), std::string const& description = "") { + return Generic::PredicateMatcher>(predicateF, description); } } // namespace Matchers diff --git a/include/internal/catch_matchers_string.cpp b/include/internal/catch_matchers_string.cpp index 1e3e72fdfe..b3f7b87789 100644 --- a/include/internal/catch_matchers_string.cpp +++ b/include/internal/catch_matchers_string.cpp @@ -32,24 +32,6 @@ namespace Matchers { : std::string(); } - - StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) - : m_comparator( comparator ), - m_operation( operation ) { - } - - std::string StringMatcherBase::describe() const { - std::string description; - description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + - m_comparator.caseSensitivitySuffix().size()); - description += m_operation; - description += ": \""; - description += m_comparator.m_str; - description += "\""; - description += m_comparator.caseSensitivitySuffix(); - return description; - } - EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} bool EqualsMatcher::match( std::string const& source ) const { diff --git a/include/internal/catch_matchers_string.h b/include/internal/catch_matchers_string.h index fdbc03ce75..c20c0bb414 100644 --- a/include/internal/catch_matchers_string.h +++ b/include/internal/catch_matchers_string.h @@ -27,42 +27,63 @@ namespace Matchers { std::string m_str; }; - struct StringMatcherBase : MatcherBase { + template + struct StringMatcherBase : MatcherBase { StringMatcherBase( std::string const& operation, CasedString const& comparator ); - std::string describe() const override; + std::string describe() const ; CasedString m_comparator; std::string m_operation; }; - struct EqualsMatcher : StringMatcherBase { + + template + StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) + : m_comparator( comparator ), + m_operation( operation ) { + } + + template + std::string StringMatcherBase::describe() const { + std::string description; + description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + + m_comparator.caseSensitivitySuffix().size()); + description += m_operation; + description += ": \""; + description += m_comparator.m_str; + description += "\""; + description += m_comparator.caseSensitivitySuffix(); + return description; + } + + struct EqualsMatcher : StringMatcherBase { EqualsMatcher( CasedString const& comparator ); - bool match( std::string const& source ) const override; + bool match( std::string const& source ) const ; }; - struct ContainsMatcher : StringMatcherBase { + struct ContainsMatcher : StringMatcherBase { ContainsMatcher( CasedString const& comparator ); - bool match( std::string const& source ) const override; + bool match( std::string const& source ) const ; }; - struct StartsWithMatcher : StringMatcherBase { + struct StartsWithMatcher : StringMatcherBase { StartsWithMatcher( CasedString const& comparator ); - bool match( std::string const& source ) const override; + bool match( std::string const& source ) const ; }; - struct EndsWithMatcher : StringMatcherBase { + struct EndsWithMatcher : StringMatcherBase { EndsWithMatcher( CasedString const& comparator ); - bool match( std::string const& source ) const override; + bool match( std::string const& source ) const ; }; - struct RegexMatcher : MatcherBase { + struct RegexMatcher : MatcherBase { RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity ); - bool match( std::string const& matchee ) const override; - std::string describe() const override; + bool match( std::string const& matchee ) const ; + std::string describe() const ; private: std::string m_regex; CaseSensitive::Choice m_caseSensitivity; }; - } // namespace StdString + } // namespace StdString` // The following functions create the actual matcher objects. diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h index 1e29cc9403..6ccb4dacbf 100644 --- a/include/internal/catch_matchers_vector.h +++ b/include/internal/catch_matchers_vector.h @@ -39,11 +39,11 @@ namespace Matchers { } template - struct ContainsElementMatcher : MatcherBase> { + struct ContainsElementMatcher : MatcherBase> { ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} - bool match(std::vector const &v) const override { + bool match(std::vector const &v) const { for (auto const& el : v) { if (el == m_comparator) { return true; @@ -52,7 +52,7 @@ namespace Matchers { return false; } - std::string describe() const override { + std::string describe() const { return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } @@ -60,11 +60,11 @@ namespace Matchers { }; template - struct ContainsMatcher : MatcherBase> { + struct ContainsMatcher : MatcherBase> { ContainsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - bool match(std::vector const &v) const override { + bool match(std::vector const &v) const { // !TBD: see note in EqualsMatcher if (m_comparator.size() > v.size()) return false; @@ -82,7 +82,7 @@ namespace Matchers { } return true; } - std::string describe() const override { + std::string describe() const { return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } @@ -90,11 +90,11 @@ namespace Matchers { }; template - struct EqualsMatcher : MatcherBase> { + struct EqualsMatcher : MatcherBase> { EqualsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} - bool match(std::vector const &v) const override { + bool match(std::vector const &v) const { // !TBD: This currently works if all elements can be compared using != // - a more general approach would be via a compare template that defaults // to using !=. but could be specialised for, e.g. std::vector etc @@ -106,16 +106,16 @@ namespace Matchers { return false; return true; } - std::string describe() const override { + std::string describe() const { return "Equals: " + ::Catch::Detail::stringify( m_comparator ); } std::vector const& m_comparator; }; template - struct UnorderedEqualsMatcher : MatcherBase> { + struct UnorderedEqualsMatcher : MatcherBase> { UnorderedEqualsMatcher(std::vector const& target) : m_target(target) {} - bool match(std::vector const& vec) const override { + bool match(std::vector const& vec) const { // Note: This is a reimplementation of std::is_permutation, // because I don't want to include inside the common path if (m_target.size() != vec.size()) { @@ -145,7 +145,7 @@ namespace Matchers { return true; } - std::string describe() const override { + std::string describe() const { return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); } private: diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp index 39cbb1fa89..5d4864a211 100644 --- a/include/internal/catch_objc.hpp +++ b/include/internal/catch_objc.hpp @@ -109,14 +109,14 @@ namespace Catch { namespace Impl { namespace NSStringMatchers { - struct StringHolder : MatcherBase{ + struct StringHolder : MatcherBase{ StringHolder( NSString* substr ) : m_substr( [substr copy] ){} StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} StringHolder() { arcSafeRelease( m_substr ); } - bool match( NSString* arg ) const override { + bool match( NSString* arg ) const { return false; } @@ -126,12 +126,12 @@ namespace Catch { struct Equals : StringHolder { Equals( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* str ) const override { + bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str isEqualToString:m_substr]; } - std::string describe() const override { + std::string describe() const { return "equals string: " + Catch::Detail::stringify( m_substr ); } }; @@ -144,7 +144,7 @@ namespace Catch { [str rangeOfString:m_substr].location != NSNotFound; } - std::string describe() const override { + std::string describe() const { return "contains string: " + Catch::Detail::stringify( m_substr ); } }; @@ -152,24 +152,24 @@ namespace Catch { struct StartsWith : StringHolder { StartsWith( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* str ) const override { + bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == 0; } - std::string describe() const override { + std::string describe() const { return "starts with: " + Catch::Detail::stringify( m_substr ); } }; struct EndsWith : StringHolder { EndsWith( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* str ) const override { + bool match( NSString* str ) const { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == [str length] - [m_substr length]; } - std::string describe() const override { + std::string describe() const { return "ends with: " + Catch::Detail::stringify( m_substr ); } }; diff --git a/include/internal/catch_test_spec.h b/include/internal/catch_test_spec.h index baf8b0193b..410a807b60 100644 --- a/include/internal/catch_test_spec.h +++ b/include/internal/catch_test_spec.h @@ -33,7 +33,7 @@ namespace Catch { public: NamePattern( std::string const& name ); virtual ~NamePattern(); - virtual bool matches( TestCaseInfo const& testCase ) const override; + virtual bool matches( TestCaseInfo const& testCase ) const ; private: WildcardPattern m_wildcardPattern; }; @@ -42,7 +42,7 @@ namespace Catch { public: TagPattern( std::string const& tag ); virtual ~TagPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const override; + virtual bool matches( TestCaseInfo const& testCase ) const ; private: std::string m_tag; }; @@ -51,7 +51,7 @@ namespace Catch { public: ExcludedPattern( PatternPtr const& underlyingPattern ); virtual ~ExcludedPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const override; + virtual bool matches( TestCaseInfo const& testCase ) const ; private: PatternPtr m_underlyingPattern; }; diff --git a/include/reporters/catch_reporter_tap.hpp b/include/reporters/catch_reporter_tap.hpp index 1bfe4f5e1c..ffb7f8bc5b 100644 --- a/include/reporters/catch_reporter_tap.hpp +++ b/include/reporters/catch_reporter_tap.hpp @@ -33,7 +33,7 @@ namespace Catch { return m_reporterPrefs; } - void noMatchingTestCases( std::string const& spec ) override { + void nomatchingTestCases( std::string const& spec ) { stream << "# No test cases matched '" << spec << "'" << std::endl; } diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index eca2885cd4..c08213252e 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -49,7 +49,7 @@ namespace Catch { void skipTest( TestCaseInfo const& /* testInfo */ ) override { } - void noMatchingTestCases( std::string const& /* spec */ ) override {} + void nomatchingTestCases( std::string const& /* spec */ ) {} void testGroupStarting( GroupInfo const& groupInfo ) override { StreamingReporterBase::testGroupStarting( groupInfo ); diff --git a/projects/CMakeLists.txt b/projects/CMakeLists.txt index b3caa82fe2..04cb7cf46c 100644 --- a/projects/CMakeLists.txt +++ b/projects/CMakeLists.txt @@ -172,7 +172,6 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_assertionhandler.cpp ${HEADER_DIR}/internal/catch_assertionresult.cpp ${HEADER_DIR}/internal/catch_benchmark.cpp - ${HEADER_DIR}/internal/catch_capture_matchers.cpp ${HEADER_DIR}/internal/catch_commandline.cpp ${HEADER_DIR}/internal/catch_common.cpp ${HEADER_DIR}/internal/catch_config.cpp @@ -195,7 +194,6 @@ set(IMPL_SOURCES ${HEADER_DIR}/internal/catch_interfaces_testcase.cpp ${HEADER_DIR}/internal/catch_list.cpp ${HEADER_DIR}/internal/catch_leak_detector.cpp - ${HEADER_DIR}/internal/catch_matchers.cpp ${HEADER_DIR}/internal/catch_matchers_floating.cpp ${HEADER_DIR}/internal/catch_matchers_generic.cpp ${HEADER_DIR}/internal/catch_matchers_string.cpp diff --git a/projects/SelfTest/Baselines/compact.sw.approved.txt b/projects/SelfTest/Baselines/compact.sw.approved.txt index 31c7ee0da1..075666531b 100644 --- a/projects/SelfTest/Baselines/compact.sw.approved.txt +++ b/projects/SelfTest/Baselines/compact.sw.approved.txt @@ -207,10 +207,10 @@ Approx.tests.cpp:: passed: 0 == Approx( dZero) for: 0 == Approx( 0. Approx.tests.cpp:: passed: 0 == Approx( dSmall ).margin( 0.001 ) for: 0 == Approx( 0.00001 ) Approx.tests.cpp:: passed: 1.234f == Approx( dMedium ) for: 1.234f == Approx( 1.234 ) Approx.tests.cpp:: passed: dMedium == Approx( 1.234f ) for: 1.234 == Approx( 1.2339999676 ) -Matchers.tests.cpp:: passed: 1, Predicate(alwaysTrue, "always true") for: 1 matches predicate: "always true" -Matchers.tests.cpp:: passed: 1, !Predicate(alwaysFalse, "always false") for: 1 not matches predicate: "always false" -Matchers.tests.cpp:: passed: "Hello olleH", Predicate( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal" -Matchers.tests.cpp:: passed: "This wouldn't pass", !Predicate( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate +Matchers.tests.cpp:: passed: 1, Predicate(alwaysTrue, "always true") for: 1 matches predicate: "always true" +Matchers.tests.cpp:: passed: 1, !Predicate(alwaysFalse, "always false") for: 1 not matches predicate: "always false" +Matchers.tests.cpp:: passed: "Hello olleH", Predicate( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") for: "Hello olleH" matches predicate: "First and last character should be equal" +Matchers.tests.cpp:: passed: "This wouldn't pass", !Predicate( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) for: "This wouldn't pass" not matches undescribed predicate Tricky.tests.cpp:: passed: true Tricky.tests.cpp:: passed: true Tricky.tests.cpp:: passed: true @@ -813,7 +813,7 @@ Condition.tests.cpp:: passed: cpc != 0 for: 0x != 0 Condition.tests.cpp:: passed: returnsNull() == 0 for: {null string} == 0 Condition.tests.cpp:: passed: returnsConstNull() == 0 for: {null string} == 0 Condition.tests.cpp:: passed: 0 != p for: 0 != 0x -Matchers.tests.cpp:: passed: "foo", Predicate([] (const char* const&) { return true; }) for: "foo" matches undescribed predicate +Matchers.tests.cpp:: passed: "foo", Predicate([] (const char* const&) { return true; }) for: "foo" matches undescribed predicate CmdLine.tests.cpp:: passed: result for: {?} CmdLine.tests.cpp:: passed: config.processName == "" for: "" == "" CmdLine.tests.cpp:: passed: result for: {?} diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 23f91912ae..88288a4d85 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -1603,12 +1603,12 @@ Matchers.tests.cpp: ............................................................................... Matchers.tests.cpp:: PASSED: - REQUIRE_THAT( 1, Predicate(alwaysTrue, "always true") ) + REQUIRE_THAT( 1, Predicate(alwaysTrue, "always true") ) with expansion: 1 matches predicate: "always true" Matchers.tests.cpp:: PASSED: - REQUIRE_THAT( 1, !Predicate(alwaysFalse, "always false") ) + REQUIRE_THAT( 1, !Predicate(alwaysFalse, "always false") ) with expansion: 1 not matches predicate: "always false" @@ -1620,12 +1620,12 @@ Matchers.tests.cpp: ............................................................................... Matchers.tests.cpp:: PASSED: - REQUIRE_THAT( "Hello olleH", Predicate( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") ) + REQUIRE_THAT( "Hello olleH", Predicate( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") ) with expansion: "Hello olleH" matches predicate: "First and last character should be equal" Matchers.tests.cpp:: PASSED: - REQUIRE_THAT( "This wouldn't pass", !Predicate( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) ) + REQUIRE_THAT( "This wouldn't pass", !Predicate( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) ) with expansion: "This wouldn't pass" not matches undescribed predicate @@ -5825,7 +5825,7 @@ Matchers.tests.cpp: ............................................................................... Matchers.tests.cpp:: PASSED: - REQUIRE_THAT( "foo", Predicate([] (const char* const&) { return true; }) ) + REQUIRE_THAT( "foo", Predicate([] (const char* const&) { return true; }) ) with expansion: "foo" matches undescribed predicate diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 60257c25df..9f5e59014d 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1831,7 +1831,7 @@
- 1, Predicate<int>(alwaysTrue, "always true") + 1, Predicate(alwaysTrue, "always true") 1 matches predicate: "always true" @@ -1839,7 +1839,7 @@ - 1, !Predicate<int>(alwaysFalse, "always false") + 1, !Predicate(alwaysFalse, "always false") 1 not matches predicate: "always false" @@ -1850,7 +1850,7 @@
- "Hello olleH", Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") + "Hello olleH", Predicate( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") "Hello olleH" matches predicate: "First and last character should be equal" @@ -1858,7 +1858,7 @@ - "This wouldn't pass", !Predicate<std::string>( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) + "This wouldn't pass", !Predicate( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) "This wouldn't pass" not matches undescribed predicate @@ -7404,7 +7404,7 @@ - "foo", Predicate<const char*>([] (const char* const&) { return true; }) + "foo", Predicate([] (const char* const&) { return true; }) "foo" matches undescribed predicate diff --git a/projects/SelfTest/UsageTests/Matchers.tests.cpp b/projects/SelfTest/UsageTests/Matchers.tests.cpp index f07481d46d..97c5bf00b7 100644 --- a/projects/SelfTest/UsageTests/Matchers.tests.cpp +++ b/projects/SelfTest/UsageTests/Matchers.tests.cpp @@ -64,16 +64,16 @@ namespace { namespace MatchersTests { throw i; } - class ExceptionMatcher : public Catch::MatcherBase { + class ExceptionMatcher : public Catch::MatcherBase { int m_expected; public: ExceptionMatcher(int i) : m_expected(i) {} - bool match(SpecialException const &se) const override { + bool match(SpecialException const &se) const { return se.i == m_expected; } - std::string describe() const override { + std::string describe() const { std::ostringstream ss; ss << "special exception has value of " << m_expected; return ss.str(); @@ -405,18 +405,18 @@ namespace { namespace MatchersTests { TEST_CASE("Arbitrary predicate matcher", "[matchers][generic]") { SECTION("Function pointer") { - REQUIRE_THAT(1, Predicate(alwaysTrue, "always true")); - REQUIRE_THAT(1, !Predicate(alwaysFalse, "always false")); + REQUIRE_THAT(1, Predicate(alwaysTrue, "always true")); + REQUIRE_THAT(1, !Predicate(alwaysFalse, "always false")); } SECTION("Lambdas + different type") { REQUIRE_THAT("Hello olleH", - Predicate( + Predicate( [] (std::string const& str) -> bool { return str.front() == str.back(); }, "First and last character should be equal") ); REQUIRE_THAT("This wouldn't pass", - !Predicate( + !Predicate( [] (std::string const& str) -> bool { return str.front() == str.back(); } ) ); @@ -433,7 +433,7 @@ namespace { namespace MatchersTests { } TEST_CASE("Predicate matcher can accept const char*", "[matchers][compilation]") { - REQUIRE_THAT("foo", Predicate([] (const char* const&) { return true; })); + REQUIRE_THAT("foo", Predicate([] (const char* const&) { return true; })); } } } // namespace MatchersTests