mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 12:17:11 +01:00 
			
		
		
		
	Start fixing up Matchers: namespaces, composition ops
This commit also forbids composing lvalues of composed matchers, as per previous deprecation notice. I do not expect this to be contentious in practice, because there was a bug in that usage for years, and nobody complained.
This commit is contained in:
		| @@ -9,34 +9,6 @@ either of these is a breaking change, and thus will not happen until | |||||||
| at least the next major release. | at least the next major release. | ||||||
|  |  | ||||||
|  |  | ||||||
| ### Composing lvalues of already composed matchers |  | ||||||
|  |  | ||||||
| Because a significant bug in this use case has persisted for 2+ years |  | ||||||
| without a bug report, and to simplify the implementation, code that |  | ||||||
| composes lvalues of composed matchers will not compile. That is, |  | ||||||
| this code will no longer work: |  | ||||||
|  |  | ||||||
| ```cpp |  | ||||||
|             auto m1 = Contains("string"); |  | ||||||
|             auto m2 = Contains("random"); |  | ||||||
|             auto composed1 = m1 || m2; |  | ||||||
|             auto m3 = Contains("different"); |  | ||||||
|             auto composed2 = composed1 || m3; |  | ||||||
|             REQUIRE_THAT(foo(), !composed1); |  | ||||||
|             REQUIRE_THAT(foo(), composed2); |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Instead you will have to write this: |  | ||||||
|  |  | ||||||
| ```cpp |  | ||||||
|             auto m1 = Contains("string"); |  | ||||||
|             auto m2 = Contains("random"); |  | ||||||
|             auto m3 = Contains("different"); |  | ||||||
|             REQUIRE_THAT(foo(), !(m1 || m2)); |  | ||||||
|             REQUIRE_THAT(foo(), m1 || m2 || m3); |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ## Planned changes | ## Planned changes | ||||||
|  |  | ||||||
|   | |||||||
| @@ -53,6 +53,7 @@ | |||||||
|   * The description type now must be a `const char*` or implicitly convertible to it |   * The description type now must be a `const char*` or implicitly convertible to it | ||||||
| * The `[!hide]` tag has been removed. | * The `[!hide]` tag has been removed. | ||||||
|   * Use `[.]` or `[.foo]` instead. |   * Use `[.]` or `[.foo]` instead. | ||||||
|  | * Lvalues of composed matchers cannot be composed further | ||||||
|  |  | ||||||
| ### Fixes | ### Fixes | ||||||
| * The `INFO` macro no longer contains superfluous semicolon (#1456) | * The `INFO` macro no longer contains superfluous semicolon (#1456) | ||||||
|   | |||||||
| @@ -26,7 +26,6 @@ | |||||||
| #include <catch2/catch_compiler_capabilities.h> | #include <catch2/catch_compiler_capabilities.h> | ||||||
| #include <catch2/catch_string_manip.h> | #include <catch2/catch_string_manip.h> | ||||||
|  |  | ||||||
| #include <catch2/catch_capture_matchers.h> |  | ||||||
| #include <catch2/catch_generators.hpp> | #include <catch2/catch_generators.hpp> | ||||||
| #include <catch2/catch_generators_generic.hpp> | #include <catch2/catch_generators_generic.hpp> | ||||||
| #include <catch2/catch_generators_specific.hpp> | #include <catch2/catch_generators_specific.hpp> | ||||||
|   | |||||||
| @@ -10,8 +10,6 @@ | |||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
|  |  | ||||||
|     using StringMatcher = Matchers::Impl::MatcherBase<std::string>; |  | ||||||
|  |  | ||||||
|     // This is the general overload that takes a any string matcher |     // 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 |     // 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) |     // the Equals matcher (so the header does not mention matchers) | ||||||
|   | |||||||
| @@ -17,7 +17,7 @@ namespace Catch { | |||||||
|     template<typename ArgT, typename MatcherT> |     template<typename ArgT, typename MatcherT> | ||||||
|     class MatchExpr : public ITransientExpression { |     class MatchExpr : public ITransientExpression { | ||||||
|         ArgT && m_arg; |         ArgT && m_arg; | ||||||
|         MatcherT m_matcher; |         MatcherT const& m_matcher; | ||||||
|         StringRef m_matcherString; |         StringRef m_matcherString; | ||||||
|     public: |     public: | ||||||
|         MatchExpr( ArgT && arg, MatcherT const& matcher, StringRef const& matcherString ) |         MatchExpr( ArgT && arg, MatcherT const& matcher, StringRef const& matcherString ) | ||||||
| @@ -37,7 +37,7 @@ namespace Catch { | |||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     using StringMatcher = Matchers::Impl::MatcherBase<std::string>; |     using StringMatcher = Matchers::MatcherBase<std::string>; | ||||||
|  |  | ||||||
|     void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  ); |     void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  ); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ | |||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
| namespace Matchers { | namespace Matchers { | ||||||
|     namespace Impl { |  | ||||||
|  |  | ||||||
|         std::string MatcherUntypedBase::toString() const { |         std::string MatcherUntypedBase::toString() const { | ||||||
|             if( m_cachedToString.empty() ) |             if( m_cachedToString.empty() ) | ||||||
| @@ -19,10 +18,5 @@ namespace Matchers { | |||||||
|  |  | ||||||
|         MatcherUntypedBase::~MatcherUntypedBase() = default; |         MatcherUntypedBase::~MatcherUntypedBase() = default; | ||||||
|  |  | ||||||
|     } // namespace Impl |  | ||||||
| } // namespace Matchers | } // namespace Matchers | ||||||
|  |  | ||||||
| using namespace Matchers; |  | ||||||
| using Matchers::Impl::MatcherBase; |  | ||||||
|  |  | ||||||
| } // namespace Catch | } // namespace Catch | ||||||
|   | |||||||
| @@ -15,11 +15,11 @@ | |||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
| namespace Matchers { | namespace Matchers { | ||||||
|     namespace Impl { |  | ||||||
|  |  | ||||||
|         template<typename ArgT> struct MatchAllOf; | #ifdef __clang__ | ||||||
|         template<typename ArgT> struct MatchAnyOf; | #    pragma clang diagnostic push | ||||||
|         template<typename ArgT> struct MatchNotOf; | #    pragma clang diagnostic ignored "-Wnon-virtual-dtor" | ||||||
|  | #endif | ||||||
|  |  | ||||||
|         class MatcherUntypedBase { |         class MatcherUntypedBase { | ||||||
|         public: |         public: | ||||||
| @@ -29,16 +29,11 @@ namespace Matchers { | |||||||
|             std::string toString() const; |             std::string toString() const; | ||||||
|  |  | ||||||
|         protected: |         protected: | ||||||
|             virtual ~MatcherUntypedBase(); |             virtual ~MatcherUntypedBase(); // = default; | ||||||
|             virtual std::string describe() const = 0; |             virtual std::string describe() const = 0; | ||||||
|             mutable std::string m_cachedToString; |             mutable std::string m_cachedToString; | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
| #ifdef __clang__ |  | ||||||
| #    pragma clang diagnostic push |  | ||||||
| #    pragma clang diagnostic ignored "-Wnon-virtual-dtor" |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|         template<typename ObjectT> |         template<typename ObjectT> | ||||||
|         struct MatcherMethod { |         struct MatcherMethod { | ||||||
|             virtual bool match( ObjectT const& arg ) const = 0; |             virtual bool match( ObjectT const& arg ) const = 0; | ||||||
| @@ -58,16 +53,19 @@ namespace Matchers { | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
|         template<typename T> |         template<typename T> | ||||||
|         struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> { |         struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> {}; | ||||||
|  |  | ||||||
|  |     namespace Detail { | ||||||
|             MatchAllOf<T> operator && ( MatcherBase const& other ) const; |  | ||||||
|             MatchAnyOf<T> operator || ( MatcherBase const& other ) const; |  | ||||||
|             MatchNotOf<T> operator ! () const; |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         template<typename ArgT> |         template<typename ArgT> | ||||||
|         struct MatchAllOf : MatcherBase<ArgT> { |         struct MatchAllOf : MatcherBase<ArgT> { | ||||||
|  |             MatchAllOf() = default; | ||||||
|  |             MatchAllOf(MatchAllOf const&) = delete; | ||||||
|  |             MatchAllOf& operator=(MatchAllOf const&) = delete; | ||||||
|  |             MatchAllOf(MatchAllOf&&) = default; | ||||||
|  |             MatchAllOf& operator=(MatchAllOf&&) = default; | ||||||
|  |  | ||||||
|  |  | ||||||
|             bool match( ArgT const& arg ) const override { |             bool match( ArgT const& arg ) const override { | ||||||
|                 for( auto matcher : m_matchers ) { |                 for( auto matcher : m_matchers ) { | ||||||
|                     if (!matcher->match(arg)) |                     if (!matcher->match(arg)) | ||||||
| @@ -91,16 +89,35 @@ namespace Matchers { | |||||||
|                 return description; |                 return description; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             MatchAllOf<ArgT> operator && ( MatcherBase<ArgT> const& other ) { |             friend MatchAllOf operator&& (MatchAllOf&& lhs, MatcherBase<ArgT> const& rhs) { | ||||||
|                 auto copy(*this); |                 lhs.m_matchers.push_back(&rhs); | ||||||
|                 copy.m_matchers.push_back( &other ); |                 return std::move(lhs); | ||||||
|                 return copy; |             } | ||||||
|  |             friend MatchAllOf operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf&& rhs) { | ||||||
|  |                 rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs); | ||||||
|  |                 return std::move(rhs); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |         private: | ||||||
|             std::vector<MatcherBase<ArgT> const*> m_matchers; |             std::vector<MatcherBase<ArgT> const*> m_matchers; | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  |         //! lvalue overload is intentionally deleted, users should | ||||||
|  |         //! not be trying to compose stored composition matchers | ||||||
|  |         template<typename ArgT> | ||||||
|  |         MatchAllOf<ArgT> operator&& (MatchAllOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete; | ||||||
|  |         //! lvalue overload is intentionally deleted, users should | ||||||
|  |         //! not be trying to compose stored composition matchers | ||||||
|  |         template<typename ArgT> | ||||||
|  |         MatchAllOf<ArgT> operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf<ArgT> const& rhs) = delete; | ||||||
|  |  | ||||||
|         template<typename ArgT> |         template<typename ArgT> | ||||||
|         struct MatchAnyOf : MatcherBase<ArgT> { |         struct MatchAnyOf : MatcherBase<ArgT> { | ||||||
|  |             MatchAnyOf() = default; | ||||||
|  |             MatchAnyOf(MatchAnyOf const&) = delete; | ||||||
|  |             MatchAnyOf& operator=(MatchAnyOf const&) = delete; | ||||||
|  |             MatchAnyOf(MatchAnyOf&&) = default; | ||||||
|  |             MatchAnyOf& operator=(MatchAnyOf&&) = default; | ||||||
|  |  | ||||||
|             bool match( ArgT const& arg ) const override { |             bool match( ArgT const& arg ) const override { | ||||||
|                 for( auto matcher : m_matchers ) { |                 for( auto matcher : m_matchers ) { | ||||||
| @@ -125,19 +142,34 @@ namespace Matchers { | |||||||
|                 return description; |                 return description; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             MatchAnyOf<ArgT> operator || ( MatcherBase<ArgT> const& other ) { |             friend MatchAnyOf operator|| (MatchAnyOf&& lhs, MatcherBase<ArgT> const& rhs) { | ||||||
|                 auto copy(*this); |                 lhs.m_matchers.push_back(&rhs); | ||||||
|                 copy.m_matchers.push_back( &other ); |                 return std::move(lhs); | ||||||
|                 return copy; |             } | ||||||
|  |             friend MatchAnyOf operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf&& rhs) { | ||||||
|  |                 rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs); | ||||||
|  |                 return std::move(rhs); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |         private: | ||||||
|             std::vector<MatcherBase<ArgT> const*> m_matchers; |             std::vector<MatcherBase<ArgT> const*> m_matchers; | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|  |         //! lvalue overload is intentionally deleted, users should | ||||||
|  |         //! not be trying to compose stored composition matchers | ||||||
|  |         template<typename ArgT> | ||||||
|  |         MatchAnyOf<ArgT> operator|| (MatchAnyOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete; | ||||||
|  |         //! lvalue overload is intentionally deleted, users should | ||||||
|  |         //! not be trying to compose stored composition matchers | ||||||
|  |         template<typename ArgT> | ||||||
|  |         MatchAnyOf<ArgT> operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf<ArgT> const& rhs) = delete; | ||||||
|  |  | ||||||
|         template<typename ArgT> |         template<typename ArgT> | ||||||
|         struct MatchNotOf : MatcherBase<ArgT> { |         struct MatchNotOf : MatcherBase<ArgT> { | ||||||
|  |  | ||||||
|             MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} |             explicit MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ): | ||||||
|  |                 m_underlyingMatcher( underlyingMatcher ) | ||||||
|  |             {} | ||||||
|  |  | ||||||
|             bool match( ArgT const& arg ) const override { |             bool match( ArgT const& arg ) const override { | ||||||
|                 return !m_underlyingMatcher.match( arg ); |                 return !m_underlyingMatcher.match( arg ); | ||||||
| @@ -146,29 +178,29 @@ namespace Matchers { | |||||||
|             std::string describe() const override { |             std::string describe() const override { | ||||||
|                 return "not " + m_underlyingMatcher.toString(); |                 return "not " + m_underlyingMatcher.toString(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |         private: | ||||||
|             MatcherBase<ArgT> const& m_underlyingMatcher; |             MatcherBase<ArgT> const& m_underlyingMatcher; | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         template<typename T> |     } // namespace Detail | ||||||
|         MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const { |  | ||||||
|             return MatchAllOf<T>() && *this && other; |     template <typename T> | ||||||
|  |     Detail::MatchAllOf<T> operator&& (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) { | ||||||
|  |         return Detail::MatchAllOf<T>{} && lhs && rhs; | ||||||
|     } |     } | ||||||
|         template<typename T> |     template <typename T> | ||||||
|         MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const { |     Detail::MatchAnyOf<T> operator|| (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) { | ||||||
|             return MatchAnyOf<T>() || *this || other; |         return Detail::MatchAnyOf<T>{} || lhs || rhs; | ||||||
|         } |     } | ||||||
|         template<typename T> |  | ||||||
|         MatchNotOf<T> MatcherBase<T>::operator ! () const { |     template <typename T> | ||||||
|             return MatchNotOf<T>( *this ); |     Detail::MatchNotOf<T> operator! (MatcherBase<T> const& matcher) { | ||||||
|  |         return Detail::MatchNotOf<T>{ matcher }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     } // namespace Impl |  | ||||||
|  |  | ||||||
| } // namespace Matchers | } // namespace Matchers | ||||||
|  |  | ||||||
| using namespace Matchers; |  | ||||||
| using Matchers::Impl::MatcherBase; |  | ||||||
|  |  | ||||||
| } // namespace Catch | } // namespace Catch | ||||||
|  |  | ||||||
| #endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED | #endif // TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED | ||||||
|   | |||||||
| @@ -2,8 +2,9 @@ | |||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
| namespace Matchers { | namespace Matchers { | ||||||
|     namespace Impl { |     MatcherGenericBase::~MatcherGenericBase() = default; | ||||||
|         MatcherGenericBase::~MatcherGenericBase() {} |  | ||||||
|  |     namespace Detail { | ||||||
|  |  | ||||||
|         std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end) { |         std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end) { | ||||||
|             std::string description; |             std::string description; | ||||||
| @@ -27,6 +28,7 @@ namespace Matchers { | |||||||
|             description += " )"; |             description += " )"; | ||||||
|             return description; |             return description; | ||||||
|         } |         } | ||||||
|     } |  | ||||||
|  |     } // namespace Detail | ||||||
| } // namespace Matchers | } // namespace Matchers | ||||||
| } // namespace Catch | } // namespace Catch | ||||||
|   | |||||||
| @@ -14,16 +14,12 @@ | |||||||
|  |  | ||||||
| namespace Catch { | namespace Catch { | ||||||
| namespace Matchers { | namespace Matchers { | ||||||
|     namespace Impl { |  | ||||||
|  |  | ||||||
|         template<typename... MatcherTs> struct MatchAllOfGeneric; |  | ||||||
|         template<typename... MatcherTs> struct MatchAnyOfGeneric; |  | ||||||
|         template<typename MatcherT> struct MatchNotOfGeneric; |  | ||||||
|  |  | ||||||
|     struct MatcherGenericBase : MatcherUntypedBase { |     struct MatcherGenericBase : MatcherUntypedBase { | ||||||
|             virtual ~MatcherGenericBase(); |         virtual ~MatcherGenericBase(); // = default; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     namespace Detail { | ||||||
|         template<std::size_t N, std::size_t M> |         template<std::size_t N, std::size_t M> | ||||||
|         std::array<void const*, N + M> array_cat(std::array<void const*, N> && lhs, std::array<void const*, M> && rhs) { |         std::array<void const*, N + M> array_cat(std::array<void const*, N> && lhs, std::array<void const*, M> && rhs) { | ||||||
|             std::array<void const*, N + M> arr{}; |             std::array<void const*, N + M> arr{}; | ||||||
| @@ -63,7 +59,7 @@ namespace Matchers { | |||||||
|  |  | ||||||
|         template<typename T> |         template<typename T> | ||||||
|         using is_generic_matcher = std::is_base_of< |         using is_generic_matcher = std::is_base_of< | ||||||
|             Catch::Matchers::Impl::MatcherGenericBase, |             Catch::Matchers::MatcherGenericBase, | ||||||
|             typename std::remove_cv<typename std::remove_reference<T>::type>::type |             typename std::remove_cv<typename std::remove_reference<T>::type>::type | ||||||
|         >; |         >; | ||||||
|  |  | ||||||
| @@ -72,7 +68,7 @@ namespace Matchers { | |||||||
|  |  | ||||||
|         template<typename T> |         template<typename T> | ||||||
|         using is_matcher = std::is_base_of< |         using is_matcher = std::is_base_of< | ||||||
|             Catch::Matchers::Impl::MatcherUntypedBase, |             Catch::Matchers::MatcherUntypedBase, | ||||||
|             typename std::remove_cv<typename std::remove_reference<T>::type>::type |             typename std::remove_cv<typename std::remove_reference<T>::type>::type | ||||||
|         >; |         >; | ||||||
|  |  | ||||||
| @@ -161,102 +157,101 @@ namespace Matchers { | |||||||
|  |  | ||||||
|             MatcherT const& m_matcher; |             MatcherT const& m_matcher; | ||||||
|         }; |         }; | ||||||
|  |     } // namespace Detail | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     // FIXME: enable_if_t | ||||||
|  |  | ||||||
|     // compose only generic matchers |     // compose only generic matchers | ||||||
|     template<typename MatcherLHS, typename MatcherRHS> |     template<typename MatcherLHS, typename MatcherRHS> | ||||||
|         typename std::enable_if<are_generic_matchers<MatcherLHS, MatcherRHS>::value, MatchAllOfGeneric<MatcherLHS, MatcherRHS>>::type |     typename std::enable_if<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>>::type | ||||||
|         operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) { |         operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) { | ||||||
|             return {lhs, rhs}; |         return { lhs, rhs }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     template<typename MatcherLHS, typename MatcherRHS> |     template<typename MatcherLHS, typename MatcherRHS> | ||||||
|         typename std::enable_if<are_generic_matchers<MatcherLHS, MatcherRHS>::value, MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>::type |     typename std::enable_if<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>::type | ||||||
|         operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) { |         operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) { | ||||||
|             return {lhs, rhs}; |         return { lhs, rhs }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     template<typename MatcherT> |     template<typename MatcherT> | ||||||
|         typename std::enable_if<is_generic_matcher<MatcherT>::value, MatchNotOfGeneric<MatcherT>>::type |     typename std::enable_if<Detail::is_generic_matcher<MatcherT>::value, Detail::MatchNotOfGeneric<MatcherT>>::type | ||||||
|         operator ! (MatcherT const& matcher) { |         operator ! (MatcherT const& matcher) { | ||||||
|             return MatchNotOfGeneric<MatcherT>{matcher}; |         return Detail::MatchNotOfGeneric<MatcherT>{matcher}; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     // compose mixed generic and non-generic matchers |     // compose mixed generic and non-generic matchers | ||||||
|     template<typename MatcherLHS, typename ArgRHS> |     template<typename MatcherLHS, typename ArgRHS> | ||||||
|         typename std::enable_if<is_generic_matcher<MatcherLHS>::value, MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>::type |     typename std::enable_if<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>::type | ||||||
|         operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) { |         operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) { | ||||||
|             return {lhs, rhs}; |         return { lhs, rhs }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     template<typename ArgLHS, typename MatcherRHS> |     template<typename ArgLHS, typename MatcherRHS> | ||||||
|         typename std::enable_if<is_generic_matcher<MatcherRHS>::value, MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>::type |     typename std::enable_if<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>::type | ||||||
|         operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) { |         operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) { | ||||||
|             return {lhs, rhs}; |         return { lhs, rhs }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     template<typename MatcherLHS, typename ArgRHS> |     template<typename MatcherLHS, typename ArgRHS> | ||||||
|         typename std::enable_if<is_generic_matcher<MatcherLHS>::value, MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>::type |     typename std::enable_if<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>::type | ||||||
|         operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) { |         operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) { | ||||||
|             return {lhs, rhs}; |         return { lhs, rhs }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     template<typename ArgLHS, typename MatcherRHS> |     template<typename ArgLHS, typename MatcherRHS> | ||||||
|         typename std::enable_if<is_generic_matcher<MatcherRHS>::value, MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>::type |     typename std::enable_if<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>::type | ||||||
|         operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) { |         operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) { | ||||||
|             return {lhs, rhs}; |         return { lhs, rhs }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     // avoid deep nesting of matcher templates |     // avoid deep nesting of matcher templates | ||||||
|     template<typename... MatchersLHS, typename... MatchersRHS> |     template<typename... MatchersLHS, typename... MatchersRHS> | ||||||
|         MatchAllOfGeneric<MatchersLHS..., MatchersRHS...> |     Detail::MatchAllOfGeneric<MatchersLHS..., MatchersRHS...> | ||||||
|         operator && (MatchAllOfGeneric<MatchersLHS...> && lhs, MatchAllOfGeneric<MatchersRHS...> && rhs) { |         operator && (Detail::MatchAllOfGeneric<MatchersLHS...>&& lhs, Detail::MatchAllOfGeneric<MatchersRHS...>&& rhs) { | ||||||
|             return MatchAllOfGeneric<MatchersLHS..., MatchersRHS...>{array_cat(std::move(lhs.m_matchers), std::move(rhs.m_matchers))}; |         return Detail::MatchAllOfGeneric<MatchersLHS..., MatchersRHS...>{Detail::array_cat(std::move(lhs.m_matchers), std::move(rhs.m_matchers))}; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     template<typename... MatchersLHS, typename MatcherRHS> |     template<typename... MatchersLHS, typename MatcherRHS> | ||||||
|         typename std::enable_if<is_matcher<MatcherRHS>::value, MatchAllOfGeneric<MatchersLHS..., MatcherRHS>>::type |     typename std::enable_if<Detail::is_matcher<MatcherRHS>::value, Detail::MatchAllOfGeneric<MatchersLHS..., MatcherRHS>>::type | ||||||
|         operator && (MatchAllOfGeneric<MatchersLHS...> && lhs, MatcherRHS const& rhs) { |         operator && (Detail::MatchAllOfGeneric<MatchersLHS...>&& lhs, MatcherRHS const& rhs) { | ||||||
|             return MatchAllOfGeneric<MatchersLHS..., MatcherRHS>{array_cat(std::move(lhs.m_matchers), static_cast<void const*>(&rhs))}; |         return Detail::MatchAllOfGeneric<MatchersLHS..., MatcherRHS>{Detail::array_cat(std::move(lhs.m_matchers), static_cast<void const*>(&rhs))}; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     template<typename MatcherLHS, typename... MatchersRHS> |     template<typename MatcherLHS, typename... MatchersRHS> | ||||||
|         typename std::enable_if<is_matcher<MatcherLHS>::value, MatchAllOfGeneric<MatcherLHS, MatchersRHS...>>::type |     typename std::enable_if<Detail::is_matcher<MatcherLHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatchersRHS...>>::type | ||||||
|         operator && (MatcherLHS const& lhs, MatchAllOfGeneric<MatchersRHS...> && rhs) { |         operator && (MatcherLHS const& lhs, Detail::MatchAllOfGeneric<MatchersRHS...>&& rhs) { | ||||||
|             return MatchAllOfGeneric<MatcherLHS, MatchersRHS...>{array_cat(static_cast<void const*>(std::addressof(lhs)), std::move(rhs.m_matchers))}; |         return Detail::MatchAllOfGeneric<MatcherLHS, MatchersRHS...>{Detail::array_cat(static_cast<void const*>(std::addressof(lhs)), std::move(rhs.m_matchers))}; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     template<typename... MatchersLHS, typename... MatchersRHS> |     template<typename... MatchersLHS, typename... MatchersRHS> | ||||||
|         MatchAnyOfGeneric<MatchersLHS..., MatchersRHS...> |     Detail::MatchAnyOfGeneric<MatchersLHS..., MatchersRHS...> | ||||||
|         operator || (MatchAnyOfGeneric<MatchersLHS...> && lhs, MatchAnyOfGeneric<MatchersRHS...> && rhs) { |         operator || (Detail::MatchAnyOfGeneric<MatchersLHS...>&& lhs, Detail::MatchAnyOfGeneric<MatchersRHS...>&& rhs) { | ||||||
|             return MatchAnyOfGeneric<MatchersLHS..., MatchersRHS...>{array_cat(std::move(lhs.m_matchers), std::move(rhs.m_matchers))}; |         return Detail::MatchAnyOfGeneric<MatchersLHS..., MatchersRHS...>{Detail::array_cat(std::move(lhs.m_matchers), std::move(rhs.m_matchers))}; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     template<typename... MatchersLHS, typename MatcherRHS> |     template<typename... MatchersLHS, typename MatcherRHS> | ||||||
|         typename std::enable_if<is_matcher<MatcherRHS>::value, MatchAnyOfGeneric<MatchersLHS..., MatcherRHS>>::type |     typename std::enable_if<Detail::is_matcher<MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatchersLHS..., MatcherRHS>>::type | ||||||
|         operator || (MatchAnyOfGeneric<MatchersLHS...> && lhs, MatcherRHS const& rhs) { |         operator || (Detail::MatchAnyOfGeneric<MatchersLHS...>&& lhs, MatcherRHS const& rhs) { | ||||||
|             return MatchAnyOfGeneric<MatchersLHS..., MatcherRHS>{array_cat(std::move(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))}; |         return Detail::MatchAnyOfGeneric<MatchersLHS..., MatcherRHS>{Detail::array_cat(std::move(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))}; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     template<typename MatcherLHS, typename... MatchersRHS> |     template<typename MatcherLHS, typename... MatchersRHS> | ||||||
|         typename std::enable_if<is_matcher<MatcherLHS>::value, MatchAnyOfGeneric<MatcherLHS, MatchersRHS...>>::type |     typename std::enable_if<Detail::is_matcher<MatcherLHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatchersRHS...>>::type | ||||||
|         operator || (MatcherLHS const& lhs, MatchAnyOfGeneric<MatchersRHS...> && rhs) { |         operator || (MatcherLHS const& lhs, Detail::MatchAnyOfGeneric<MatchersRHS...>&& rhs) { | ||||||
|             return MatchAnyOfGeneric<MatcherLHS, MatchersRHS...>{array_cat(static_cast<void const*>(std::addressof(lhs)), std::move(rhs.m_matchers))}; |         return Detail::MatchAnyOfGeneric<MatcherLHS, MatchersRHS...>{Detail::array_cat(static_cast<void const*>(std::addressof(lhs)), std::move(rhs.m_matchers))}; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     template<typename MatcherT> |     template<typename MatcherT> | ||||||
|         MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) { |     MatcherT const& operator ! (Detail::MatchNotOfGeneric<MatcherT> const& matcher) { | ||||||
|         return matcher.m_matcher; |         return matcher.m_matcher; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     } // namespace Impl |  | ||||||
|  |  | ||||||
| } // namespace Matchers | } // namespace Matchers | ||||||
|  |  | ||||||
| using namespace Matchers; |  | ||||||
| using Matchers::Impl::MatcherGenericBase; |  | ||||||
|  |  | ||||||
| } // namespace Catch | } // namespace Catch | ||||||
|  |  | ||||||
| #endif //TWOBLUECUBES_CATCH_MATCHERS_TEMPLATES_HPP_INCLUDED | #endif //TWOBLUECUBES_CATCH_MATCHERS_TEMPLATES_HPP_INCLUDED | ||||||
|   | |||||||
| @@ -99,7 +99,6 @@ Nor would this | |||||||
| :test-result: PASS Comparisons between ints where one side is computed | :test-result: PASS Comparisons between ints where one side is computed | ||||||
| :test-result: PASS Comparisons between unsigned ints and negative signed ints match c++ standard behaviour | :test-result: PASS Comparisons between unsigned ints and negative signed ints match c++ standard behaviour | ||||||
| :test-result: PASS Comparisons with int literals don't warn when mixing signed/ unsigned | :test-result: PASS Comparisons with int literals don't warn when mixing signed/ unsigned | ||||||
| :test-result: PASS Composed matchers are distinct |  | ||||||
| :test-result: FAIL Contains string matcher | :test-result: FAIL Contains string matcher | ||||||
| :test-result: PASS Copy and then generate a range | :test-result: PASS Copy and then generate a range | ||||||
| :test-result: FAIL Custom exceptions can be translated when testing for nothrow | :test-result: FAIL Custom exceptions can be translated when testing for nothrow | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ Compilation.tests.cpp:<line number>: passed: a == t for: 3 == 3 | |||||||
| Compilation.tests.cpp:<line number>: passed: throws_int(true) | Compilation.tests.cpp:<line number>: passed: throws_int(true) | ||||||
| Compilation.tests.cpp:<line number>: passed: throws_int(true), int | Compilation.tests.cpp:<line number>: passed: throws_int(true), int | ||||||
| Compilation.tests.cpp:<line number>: passed: throws_int(false) | Compilation.tests.cpp:<line number>: passed: throws_int(false) | ||||||
| Compilation.tests.cpp:<line number>: passed: "aaa", Catch::EndsWith("aaa") for: "aaa" ends with: "aaa" | Compilation.tests.cpp:<line number>: passed: "aaa", Catch::Matchers::EndsWith("aaa") for: "aaa" ends with: "aaa" | ||||||
| Compilation.tests.cpp:<line number>: passed: templated_tests<int>(3) for: true | Compilation.tests.cpp:<line number>: passed: templated_tests<int>(3) for: true | ||||||
| Misc.tests.cpp:<line number>: failed: f() == 0 for: 1 == 0 | Misc.tests.cpp:<line number>: failed: f() == 0 for: 1 == 0 | ||||||
| Misc.tests.cpp:<line number>: passed: errno == 1 for: 1 == 1 | Misc.tests.cpp:<line number>: passed: errno == 1 for: 1 == 1 | ||||||
| @@ -263,28 +263,28 @@ ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 2 == 2 | |||||||
| ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 3 == 3 | ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 3 == 3 | ||||||
| ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 4 == 4 | ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 4 == 4 | ||||||
| ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 5 == 5 | ToStringGeneral.tests.cpp:<line number>: passed: c == i for: 5 == 5 | ||||||
| Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC()), Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value' | Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC()), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value' | ||||||
| Matchers.tests.cpp:<line number>: passed: 1, MatcherA() && MatcherB() && MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 ) | Matchers.tests.cpp:<line number>: passed: 1, MatcherA() && MatcherB() && MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 ) | ||||||
| Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()), Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value' | Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value' | ||||||
| Matchers.tests.cpp:<line number>: passed: 1, MatcherA() && MatcherB() && MatcherC() && MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 and equals: true ) | Matchers.tests.cpp:<line number>: passed: 1, MatcherA() && MatcherB() && MatcherC() && MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 and equals: true ) | ||||||
| Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value' | Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value' | ||||||
| Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || MatcherB() || MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 ) | Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || MatcherB() || MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 ) | ||||||
| Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value' | Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value' | ||||||
| Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || MatcherB() || MatcherC() || MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 or equals: true ) | Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || MatcherB() || MatcherC() || MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 or equals: true ) | ||||||
| Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!MatcherA()), Catch::Matchers::Impl::MatchNotOfGeneric<MatcherA> >::value' | Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!MatcherA()), Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA> >::value' | ||||||
| Matchers.tests.cpp:<line number>: passed: 0, !MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f | Matchers.tests.cpp:<line number>: passed: 0, !MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f | ||||||
| Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!!MatcherA()), MatcherA const& >::value' | Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!!MatcherA()), MatcherA const& >::value' | ||||||
| Matchers.tests.cpp:<line number>: passed: 1, !!MatcherA() for: 1 equals: (int) 1 or (float) 1.0f | Matchers.tests.cpp:<line number>: passed: 1, !!MatcherA() for: 1 equals: (int) 1 or (float) 1.0f | ||||||
| Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!!!MatcherA()), Catch::Matchers::Impl::MatchNotOfGeneric<MatcherA> >::value' | Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!!!MatcherA()), Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA> >::value' | ||||||
| Matchers.tests.cpp:<line number>: passed: 0, !!!MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f | Matchers.tests.cpp:<line number>: passed: 0, !!!MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f | ||||||
| Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!!!!MatcherA()), MatcherA const & >::value' | Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(!!!!MatcherA()), MatcherA const & >::value' | ||||||
| Matchers.tests.cpp:<line number>: passed: 1, !!!!MatcherA() for: 1 equals: (int) 1 or (float) 1.0f | Matchers.tests.cpp:<line number>: passed: 1, !!!!MatcherA() for: 1 equals: (int) 1 or (float) 1.0f | ||||||
| Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith("bar") && !EndsWith("foo"))), Catch::Matchers::Impl::MatchAnyOf<std::string> >::value' | Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith("bar") && !EndsWith("foo"))), Catch::Matchers::Detail::MatchAnyOf<std::string> >::value' | ||||||
| Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB> >::value' | Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB> >::value' | ||||||
| Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 ) | Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 ) | ||||||
| Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB()), Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB> >::value' | Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB()), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB> >::value' | ||||||
| Matchers.tests.cpp:<line number>: passed: 1, MatcherA() && MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 ) | Matchers.tests.cpp:<line number>: passed: 1, MatcherA() && MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 ) | ||||||
| Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || !MatcherB()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, Catch::Matchers::Impl::MatchNotOfGeneric<MatcherB>> >::value' | Matchers.tests.cpp:<line number>: passed: with 1 message: 'std::is_same< decltype(MatcherA() || !MatcherB()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, Catch::Matchers::Detail::MatchNotOfGeneric<MatcherB>> >::value' | ||||||
| Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || !MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f or not equals: (long long) 1 ) | Matchers.tests.cpp:<line number>: passed: 1, MatcherA() || !MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f or not equals: (long long) 1 ) | ||||||
| Matchers.tests.cpp:<line number>: passed: vec, Predicate<std::vector<int>>([](auto const& vec) { return std::all_of(vec.begin(), vec.end(), [](int elem) { return elem % 2 == 1; }); }, "All elements are odd") && !EqualsRange(a) for: { 1, 3, 5 } ( matches predicate: "All elements are odd" and not Equals: { 5, 3, 1 } ) | Matchers.tests.cpp:<line number>: passed: vec, Predicate<std::vector<int>>([](auto const& vec) { return std::all_of(vec.begin(), vec.end(), [](int elem) { return elem % 2 == 1; }); }, "All elements are odd") && !EqualsRange(a) for: { 1, 3, 5 } ( matches predicate: "All elements are odd" and not Equals: { 5, 3, 1 } ) | ||||||
| Matchers.tests.cpp:<line number>: passed: str, StartsWith("foo") && EqualsRange(arr) && EndsWith("bar") for: "foobar" ( starts with: "foo" and Equals: { 'f', 'o', 'o', 'b', 'a', 'r' } and ends with: "bar" ) | Matchers.tests.cpp:<line number>: passed: str, StartsWith("foo") && EqualsRange(arr) && EndsWith("bar") for: "foobar" ( starts with: "foo" and Equals: { 'f', 'o', 'o', 'b', 'a', 'r' } and ends with: "bar" ) | ||||||
| @@ -344,8 +344,6 @@ Condition.tests.cpp:<line number>: passed: 4 == ul for: 4 == 4 | |||||||
| Condition.tests.cpp:<line number>: passed: 5 == c for: 5 == 5 | Condition.tests.cpp:<line number>: passed: 5 == c for: 5 == 5 | ||||||
| Condition.tests.cpp:<line number>: passed: 6 == uc for: 6 == 6 | Condition.tests.cpp:<line number>: passed: 6 == uc for: 6 == 6 | ||||||
| Condition.tests.cpp:<line number>: passed: (std::numeric_limits<uint32_t>::max)() > ul for: 4294967295 (0x<hex digits>) > 4 | Condition.tests.cpp:<line number>: passed: (std::numeric_limits<uint32_t>::max)() > ul for: 4294967295 (0x<hex digits>) > 4 | ||||||
| Matchers.tests.cpp:<line number>: passed: testStringForMatching2(), !composed1 for: "some completely different text that contains one common word" not ( contains: "string" or contains: "random" ) |  | ||||||
| Matchers.tests.cpp:<line number>: passed: testStringForMatching2(), composed2 for: "some completely different text that contains one common word" ( contains: "string" or contains: "random" or contains: "different" ) |  | ||||||
| Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" contains: "not there" (case insensitive) | Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" contains: "not there" (case insensitive) | ||||||
| Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("STRING") for: "this string contains 'abc' as a substring" contains: "STRING" | Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Contains("STRING") for: "this string contains 'abc' as a substring" contains: "STRING" | ||||||
| Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1 | Generators.tests.cpp:<line number>: passed: elem % 2 == 1 for: 1 == 1 | ||||||
| @@ -1841,7 +1839,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: Timing.result == Timing.itera | |||||||
| InternalBenchmark.tests.cpp:<line number>: passed: Timing.iterations >= time.count() for: 128 >= 100 | InternalBenchmark.tests.cpp:<line number>: passed: Timing.iterations >= time.count() for: 128 >= 100 | ||||||
| Misc.tests.cpp:<line number>: failed: false with 1 message: '3' | Misc.tests.cpp:<line number>: failed: false with 1 message: '3' | ||||||
| Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7' | Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7' | ||||||
| Tag.tests.cpp:<line number>: passed: tags, Catch::VectorContains("magic-tag"_catch_sr) && Catch::VectorContains("."_catch_sr) for: { ., magic-tag } ( Contains: magic-tag and Contains: . ) | Tag.tests.cpp:<line number>: passed: tags, VectorContains("magic-tag"_catch_sr) && VectorContains("."_catch_sr) for: { ., magic-tag } ( Contains: magic-tag and Contains: . ) | ||||||
| StringManip.tests.cpp:<line number>: passed: splitStringRef("", ','), Equals(std::vector<StringRef>()) for: {  } Equals: {  } | StringManip.tests.cpp:<line number>: passed: splitStringRef("", ','), Equals(std::vector<StringRef>()) for: {  } Equals: {  } | ||||||
| StringManip.tests.cpp:<line number>: passed: splitStringRef("abc", ','), Equals(std::vector<StringRef>{"abc"}) for: { abc } Equals: { abc } | StringManip.tests.cpp:<line number>: passed: splitStringRef("abc", ','), Equals(std::vector<StringRef>{"abc"}) for: { abc } Equals: { abc } | ||||||
| StringManip.tests.cpp:<line number>: passed: splitStringRef("abc,def", ','), Equals(std::vector<StringRef>{"abc", "def"}) for: { abc, def } Equals: { abc, def } | StringManip.tests.cpp:<line number>: passed: splitStringRef("abc,def", ','), Equals(std::vector<StringRef>{"abc", "def"}) for: { abc, def } Equals: { abc, def } | ||||||
|   | |||||||
| @@ -1380,6 +1380,6 @@ due to unexpected exception with message: | |||||||
|   Why would you throw a std::string? |   Why would you throw a std::string? | ||||||
|  |  | ||||||
| =============================================================================== | =============================================================================== | ||||||
| test cases:  329 |  255 passed |  70 failed |  4 failed as expected | test cases:  328 |  254 passed |  70 failed |  4 failed as expected | ||||||
| assertions: 1841 | 1689 passed | 131 failed | 21 failed as expected | assertions: 1839 | 1687 passed | 131 failed | 21 failed as expected | ||||||
|  |  | ||||||
|   | |||||||
| @@ -271,7 +271,7 @@ Compilation.tests.cpp:<line number>: PASSED: | |||||||
|   REQUIRE_NOTHROW( throws_int(false) ) |   REQUIRE_NOTHROW( throws_int(false) ) | ||||||
|  |  | ||||||
| Compilation.tests.cpp:<line number>: PASSED: | Compilation.tests.cpp:<line number>: PASSED: | ||||||
|   REQUIRE_THAT( "aaa", Catch::EndsWith("aaa") ) |   REQUIRE_THAT( "aaa", Catch::Matchers::EndsWith("aaa") ) | ||||||
| with expansion: | with expansion: | ||||||
|   "aaa" ends with: "aaa" |   "aaa" ends with: "aaa" | ||||||
|  |  | ||||||
| @@ -2125,7 +2125,7 @@ Matchers.tests.cpp:<line number> | |||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| with message: | with message: | ||||||
|   std::is_same< decltype(MatcherA() && MatcherB() && MatcherC()), Catch:: |   std::is_same< decltype(MatcherA() && MatcherB() && MatcherC()), Catch:: | ||||||
|   Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value |   Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value | ||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
|   REQUIRE_THAT( 1, MatcherA() && MatcherB() && MatcherC() ) |   REQUIRE_THAT( 1, MatcherA() && MatcherB() && MatcherC() ) | ||||||
| @@ -2136,7 +2136,7 @@ with expansion: | |||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| with message: | with message: | ||||||
|   std::is_same< decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()), |   std::is_same< decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()), | ||||||
|   Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, |   Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, | ||||||
|   MatcherD> >::value |   MatcherD> >::value | ||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| @@ -2154,7 +2154,7 @@ Matchers.tests.cpp:<line number> | |||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| with message: | with message: | ||||||
|   std::is_same< decltype(MatcherA() || MatcherB() || MatcherC()), Catch:: |   std::is_same< decltype(MatcherA() || MatcherB() || MatcherC()), Catch:: | ||||||
|   Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value |   Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value | ||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
|   REQUIRE_THAT( 1, MatcherA() || MatcherB() || MatcherC() ) |   REQUIRE_THAT( 1, MatcherA() || MatcherB() || MatcherC() ) | ||||||
| @@ -2165,7 +2165,7 @@ with expansion: | |||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| with message: | with message: | ||||||
|   std::is_same< decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()), |   std::is_same< decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()), | ||||||
|   Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, |   Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, | ||||||
|   MatcherD> >::value |   MatcherD> >::value | ||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| @@ -2182,8 +2182,8 @@ Matchers.tests.cpp:<line number> | |||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| with message: | with message: | ||||||
|   std::is_same< decltype(!MatcherA()), Catch::Matchers::Impl::MatchNotOfGeneric |   std::is_same< decltype(!MatcherA()), Catch::Matchers::Detail:: | ||||||
|   <MatcherA> >::value |   MatchNotOfGeneric<MatcherA> >::value | ||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
|   REQUIRE_THAT( 0, !MatcherA() ) |   REQUIRE_THAT( 0, !MatcherA() ) | ||||||
| @@ -2201,7 +2201,7 @@ with expansion: | |||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| with message: | with message: | ||||||
|   std::is_same< decltype(!!!MatcherA()), Catch::Matchers::Impl:: |   std::is_same< decltype(!!!MatcherA()), Catch::Matchers::Detail:: | ||||||
|   MatchNotOfGeneric<MatcherA> >::value |   MatchNotOfGeneric<MatcherA> >::value | ||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| @@ -2227,8 +2227,8 @@ Matchers.tests.cpp:<line number> | |||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| with message: | with message: | ||||||
|   std::is_same< decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith |   std::is_same< decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith | ||||||
|   ("bar") && !EndsWith("foo"))), Catch::Matchers::Impl::MatchAnyOf<std::string> |   ("bar") && !EndsWith("foo"))), Catch::Matchers::Detail::MatchAnyOf<std:: | ||||||
|   >::value |   string> >::value | ||||||
|  |  | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| Combining only templated matchers | Combining only templated matchers | ||||||
| @@ -2238,7 +2238,7 @@ Matchers.tests.cpp:<line number> | |||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| with message: | with message: | ||||||
|   std::is_same< decltype(MatcherA() || MatcherB()), Catch::Matchers::Impl:: |   std::is_same< decltype(MatcherA() || MatcherB()), Catch::Matchers::Detail:: | ||||||
|   MatchAnyOfGeneric<MatcherA, MatcherB> >::value |   MatchAnyOfGeneric<MatcherA, MatcherB> >::value | ||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| @@ -2248,7 +2248,7 @@ with expansion: | |||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| with message: | with message: | ||||||
|   std::is_same< decltype(MatcherA() && MatcherB()), Catch::Matchers::Impl:: |   std::is_same< decltype(MatcherA() && MatcherB()), Catch::Matchers::Detail:: | ||||||
|   MatchAllOfGeneric<MatcherA, MatcherB> >::value |   MatchAllOfGeneric<MatcherA, MatcherB> >::value | ||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| @@ -2258,8 +2258,8 @@ with expansion: | |||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| with message: | with message: | ||||||
|   std::is_same< decltype(MatcherA() || !MatcherB()), Catch::Matchers::Impl:: |   std::is_same< decltype(MatcherA() || !MatcherB()), Catch::Matchers::Detail:: | ||||||
|   MatchAnyOfGeneric<MatcherA, Catch::Matchers::Impl::MatchNotOfGeneric |   MatchAnyOfGeneric<MatcherA, Catch::Matchers::Detail::MatchNotOfGeneric | ||||||
|   <MatcherB>> >::value |   <MatcherB>> >::value | ||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: | Matchers.tests.cpp:<line number>: PASSED: | ||||||
| @@ -2610,24 +2610,6 @@ Condition.tests.cpp:<line number>: PASSED: | |||||||
| with expansion: | with expansion: | ||||||
|   4294967295 (0x<hex digits>) > 4 |   4294967295 (0x<hex digits>) > 4 | ||||||
|  |  | ||||||
| ------------------------------------------------------------------------------- |  | ||||||
| Composed matchers are distinct |  | ||||||
| ------------------------------------------------------------------------------- |  | ||||||
| Matchers.tests.cpp:<line number> |  | ||||||
| ............................................................................... |  | ||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: |  | ||||||
|   REQUIRE_THAT( testStringForMatching2(), !composed1 ) |  | ||||||
| with expansion: |  | ||||||
|   "some completely different text that contains one common word" not ( |  | ||||||
|   contains: "string" or contains: "random" ) |  | ||||||
|  |  | ||||||
| Matchers.tests.cpp:<line number>: PASSED: |  | ||||||
|   REQUIRE_THAT( testStringForMatching2(), composed2 ) |  | ||||||
| with expansion: |  | ||||||
|   "some completely different text that contains one common word" ( contains: |  | ||||||
|   "string" or contains: "random" or contains: "different" ) |  | ||||||
|  |  | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| Contains string matcher | Contains string matcher | ||||||
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ||||||
| @@ -13485,7 +13467,7 @@ Tag.tests.cpp:<line number> | |||||||
| ............................................................................... | ............................................................................... | ||||||
|  |  | ||||||
| Tag.tests.cpp:<line number>: PASSED: | Tag.tests.cpp:<line number>: PASSED: | ||||||
|   REQUIRE_THAT( tags, Catch::VectorContains("magic-tag"_catch_sr) && Catch::VectorContains("."_catch_sr) ) |   REQUIRE_THAT( tags, VectorContains("magic-tag"_catch_sr) && VectorContains("."_catch_sr) ) | ||||||
| with expansion: | with expansion: | ||||||
|   { ., magic-tag } ( Contains: magic-tag and Contains: . ) |   { ., magic-tag } ( Contains: magic-tag and Contains: . ) | ||||||
|  |  | ||||||
| @@ -14414,6 +14396,6 @@ Misc.tests.cpp:<line number> | |||||||
| Misc.tests.cpp:<line number>: PASSED: | Misc.tests.cpp:<line number>: PASSED: | ||||||
|  |  | ||||||
| =============================================================================== | =============================================================================== | ||||||
| test cases:  329 |  239 passed |  86 failed |  4 failed as expected | test cases:  328 |  238 passed |  86 failed |  4 failed as expected | ||||||
| assertions: 1858 | 1689 passed | 148 failed | 21 failed as expected | assertions: 1856 | 1687 passed | 148 failed | 21 failed as expected | ||||||
|  |  | ||||||
|   | |||||||
| @@ -271,7 +271,7 @@ Compilation.tests.cpp:<line number>: PASSED: | |||||||
|   REQUIRE_NOTHROW( throws_int(false) ) |   REQUIRE_NOTHROW( throws_int(false) ) | ||||||
|  |  | ||||||
| Compilation.tests.cpp:<line number>: PASSED: | Compilation.tests.cpp:<line number>: PASSED: | ||||||
|   REQUIRE_THAT( "aaa", Catch::EndsWith("aaa") ) |   REQUIRE_THAT( "aaa", Catch::Matchers::EndsWith("aaa") ) | ||||||
| with expansion: | with expansion: | ||||||
|   "aaa" ends with: "aaa" |   "aaa" ends with: "aaa" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| <?xml version="1.0" encoding="UTF-8"?> | <?xml version="1.0" encoding="UTF-8"?> | ||||||
| <testsuitesloose text artifact | <testsuitesloose text artifact | ||||||
| > | > | ||||||
|   <testsuite name="<exe-name>" errors="17" failures="132" tests="1859" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> |   <testsuite name="<exe-name>" errors="17" failures="132" tests="1857" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}"> | ||||||
|     <properties> |     <properties> | ||||||
|       <property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/> |       <property name="filters" value="~[!nonportable]~[!benchmark]~[approvals] *"/> | ||||||
|       <property name="random-seed" value="1"/> |       <property name="random-seed" value="1"/> | ||||||
| @@ -364,7 +364,6 @@ Exception.tests.cpp:<line number> | |||||||
|     <testcase classname="<exe-name>.global" name="Comparisons between ints where one side is computed" time="{duration}"/> |     <testcase classname="<exe-name>.global" name="Comparisons between ints where one side is computed" time="{duration}"/> | ||||||
|     <testcase classname="<exe-name>.global" name="Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" time="{duration}"/> |     <testcase classname="<exe-name>.global" name="Comparisons between unsigned ints and negative signed ints match c++ standard behaviour" time="{duration}"/> | ||||||
|     <testcase classname="<exe-name>.global" name="Comparisons with int literals don't warn when mixing signed/ unsigned" time="{duration}"/> |     <testcase classname="<exe-name>.global" name="Comparisons with int literals don't warn when mixing signed/ unsigned" time="{duration}"/> | ||||||
|     <testcase classname="<exe-name>.global" name="Composed matchers are distinct" time="{duration}"/> |  | ||||||
|     <testcase classname="<exe-name>.global" name="Contains string matcher" time="{duration}"> |     <testcase classname="<exe-name>.global" name="Contains string matcher" time="{duration}"> | ||||||
|       <failure message="testStringForMatching(), Contains("not there", Catch::CaseSensitive::No)" type="CHECK_THAT"> |       <failure message="testStringForMatching(), Contains("not there", Catch::CaseSensitive::No)" type="CHECK_THAT"> | ||||||
| FAILED: | FAILED: | ||||||
|   | |||||||
| @@ -925,7 +925,6 @@ Exception.tests.cpp:<line number> | |||||||
|     <testCase name="Combining only templated matchers" duration="{duration}"/> |     <testCase name="Combining only templated matchers" duration="{duration}"/> | ||||||
|     <testCase name="Combining templated and concrete matchers" duration="{duration}"/> |     <testCase name="Combining templated and concrete matchers" duration="{duration}"/> | ||||||
|     <testCase name="Combining templated matchers" duration="{duration}"/> |     <testCase name="Combining templated matchers" duration="{duration}"/> | ||||||
|     <testCase name="Composed matchers are distinct" duration="{duration}"/> |  | ||||||
|     <testCase name="Contains string matcher" duration="{duration}"> |     <testCase name="Contains string matcher" duration="{duration}"> | ||||||
|       <failure message="CHECK_THAT(testStringForMatching(), Contains("not there", Catch::CaseSensitive::No))"> |       <failure message="CHECK_THAT(testStringForMatching(), Contains("not there", Catch::CaseSensitive::No))"> | ||||||
| FAILED: | FAILED: | ||||||
|   | |||||||
| @@ -65,7 +65,7 @@ ok {test-number} - throws_int(true), int | |||||||
| # #833 | # #833 | ||||||
| ok {test-number} - throws_int(false) | ok {test-number} - throws_int(false) | ||||||
| # #833 | # #833 | ||||||
| ok {test-number} - "aaa", Catch::EndsWith("aaa") for: "aaa" ends with: "aaa" | ok {test-number} - "aaa", Catch::Matchers::EndsWith("aaa") for: "aaa" ends with: "aaa" | ||||||
| # #833 | # #833 | ||||||
| ok {test-number} - templated_tests<int>(3) for: true | ok {test-number} - templated_tests<int>(3) for: true | ||||||
| # #835 -- errno should not be touched by Catch | # #835 -- errno should not be touched by Catch | ||||||
| @@ -525,23 +525,23 @@ ok {test-number} - c == i for: 4 == 4 | |||||||
| # Character pretty printing | # Character pretty printing | ||||||
| ok {test-number} - c == i for: 5 == 5 | ok {test-number} - c == i for: 5 == 5 | ||||||
| # Combining MatchAllOfGeneric does not nest | # Combining MatchAllOfGeneric does not nest | ||||||
| ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC()), Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value' | ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC()), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> >::value' | ||||||
| # Combining MatchAllOfGeneric does not nest | # Combining MatchAllOfGeneric does not nest | ||||||
| ok {test-number} - 1, MatcherA() && MatcherB() && MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 ) | ok {test-number} - 1, MatcherA() && MatcherB() && MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 ) | ||||||
| # Combining MatchAllOfGeneric does not nest | # Combining MatchAllOfGeneric does not nest | ||||||
| ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()), Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value' | ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value' | ||||||
| # Combining MatchAllOfGeneric does not nest | # Combining MatchAllOfGeneric does not nest | ||||||
| ok {test-number} - 1, MatcherA() && MatcherB() && MatcherC() && MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 and equals: true ) | ok {test-number} - 1, MatcherA() && MatcherB() && MatcherC() && MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 and equals: (T) 1 and equals: true ) | ||||||
| # Combining MatchAnyOfGeneric does not nest | # Combining MatchAnyOfGeneric does not nest | ||||||
| ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value' | ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> >::value' | ||||||
| # Combining MatchAnyOfGeneric does not nest | # Combining MatchAnyOfGeneric does not nest | ||||||
| ok {test-number} - 1, MatcherA() || MatcherB() || MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 ) | ok {test-number} - 1, MatcherA() || MatcherB() || MatcherC() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 ) | ||||||
| # Combining MatchAnyOfGeneric does not nest | # Combining MatchAnyOfGeneric does not nest | ||||||
| ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value' | ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> >::value' | ||||||
| # Combining MatchAnyOfGeneric does not nest | # Combining MatchAnyOfGeneric does not nest | ||||||
| ok {test-number} - 1, MatcherA() || MatcherB() || MatcherC() || MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 or equals: true ) | ok {test-number} - 1, MatcherA() || MatcherB() || MatcherC() || MatcherD() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 or equals: (T) 1 or equals: true ) | ||||||
| # Combining MatchNotOfGeneric does not nest | # Combining MatchNotOfGeneric does not nest | ||||||
| ok {test-number} - with 1 message: 'std::is_same< decltype(!MatcherA()), Catch::Matchers::Impl::MatchNotOfGeneric<MatcherA> >::value' | ok {test-number} - with 1 message: 'std::is_same< decltype(!MatcherA()), Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA> >::value' | ||||||
| # Combining MatchNotOfGeneric does not nest | # Combining MatchNotOfGeneric does not nest | ||||||
| ok {test-number} - 0, !MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f | ok {test-number} - 0, !MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f | ||||||
| # Combining MatchNotOfGeneric does not nest | # Combining MatchNotOfGeneric does not nest | ||||||
| @@ -549,7 +549,7 @@ ok {test-number} - with 1 message: 'std::is_same< decltype(!!MatcherA()), Matche | |||||||
| # Combining MatchNotOfGeneric does not nest | # Combining MatchNotOfGeneric does not nest | ||||||
| ok {test-number} - 1, !!MatcherA() for: 1 equals: (int) 1 or (float) 1.0f | ok {test-number} - 1, !!MatcherA() for: 1 equals: (int) 1 or (float) 1.0f | ||||||
| # Combining MatchNotOfGeneric does not nest | # Combining MatchNotOfGeneric does not nest | ||||||
| ok {test-number} - with 1 message: 'std::is_same< decltype(!!!MatcherA()), Catch::Matchers::Impl::MatchNotOfGeneric<MatcherA> >::value' | ok {test-number} - with 1 message: 'std::is_same< decltype(!!!MatcherA()), Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA> >::value' | ||||||
| # Combining MatchNotOfGeneric does not nest | # Combining MatchNotOfGeneric does not nest | ||||||
| ok {test-number} - 0, !!!MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f | ok {test-number} - 0, !!!MatcherA() for: 0 not equals: (int) 1 or (float) 1.0f | ||||||
| # Combining MatchNotOfGeneric does not nest | # Combining MatchNotOfGeneric does not nest | ||||||
| @@ -557,17 +557,17 @@ ok {test-number} - with 1 message: 'std::is_same< decltype(!!!!MatcherA()), Matc | |||||||
| # Combining MatchNotOfGeneric does not nest | # Combining MatchNotOfGeneric does not nest | ||||||
| ok {test-number} - 1, !!!!MatcherA() for: 1 equals: (int) 1 or (float) 1.0f | ok {test-number} - 1, !!!!MatcherA() for: 1 equals: (int) 1 or (float) 1.0f | ||||||
| # Combining concrete matchers does not use templated matchers | # Combining concrete matchers does not use templated matchers | ||||||
| ok {test-number} - with 1 message: 'std::is_same< decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith("bar") && !EndsWith("foo"))), Catch::Matchers::Impl::MatchAnyOf<std::string> >::value' | ok {test-number} - with 1 message: 'std::is_same< decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith("bar") && !EndsWith("foo"))), Catch::Matchers::Detail::MatchAnyOf<std::string> >::value' | ||||||
| # Combining only templated matchers | # Combining only templated matchers | ||||||
| ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB> >::value' | ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || MatcherB()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB> >::value' | ||||||
| # Combining only templated matchers | # Combining only templated matchers | ||||||
| ok {test-number} - 1, MatcherA() || MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 ) | ok {test-number} - 1, MatcherA() || MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f or equals: (long long) 1 ) | ||||||
| # Combining only templated matchers | # Combining only templated matchers | ||||||
| ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB()), Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB> >::value' | ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() && MatcherB()), Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB> >::value' | ||||||
| # Combining only templated matchers | # Combining only templated matchers | ||||||
| ok {test-number} - 1, MatcherA() && MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 ) | ok {test-number} - 1, MatcherA() && MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f and equals: (long long) 1 ) | ||||||
| # Combining only templated matchers | # Combining only templated matchers | ||||||
| ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || !MatcherB()), Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, Catch::Matchers::Impl::MatchNotOfGeneric<MatcherB>> >::value' | ok {test-number} - with 1 message: 'std::is_same< decltype(MatcherA() || !MatcherB()), Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, Catch::Matchers::Detail::MatchNotOfGeneric<MatcherB>> >::value' | ||||||
| # Combining only templated matchers | # Combining only templated matchers | ||||||
| ok {test-number} - 1, MatcherA() || !MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f or not equals: (long long) 1 ) | ok {test-number} - 1, MatcherA() || !MatcherB() for: 1 ( equals: (int) 1 or (float) 1.0f or not equals: (long long) 1 ) | ||||||
| # Combining templated and concrete matchers | # Combining templated and concrete matchers | ||||||
| @@ -686,10 +686,6 @@ ok {test-number} - 5 == c for: 5 == 5 | |||||||
| ok {test-number} - 6 == uc for: 6 == 6 | ok {test-number} - 6 == uc for: 6 == 6 | ||||||
| # Comparisons with int literals don't warn when mixing signed/ unsigned | # Comparisons with int literals don't warn when mixing signed/ unsigned | ||||||
| ok {test-number} - (std::numeric_limits<uint32_t>::max)() > ul for: 4294967295 (0x<hex digits>) > 4 | ok {test-number} - (std::numeric_limits<uint32_t>::max)() > ul for: 4294967295 (0x<hex digits>) > 4 | ||||||
| # Composed matchers are distinct |  | ||||||
| ok {test-number} - testStringForMatching2(), !composed1 for: "some completely different text that contains one common word" not ( contains: "string" or contains: "random" ) |  | ||||||
| # Composed matchers are distinct |  | ||||||
| ok {test-number} - testStringForMatching2(), composed2 for: "some completely different text that contains one common word" ( contains: "string" or contains: "random" or contains: "different" ) |  | ||||||
| # Contains string matcher | # Contains string matcher | ||||||
| not ok {test-number} - testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" contains: "not there" (case insensitive) | not ok {test-number} - testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" contains: "not there" (case insensitive) | ||||||
| # Contains string matcher | # Contains string matcher | ||||||
| @@ -3509,7 +3505,7 @@ not ok {test-number} - false with 1 message: '3' | |||||||
| # sends information to INFO | # sends information to INFO | ||||||
| not ok {test-number} - false with 2 messages: 'hi' and 'i := 7' | not ok {test-number} - false with 2 messages: 'hi' and 'i := 7' | ||||||
| # shortened hide tags are split apart | # shortened hide tags are split apart | ||||||
| ok {test-number} - tags, Catch::VectorContains("magic-tag"_catch_sr) && Catch::VectorContains("."_catch_sr) for: { ., magic-tag } ( Contains: magic-tag and Contains: . ) | ok {test-number} - tags, VectorContains("magic-tag"_catch_sr) && VectorContains("."_catch_sr) for: { ., magic-tag } ( Contains: magic-tag and Contains: . ) | ||||||
| # splitString | # splitString | ||||||
| ok {test-number} - splitStringRef("", ','), Equals(std::vector<StringRef>()) for: {  } Equals: {  } | ok {test-number} - splitStringRef("", ','), Equals(std::vector<StringRef>()) for: {  } Equals: {  } | ||||||
| # splitString | # splitString | ||||||
| @@ -3708,5 +3704,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 | |||||||
| ok {test-number} - | ok {test-number} - | ||||||
| # xmlentitycheck | # xmlentitycheck | ||||||
| ok {test-number} - | ok {test-number} - | ||||||
| 1..1850 | 1..1848 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -231,8 +231,6 @@ Exception.tests.cpp:<line number>|nunexpected exception with message:|n  "unexpe | |||||||
| ##teamcity[testFinished name='Comparisons between unsigned ints and negative signed ints match c++ standard behaviour' duration="{duration}"] | ##teamcity[testFinished name='Comparisons between unsigned ints and negative signed ints match c++ standard behaviour' duration="{duration}"] | ||||||
| ##teamcity[testStarted name='Comparisons with int literals don|'t warn when mixing signed/ unsigned'] | ##teamcity[testStarted name='Comparisons with int literals don|'t warn when mixing signed/ unsigned'] | ||||||
| ##teamcity[testFinished name='Comparisons with int literals don|'t warn when mixing signed/ unsigned' duration="{duration}"] | ##teamcity[testFinished name='Comparisons with int literals don|'t warn when mixing signed/ unsigned' duration="{duration}"] | ||||||
| ##teamcity[testStarted name='Composed matchers are distinct'] |  | ||||||
| ##teamcity[testFinished name='Composed matchers are distinct' duration="{duration}"] |  | ||||||
| ##teamcity[testStarted name='Contains string matcher'] | ##teamcity[testStarted name='Contains string matcher'] | ||||||
| Matchers.tests.cpp:<line number>|nexpression failed|n  CHECK_THAT( testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) )|nwith expansion:|n  "this string contains |'abc|' as a substring" contains: "not there" (case insensitive)|n'] | Matchers.tests.cpp:<line number>|nexpression failed|n  CHECK_THAT( testStringForMatching(), Contains("not there", Catch::CaseSensitive::No) )|nwith expansion:|n  "this string contains |'abc|' as a substring" contains: "not there" (case insensitive)|n'] | ||||||
| Matchers.tests.cpp:<line number>|nexpression failed|n  CHECK_THAT( testStringForMatching(), Contains("STRING") )|nwith expansion:|n  "this string contains |'abc|' as a substring" contains: "STRING"|n'] | Matchers.tests.cpp:<line number>|nexpression failed|n  CHECK_THAT( testStringForMatching(), Contains("STRING") )|nwith expansion:|n  "this string contains |'abc|' as a substring" contains: "STRING"|n'] | ||||||
|   | |||||||
| @@ -299,7 +299,7 @@ Nor would this | |||||||
|       </Expression> |       </Expression> | ||||||
|       <Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Compilation.tests.cpp" > |       <Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Compilation.tests.cpp" > | ||||||
|         <Original> |         <Original> | ||||||
|           "aaa", Catch::EndsWith("aaa") |           "aaa", Catch::Matchers::EndsWith("aaa") | ||||||
|         </Original> |         </Original> | ||||||
|         <Expanded> |         <Expanded> | ||||||
|           "aaa" ends with: "aaa" |           "aaa" ends with: "aaa" | ||||||
| @@ -3011,25 +3011,6 @@ Nor would this | |||||||
|       </Expression> |       </Expression> | ||||||
|       <OverallResult success="true"/> |       <OverallResult success="true"/> | ||||||
|     </TestCase> |     </TestCase> | ||||||
|     <TestCase name="Composed matchers are distinct" tags="[composed][matchers]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" > |  | ||||||
|       <Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" > |  | ||||||
|         <Original> |  | ||||||
|           testStringForMatching2(), !composed1 |  | ||||||
|         </Original> |  | ||||||
|         <Expanded> |  | ||||||
|           "some completely different text that contains one common word" not ( contains: "string" or contains: "random" ) |  | ||||||
|         </Expanded> |  | ||||||
|       </Expression> |  | ||||||
|       <Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" > |  | ||||||
|         <Original> |  | ||||||
|           testStringForMatching2(), composed2 |  | ||||||
|         </Original> |  | ||||||
|         <Expanded> |  | ||||||
|           "some completely different text that contains one common word" ( contains: "string" or contains: "random" or contains: "different" ) |  | ||||||
|         </Expanded> |  | ||||||
|       </Expression> |  | ||||||
|       <OverallResult success="true"/> |  | ||||||
|     </TestCase> |  | ||||||
|     <TestCase name="Contains string matcher" tags="[.][failing][matchers]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" > |     <TestCase name="Contains string matcher" tags="[.][failing][matchers]" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" > | ||||||
|       <Expression success="false" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" > |       <Expression success="false" type="CHECK_THAT" filename="tests/<exe-name>/UsageTests/Matchers.tests.cpp" > | ||||||
|         <Original> |         <Original> | ||||||
| @@ -16273,7 +16254,7 @@ loose text artifact | |||||||
|     <TestCase name="shortened hide tags are split apart" filename="tests/<exe-name>/IntrospectiveTests/Tag.tests.cpp" > |     <TestCase name="shortened hide tags are split apart" filename="tests/<exe-name>/IntrospectiveTests/Tag.tests.cpp" > | ||||||
|       <Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/IntrospectiveTests/Tag.tests.cpp" > |       <Expression success="true" type="REQUIRE_THAT" filename="tests/<exe-name>/IntrospectiveTests/Tag.tests.cpp" > | ||||||
|         <Original> |         <Original> | ||||||
|           tags, Catch::VectorContains("magic-tag"_catch_sr) && Catch::VectorContains("."_catch_sr) |           tags, VectorContains("magic-tag"_catch_sr) && VectorContains("."_catch_sr) | ||||||
|         </Original> |         </Original> | ||||||
|         <Expanded> |         <Expanded> | ||||||
|           { ., magic-tag } ( Contains: magic-tag and Contains: . ) |           { ., magic-tag } ( Contains: magic-tag and Contains: . ) | ||||||
| @@ -17283,7 +17264,7 @@ loose text artifact | |||||||
|       </Section> |       </Section> | ||||||
|       <OverallResult success="true"/> |       <OverallResult success="true"/> | ||||||
|     </TestCase> |     </TestCase> | ||||||
|     <OverallResults successes="1689" failures="149" expectedFailures="21"/> |     <OverallResults successes="1687" failures="149" expectedFailures="21"/> | ||||||
|   </Group> |   </Group> | ||||||
|   <OverallResults successes="1689" failures="148" expectedFailures="21"/> |   <OverallResults successes="1687" failures="148" expectedFailures="21"/> | ||||||
| </Catch> | </Catch> | ||||||
|   | |||||||
| @@ -41,11 +41,12 @@ TEST_CASE( "Tag alias can be registered against tag patterns" ) { | |||||||
|  |  | ||||||
| TEST_CASE("shortened hide tags are split apart") { | TEST_CASE("shortened hide tags are split apart") { | ||||||
|     using Catch::StringRef; |     using Catch::StringRef; | ||||||
|  |     using Catch::Matchers::VectorContains; | ||||||
|     auto testcase = Catch::makeTestCaseInfo("", {"fake test name", "[.magic-tag]"}, CATCH_INTERNAL_LINEINFO); |     auto testcase = Catch::makeTestCaseInfo("", {"fake test name", "[.magic-tag]"}, CATCH_INTERNAL_LINEINFO); | ||||||
|     // Transform ... |     // Transform ... | ||||||
|     std::vector<StringRef> tags; |     std::vector<StringRef> tags; | ||||||
|     for (auto const& tag : testcase->tags) { |     for (auto const& tag : testcase->tags) { | ||||||
|         tags.push_back(tag.original); |         tags.push_back(tag.original); | ||||||
|     } |     } | ||||||
|     REQUIRE_THAT(tags, Catch::VectorContains("magic-tag"_catch_sr) && Catch::VectorContains("."_catch_sr)); |     REQUIRE_THAT(tags, VectorContains("magic-tag"_catch_sr) && VectorContains("."_catch_sr)); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -79,7 +79,7 @@ namespace { namespace CompilationTests { | |||||||
|         REQUIRE_THROWS(throws_int(true)); |         REQUIRE_THROWS(throws_int(true)); | ||||||
|         CHECK_THROWS_AS(throws_int(true), int); |         CHECK_THROWS_AS(throws_int(true), int); | ||||||
|         REQUIRE_NOTHROW(throws_int(false)); |         REQUIRE_NOTHROW(throws_int(false)); | ||||||
|         REQUIRE_THAT("aaa", Catch::EndsWith("aaa")); |         REQUIRE_THAT("aaa", Catch::Matchers::EndsWith("aaa")); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -78,7 +78,7 @@ namespace { namespace MatchersTests { | |||||||
|         throw DerivedException{}; |         throw DerivedException{}; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     class ExceptionMatcher : public Catch::MatcherBase<SpecialException> { |     class ExceptionMatcher : public Catch::Matchers::MatcherBase<SpecialException> { | ||||||
|         int m_expected; |         int m_expected; | ||||||
|     public: |     public: | ||||||
|         ExceptionMatcher(int i) : m_expected(i) {} |         ExceptionMatcher(int i) : m_expected(i) {} | ||||||
| @@ -556,19 +556,8 @@ namespace { namespace MatchersTests { | |||||||
|             REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException,  Message("SpecialException::what")); |             REQUIRE_THROWS_MATCHES(throwsSpecialException(2), SpecialException,  Message("SpecialException::what")); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         TEST_CASE("Composed matchers are distinct", "[matchers][composed]") { |  | ||||||
|             auto m1 = Contains("string"); |  | ||||||
|             auto m2 = Contains("random"); |  | ||||||
|             auto composed1 = m1 || m2; |  | ||||||
|             auto m3 = Contains("different"); |  | ||||||
|             auto composed2 = composed1 || m3; |  | ||||||
|             REQUIRE_THAT(testStringForMatching2(), !composed1); |  | ||||||
|             REQUIRE_THAT(testStringForMatching2(), composed2); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     template<typename Range> |     template<typename Range> | ||||||
|     struct EqualsRangeMatcher : Catch::MatcherGenericBase { |     struct EqualsRangeMatcher : Catch::Matchers::MatcherGenericBase { | ||||||
|  |  | ||||||
|         EqualsRangeMatcher(Range const& range) : range{ range } {} |         EqualsRangeMatcher(Range const& range) : range{ range } {} | ||||||
|  |  | ||||||
| @@ -604,7 +593,6 @@ namespace { namespace MatchersTests { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     TEST_CASE("Combining templated and concrete matchers", "[matchers][templated]") { |     TEST_CASE("Combining templated and concrete matchers", "[matchers][templated]") { | ||||||
|         using namespace Catch::Matchers; |  | ||||||
|         std::vector<int> vec{ 1, 3, 5 }; |         std::vector<int> vec{ 1, 3, 5 }; | ||||||
|  |  | ||||||
|         std::array<int, 3> a{{ 5, 3, 1 }}; |         std::array<int, 3> a{{ 5, 3, 1 }}; | ||||||
| @@ -640,28 +628,28 @@ namespace { namespace MatchersTests { | |||||||
|  |  | ||||||
|         STATIC_REQUIRE(std::is_same< |         STATIC_REQUIRE(std::is_same< | ||||||
|             decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith("bar") && !EndsWith("foo"))), |             decltype(StartsWith("foo") || (StartsWith("bar") && EndsWith("bar") && !EndsWith("foo"))), | ||||||
|             Catch::Matchers::Impl::MatchAnyOf<std::string> |             Catch::Matchers::Detail::MatchAnyOf<std::string> | ||||||
|         >::value); |         >::value); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     struct MatcherA : Catch::MatcherGenericBase { |     struct MatcherA : Catch::Matchers::MatcherGenericBase { | ||||||
|         std::string describe() const override { return "equals: (int) 1 or (float) 1.0f"; } |         std::string describe() const override { return "equals: (int) 1 or (float) 1.0f"; } | ||||||
|         bool match(int i) const { return i == 1; } |         bool match(int i) const { return i == 1; } | ||||||
|         bool match(float f) const { return f == 1.0f; } |         bool match(float f) const { return f == 1.0f; } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     struct MatcherB : Catch::MatcherGenericBase { |     struct MatcherB : Catch::Matchers::MatcherGenericBase { | ||||||
|         std::string describe() const override { return "equals: (long long) 1"; } |         std::string describe() const override { return "equals: (long long) 1"; } | ||||||
|         bool match(long long l) const { return l == 1ll; } |         bool match(long long l) const { return l == 1ll; } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     struct MatcherC : Catch::MatcherGenericBase { |     struct MatcherC : Catch::Matchers::MatcherGenericBase { | ||||||
|         std::string describe() const override { return "equals: (T) 1"; } |         std::string describe() const override { return "equals: (T) 1"; } | ||||||
|         template<typename T> |         template<typename T> | ||||||
|         bool match(T t) const { return t == T{1}; } |         bool match(T t) const { return t == T{1}; } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     struct MatcherD : Catch::MatcherGenericBase { |     struct MatcherD : Catch::Matchers::MatcherGenericBase { | ||||||
|         std::string describe() const override { return "equals: true"; } |         std::string describe() const override { return "equals: true"; } | ||||||
|         bool match(bool b) const { return b == true; } |         bool match(bool b) const { return b == true; } | ||||||
|     }; |     }; | ||||||
| @@ -669,21 +657,21 @@ namespace { namespace MatchersTests { | |||||||
|     TEST_CASE("Combining only templated matchers", "[matchers][templated]") { |     TEST_CASE("Combining only templated matchers", "[matchers][templated]") { | ||||||
|         STATIC_REQUIRE(std::is_same< |         STATIC_REQUIRE(std::is_same< | ||||||
|             decltype(MatcherA() || MatcherB()), |             decltype(MatcherA() || MatcherB()), | ||||||
|             Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB> |             Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB> | ||||||
|         >::value); |         >::value); | ||||||
|  |  | ||||||
|         REQUIRE_THAT(1, MatcherA() || MatcherB()); |         REQUIRE_THAT(1, MatcherA() || MatcherB()); | ||||||
|  |  | ||||||
|         STATIC_REQUIRE(std::is_same< |         STATIC_REQUIRE(std::is_same< | ||||||
|             decltype(MatcherA() && MatcherB()), |             decltype(MatcherA() && MatcherB()), | ||||||
|             Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB> |             Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB> | ||||||
|         >::value); |         >::value); | ||||||
|  |  | ||||||
|         REQUIRE_THAT(1, MatcherA() && MatcherB()); |         REQUIRE_THAT(1, MatcherA() && MatcherB()); | ||||||
|  |  | ||||||
|         STATIC_REQUIRE(std::is_same< |         STATIC_REQUIRE(std::is_same< | ||||||
|             decltype(MatcherA() || !MatcherB()), |             decltype(MatcherA() || !MatcherB()), | ||||||
|             Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, Catch::Matchers::Impl::MatchNotOfGeneric<MatcherB>> |             Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, Catch::Matchers::Detail::MatchNotOfGeneric<MatcherB>> | ||||||
|         >::value); |         >::value); | ||||||
|  |  | ||||||
|         REQUIRE_THAT(1, MatcherA() || !MatcherB()); |         REQUIRE_THAT(1, MatcherA() || !MatcherB()); | ||||||
| @@ -692,14 +680,14 @@ namespace { namespace MatchersTests { | |||||||
|     TEST_CASE("Combining MatchAnyOfGeneric does not nest", "[matchers][templated]") { |     TEST_CASE("Combining MatchAnyOfGeneric does not nest", "[matchers][templated]") { | ||||||
|         STATIC_REQUIRE(std::is_same< |         STATIC_REQUIRE(std::is_same< | ||||||
|             decltype(MatcherA() || MatcherB() || MatcherC()), |             decltype(MatcherA() || MatcherB() || MatcherC()), | ||||||
|             Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> |             Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC> | ||||||
|         >::value); |         >::value); | ||||||
|  |  | ||||||
|         REQUIRE_THAT(1, MatcherA() || MatcherB() || MatcherC()); |         REQUIRE_THAT(1, MatcherA() || MatcherB() || MatcherC()); | ||||||
|  |  | ||||||
|         STATIC_REQUIRE(std::is_same< |         STATIC_REQUIRE(std::is_same< | ||||||
|             decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()), |             decltype(MatcherA() || MatcherB() || MatcherC() || MatcherD()), | ||||||
|             Catch::Matchers::Impl::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> |             Catch::Matchers::Detail::MatchAnyOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> | ||||||
|         >::value); |         >::value); | ||||||
|  |  | ||||||
|         REQUIRE_THAT(1, MatcherA() || MatcherB() || MatcherC() || MatcherD()); |         REQUIRE_THAT(1, MatcherA() || MatcherB() || MatcherC() || MatcherD()); | ||||||
| @@ -708,14 +696,14 @@ namespace { namespace MatchersTests { | |||||||
|     TEST_CASE("Combining MatchAllOfGeneric does not nest", "[matchers][templated]") { |     TEST_CASE("Combining MatchAllOfGeneric does not nest", "[matchers][templated]") { | ||||||
|         STATIC_REQUIRE(std::is_same< |         STATIC_REQUIRE(std::is_same< | ||||||
|             decltype(MatcherA() && MatcherB() && MatcherC()), |             decltype(MatcherA() && MatcherB() && MatcherC()), | ||||||
|             Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> |             Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC> | ||||||
|         >::value); |         >::value); | ||||||
|  |  | ||||||
|         REQUIRE_THAT(1, MatcherA() && MatcherB() && MatcherC()); |         REQUIRE_THAT(1, MatcherA() && MatcherB() && MatcherC()); | ||||||
|  |  | ||||||
|         STATIC_REQUIRE(std::is_same< |         STATIC_REQUIRE(std::is_same< | ||||||
|             decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()), |             decltype(MatcherA() && MatcherB() && MatcherC() && MatcherD()), | ||||||
|             Catch::Matchers::Impl::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> |             Catch::Matchers::Detail::MatchAllOfGeneric<MatcherA, MatcherB, MatcherC, MatcherD> | ||||||
|         >::value); |         >::value); | ||||||
|  |  | ||||||
|         REQUIRE_THAT(1, MatcherA() && MatcherB() && MatcherC() && MatcherD()); |         REQUIRE_THAT(1, MatcherA() && MatcherB() && MatcherC() && MatcherD()); | ||||||
| @@ -724,7 +712,7 @@ namespace { namespace MatchersTests { | |||||||
|     TEST_CASE("Combining MatchNotOfGeneric does not nest", "[matchers][templated]") { |     TEST_CASE("Combining MatchNotOfGeneric does not nest", "[matchers][templated]") { | ||||||
|         STATIC_REQUIRE(std::is_same< |         STATIC_REQUIRE(std::is_same< | ||||||
|             decltype(!MatcherA()), |             decltype(!MatcherA()), | ||||||
|             Catch::Matchers::Impl::MatchNotOfGeneric<MatcherA> |             Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA> | ||||||
|         >::value); |         >::value); | ||||||
|  |  | ||||||
|         REQUIRE_THAT(0, !MatcherA()); |         REQUIRE_THAT(0, !MatcherA()); | ||||||
| @@ -738,7 +726,7 @@ namespace { namespace MatchersTests { | |||||||
|  |  | ||||||
|         STATIC_REQUIRE(std::is_same< |         STATIC_REQUIRE(std::is_same< | ||||||
|             decltype(!!!MatcherA()), |             decltype(!!!MatcherA()), | ||||||
|             Catch::Matchers::Impl::MatchNotOfGeneric<MatcherA> |             Catch::Matchers::Detail::MatchNotOfGeneric<MatcherA> | ||||||
|         >::value); |         >::value); | ||||||
|  |  | ||||||
|         REQUIRE_THAT(0, !!!MatcherA()); |         REQUIRE_THAT(0, !!!MatcherA()); | ||||||
| @@ -765,7 +753,7 @@ namespace { namespace MatchersTests { | |||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     struct EvilMatcher : Catch::MatcherGenericBase { |     struct EvilMatcher : Catch::Matchers::MatcherGenericBase { | ||||||
|         std::string describe() const override { |         std::string describe() const override { | ||||||
|             return "equals: 45"; |             return "equals: 45"; | ||||||
|         } |         } | ||||||
| @@ -790,7 +778,7 @@ namespace { namespace MatchersTests { | |||||||
|         REQUIRE_NOTHROW((EvilMatcher() && EvilMatcher()) || !EvilMatcher()); |         REQUIRE_NOTHROW((EvilMatcher() && EvilMatcher()) || !EvilMatcher()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     struct ImmovableMatcher : Catch::MatcherGenericBase { |     struct ImmovableMatcher : Catch::Matchers::MatcherGenericBase { | ||||||
|         ImmovableMatcher() = default; |         ImmovableMatcher() = default; | ||||||
|         ImmovableMatcher(ImmovableMatcher const&) = delete; |         ImmovableMatcher(ImmovableMatcher const&) = delete; | ||||||
|         ImmovableMatcher(ImmovableMatcher &&) = delete; |         ImmovableMatcher(ImmovableMatcher &&) = delete; | ||||||
| @@ -814,7 +802,7 @@ namespace { namespace MatchersTests { | |||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     struct ThrowOnCopyOrMoveMatcher : Catch::MatcherGenericBase { |     struct ThrowOnCopyOrMoveMatcher : Catch::Matchers::MatcherGenericBase { | ||||||
|         ThrowOnCopyOrMoveMatcher() = default; |         ThrowOnCopyOrMoveMatcher() = default; | ||||||
|         [[noreturn]] |         [[noreturn]] | ||||||
|         ThrowOnCopyOrMoveMatcher(ThrowOnCopyOrMoveMatcher const&) { |         ThrowOnCopyOrMoveMatcher(ThrowOnCopyOrMoveMatcher const&) { | ||||||
| @@ -849,7 +837,7 @@ namespace { namespace MatchersTests { | |||||||
|         REQUIRE_THAT(123, (ImmovableMatcher() && ImmovableMatcher()) || !ImmovableMatcher()); |         REQUIRE_THAT(123, (ImmovableMatcher() && ImmovableMatcher()) || !ImmovableMatcher()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     struct ReferencingMatcher : Catch::MatcherGenericBase { |     struct ReferencingMatcher : Catch::Matchers::MatcherGenericBase { | ||||||
|         std::string describe() const override { |         std::string describe() const override { | ||||||
|             return "takes reference"; |             return "takes reference"; | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Martin Hořeňovský
					Martin Hořeňovský