diff options
| author | Martin Hořeňovský | 2023-01-22 19:43:11 +0100 |
|---|---|---|
| committer | Martin Hořeňovský | 2023-01-22 19:53:12 +0100 |
| commit | c837cb4a8aaa2064f63e67ed0a7f7055dbf159c5 (patch) | |
| tree | 2df4e0575eed9d5555b2992a465c5b69630c6830 /extras/catch_amalgamated.hpp | |
| parent | 8359a6b244a26cffabd4440b17fac8b1392815af (diff) | |
| download | catch3-3.3.0.tar.gz | |
v3.3.0v3.3.0
Diffstat (limited to 'extras/catch_amalgamated.hpp')
| -rw-r--r-- | extras/catch_amalgamated.hpp | 481 |
1 files changed, 350 insertions, 131 deletions
diff --git a/extras/catch_amalgamated.hpp b/extras/catch_amalgamated.hpp index e91734a4..25928e4e 100644 --- a/extras/catch_amalgamated.hpp +++ b/extras/catch_amalgamated.hpp @@ -5,8 +5,8 @@ // SPDX-License-Identifier: BSL-1.0 -// Catch v3.2.1 -// Generated: 2022-12-09 23:01:14.526666 +// Catch v3.3.0 +// Generated: 2023-01-22 19:46:23.163056 // ---------------------------------------------------------- // This file is an amalgamation of multiple different files. // You probably shouldn't edit it directly. @@ -372,9 +372,14 @@ namespace Catch { #endif #if defined(__CUDACC__) && !defined(__clang__) +# ifdef __NVCC_DIAG_PRAGMA_SUPPORT__ +// New pragmas introduced in CUDA 11.5+ # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic push" ) # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "nv_diagnostic pop" ) # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "nv_diag_suppress 177" ) +# else +# define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS _Pragma( "diag_suppress 177" ) +# endif #endif // clang-cl defines _MSC_VER as well as __clang__, which could cause the @@ -492,8 +497,14 @@ namespace Catch { // Visual C++ #if defined(_MSC_VER) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) +// We want to defer to nvcc-specific warning suppression if we are compiled +// with nvcc masquerading for MSVC. +# if !defined( __CUDACC__ ) +# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + __pragma( warning( push ) ) +# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ + __pragma( warning( pop ) ) +# endif // Universal Windows platform does not support SEH // Or console colours (or console at all...) @@ -850,6 +861,7 @@ namespace Catch { std::uint64_t passed = 0; std::uint64_t failed = 0; std::uint64_t failedButOk = 0; + std::uint64_t skipped = 0; }; struct Totals { @@ -916,6 +928,8 @@ namespace Catch { Ok = 0, Info = 1, Warning = 2, + // TODO: Should explicit skip be considered "not OK" (cf. isOk)? I.e., should it have the failure bit? + ExplicitSkip = 4, FailureBit = 0x10, @@ -1062,116 +1076,6 @@ namespace Catch { #include <chrono> -namespace Catch { - - class AssertionResult; - struct AssertionInfo; - struct SectionInfo; - struct SectionEndInfo; - struct MessageInfo; - struct MessageBuilder; - struct Counts; - struct AssertionReaction; - struct SourceLineInfo; - - class ITransientExpression; - class IGeneratorTracker; - - struct BenchmarkInfo; - template <typename Duration = std::chrono::duration<double, std::nano>> - struct BenchmarkStats; - - class IResultCapture { - public: - virtual ~IResultCapture(); - - virtual bool sectionStarted( SectionInfo const& sectionInfo, - Counts& assertions ) = 0; - virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; - virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; - - virtual auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0; - - virtual void benchmarkPreparing( StringRef name ) = 0; - virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; - virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0; - virtual void benchmarkFailed( StringRef error ) = 0; - - virtual void pushScopedMessage( MessageInfo const& message ) = 0; - virtual void popScopedMessage( MessageInfo const& message ) = 0; - - virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0; - - virtual void handleFatalErrorCondition( StringRef message ) = 0; - - virtual void handleExpr - ( AssertionInfo const& info, - ITransientExpression const& expr, - AssertionReaction& reaction ) = 0; - virtual void handleMessage - ( AssertionInfo const& info, - ResultWas::OfType resultType, - StringRef message, - AssertionReaction& reaction ) = 0; - virtual void handleUnexpectedExceptionNotThrown - ( AssertionInfo const& info, - AssertionReaction& reaction ) = 0; - virtual void handleUnexpectedInflightException - ( AssertionInfo const& info, - std::string const& message, - AssertionReaction& reaction ) = 0; - virtual void handleIncomplete - ( AssertionInfo const& info ) = 0; - virtual void handleNonExpr - ( AssertionInfo const &info, - ResultWas::OfType resultType, - AssertionReaction &reaction ) = 0; - - - - virtual bool lastAssertionPassed() = 0; - virtual void assertionPassed() = 0; - - // Deprecated, do not use: - virtual std::string getCurrentTestName() const = 0; - virtual const AssertionResult* getLastResult() const = 0; - virtual void exceptionEarlyReported() = 0; - }; - - IResultCapture& getResultCapture(); -} - -#endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED - -#include <string> - -namespace Catch { - - struct MessageInfo { - MessageInfo( StringRef _macroName, - SourceLineInfo const& _lineInfo, - ResultWas::OfType _type ); - - StringRef macroName; - std::string message; - SourceLineInfo lineInfo; - ResultWas::OfType type; - unsigned int sequence; - - bool operator == (MessageInfo const& other) const { - return sequence == other.sequence; - } - bool operator < (MessageInfo const& other) const { - return sequence < other.sequence; - } - private: - static unsigned int globalCount; - }; - -} // end namespace Catch - -#endif // CATCH_MESSAGE_INFO_HPP_INCLUDED - #ifndef CATCH_UNIQUE_PTR_HPP_INCLUDED #define CATCH_UNIQUE_PTR_HPP_INCLUDED @@ -1284,6 +1188,128 @@ namespace Detail { #endif // CATCH_UNIQUE_PTR_HPP_INCLUDED +namespace Catch { + + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + struct MessageBuilder; + struct Counts; + struct AssertionReaction; + struct SourceLineInfo; + + class ITransientExpression; + class IGeneratorTracker; + + struct BenchmarkInfo; + template <typename Duration = std::chrono::duration<double, std::nano>> + struct BenchmarkStats; + + namespace Generators { + class GeneratorUntypedBase; + using GeneratorBasePtr = Catch::Detail::unique_ptr<GeneratorUntypedBase>; + } + + + class IResultCapture { + public: + virtual ~IResultCapture(); + + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + + virtual IGeneratorTracker* + acquireGeneratorTracker( StringRef generatorName, + SourceLineInfo const& lineInfo ) = 0; + virtual IGeneratorTracker* + createGeneratorTracker( StringRef generatorName, + SourceLineInfo lineInfo, + Generators::GeneratorBasePtr&& generator ) = 0; + + virtual void benchmarkPreparing( StringRef name ) = 0; + virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; + virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0; + virtual void benchmarkFailed( StringRef error ) = 0; + + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0; + + virtual void handleFatalErrorCondition( StringRef message ) = 0; + + virtual void handleExpr + ( AssertionInfo const& info, + ITransientExpression const& expr, + AssertionReaction& reaction ) = 0; + virtual void handleMessage + ( AssertionInfo const& info, + ResultWas::OfType resultType, + StringRef message, + AssertionReaction& reaction ) = 0; + virtual void handleUnexpectedExceptionNotThrown + ( AssertionInfo const& info, + AssertionReaction& reaction ) = 0; + virtual void handleUnexpectedInflightException + ( AssertionInfo const& info, + std::string const& message, + AssertionReaction& reaction ) = 0; + virtual void handleIncomplete + ( AssertionInfo const& info ) = 0; + virtual void handleNonExpr + ( AssertionInfo const &info, + ResultWas::OfType resultType, + AssertionReaction &reaction ) = 0; + + + + virtual bool lastAssertionPassed() = 0; + virtual void assertionPassed() = 0; + + // Deprecated, do not use: + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + virtual void exceptionEarlyReported() = 0; + }; + + IResultCapture& getResultCapture(); +} + +#endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED + +#include <string> + +namespace Catch { + + struct MessageInfo { + MessageInfo( StringRef _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + StringRef macroName; + std::string message; + SourceLineInfo lineInfo; + ResultWas::OfType type; + unsigned int sequence; + + bool operator == (MessageInfo const& other) const { + return sequence == other.sequence; + } + bool operator < (MessageInfo const& other) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + +} // end namespace Catch + +#endif // CATCH_MESSAGE_INFO_HPP_INCLUDED + // Adapted from donated nonius code. @@ -1557,7 +1583,12 @@ namespace Catch { */ virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; - //! Called with test cases that are skipped due to the test run aborting + /** + * Called with test cases that are skipped due to the test run aborting. + * NOT called for test cases that are explicitly skipped using the `SKIP` macro. + * + * Deprecated - will be removed in the next major release. + */ virtual void skipTest( TestCaseInfo const& testInfo ) = 0; //! Called if a fatal error (signal/structured exception) occured @@ -1748,6 +1779,9 @@ namespace Catch { */ [[noreturn]] void throw_test_failure_exception(); + //! Used to signal that the remainder of a test should be skipped + struct TestSkipException{}; + } // namespace Catch #endif // CATCH_TEST_FAILURE_EXCEPTION_HPP_INCLUDED @@ -4058,6 +4092,7 @@ namespace Catch { Error = BrightRed, Success = Green, + Skip = LightGrey, OriginalExpression = Cyan, ReconstructedExpression = BrightYellow, @@ -5811,6 +5846,7 @@ namespace Catch { struct AssertionReaction { bool shouldDebugBreak = false; bool shouldThrow = false; + bool shouldSkip = false; }; class AssertionHandler { @@ -6183,7 +6219,7 @@ struct AutoReg : Detail::NonCopyable { CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ + namespace{ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ static void TestName() #define INTERNAL_CATCH_TESTCASE( ... ) \ @@ -6194,7 +6230,7 @@ struct AutoReg : Detail::NonCopyable { CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ + namespace{ const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION /////////////////////////////////////////////////////////////////////////////// @@ -6206,7 +6242,7 @@ struct AutoReg : Detail::NonCopyable { struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ void test(); \ }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ + const Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ } \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ void TestName::test() @@ -6260,6 +6296,7 @@ struct AutoReg : Detail::NonCopyable { #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + #define CATCH_SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) @@ -6313,6 +6350,7 @@ struct AutoReg : Detail::NonCopyable { #define CATCH_FAIL( ... ) (void)(0) #define CATCH_FAIL_CHECK( ... ) (void)(0) #define CATCH_SUCCEED( ... ) (void)(0) + #define CATCH_SKIP( ... ) (void)(0) #define CATCH_STATIC_REQUIRE( ... ) (void)(0) #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0) @@ -6357,6 +6395,7 @@ struct AutoReg : Detail::NonCopyable { #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + #define SKIP( ... ) INTERNAL_CATCH_MSG( "SKIP", Catch::ResultWas::ExplicitSkip, Catch::ResultDisposition::Normal, __VA_ARGS__ ) #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) @@ -6409,6 +6448,7 @@ struct AutoReg : Detail::NonCopyable { #define FAIL( ... ) (void)(0) #define FAIL_CHECK( ... ) (void)(0) #define SUCCEED( ... ) (void)(0) + #define SKIP( ... ) (void)(0) #define STATIC_REQUIRE( ... ) (void)(0) #define STATIC_REQUIRE_FALSE( ... ) (void)(0) @@ -7098,6 +7138,7 @@ struct AutoReg : Detail::NonCopyable { +#include <cstdint> #include <string> #include <vector> @@ -7357,8 +7398,8 @@ namespace Catch { #define CATCH_VERSION_MACROS_HPP_INCLUDED #define CATCH_VERSION_MAJOR 3 -#define CATCH_VERSION_MINOR 2 -#define CATCH_VERSION_PATCH 1 +#define CATCH_VERSION_MINOR 3 +#define CATCH_VERSION_PATCH 0 #endif // CATCH_VERSION_MACROS_HPP_INCLUDED @@ -7682,21 +7723,28 @@ namespace Detail { return makeGenerators( value( T( CATCH_FORWARD( val ) ) ), CATCH_FORWARD( moreGenerators )... ); } - auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; + IGeneratorTracker* acquireGeneratorTracker( StringRef generatorName, + SourceLineInfo const& lineInfo ); + IGeneratorTracker* createGeneratorTracker( StringRef generatorName, + SourceLineInfo lineInfo, + GeneratorBasePtr&& generator ); template<typename L> - // Note: The type after -> is weird, because VS2015 cannot parse - // the expression used in the typedef inside, when it is in - // return type. Yeah. - auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) { + auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> typename decltype(generatorExpression())::type { using UnderlyingType = typename decltype(generatorExpression())::type; - IGeneratorTracker& tracker = acquireGeneratorTracker( generatorName, lineInfo ); - if (!tracker.hasGenerator()) { - tracker.setGenerator(Catch::Detail::make_unique<Generators<UnderlyingType>>(generatorExpression())); + IGeneratorTracker* tracker = acquireGeneratorTracker( generatorName, lineInfo ); + // Creation of tracker is delayed after generator creation, so + // that constructing generator can fail without breaking everything. + if (!tracker) { + tracker = createGeneratorTracker( + generatorName, + lineInfo, + Catch::Detail::make_unique<Generators<UnderlyingType>>( + generatorExpression() ) ); } - auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() ); + auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker->getGenerator() ); return generator.get(); } @@ -8515,7 +8563,10 @@ namespace Catch { #if defined(__i386__) || defined(__x86_64__) #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ #elif defined(__aarch64__) - #define CATCH_TRAP() __asm__(".inst 0xd43e0000") + #define CATCH_TRAP() __asm__(".inst 0xd43e0000") + #elif defined(__POWERPC__) + #define CATCH_TRAP() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ + : : : "memory","r0","r3","r4" ) /* NOLINT */ #endif #elif defined(CATCH_PLATFORM_IPHONE) @@ -9148,6 +9199,10 @@ namespace TestCaseTracking { return lhs.name == rhs.name && lhs.location == rhs.location; } + friend bool operator!=(NameAndLocation const& lhs, + NameAndLocation const& rhs) { + return !( lhs == rhs ); + } }; class ITracker; @@ -9370,7 +9425,14 @@ namespace Catch { void sectionEnded( SectionEndInfo const& endInfo ) override; void sectionEndedEarly( SectionEndInfo const& endInfo ) override; - auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override; + IGeneratorTracker* + acquireGeneratorTracker( StringRef generatorName, + SourceLineInfo const& lineInfo ) override; + IGeneratorTracker* createGeneratorTracker( + StringRef generatorName, + SourceLineInfo lineInfo, + Generators::GeneratorBasePtr&& generator ) override; + void benchmarkPreparing( StringRef name ) override; void benchmarkStarting( BenchmarkInfo const& info ) override; @@ -9568,6 +9630,7 @@ namespace Catch { #define CATCH_STRING_MANIP_HPP_INCLUDED +#include <cstdint> #include <string> #include <iosfwd> #include <vector> @@ -10960,6 +11023,32 @@ public: //! Creates a matcher that checks whether a std derived exception has the provided message ExceptionMessageMatcher Message(std::string const& message); +template <typename StringMatcherType> +class ExceptionMessageMatchesMatcher final + : public MatcherBase<std::exception> { + StringMatcherType m_matcher; + +public: + ExceptionMessageMatchesMatcher( StringMatcherType matcher ): + m_matcher( CATCH_MOVE( matcher ) ) {} + + bool match( std::exception const& ex ) const override { + return m_matcher.match( ex.what() ); + } + + std::string describe() const override { + return " matches \"" + m_matcher.describe() + '"'; + } +}; + +//! Creates a matcher that checks whether a message from an std derived +//! exception matches a provided matcher +template <typename StringMatcherType> +ExceptionMessageMatchesMatcher<StringMatcherType> +MessageMatches( StringMatcherType&& matcher ) { + return { CATCH_FORWARD( matcher ) }; +} + } // namespace Matchers } // namespace Catch @@ -11247,6 +11336,136 @@ namespace Catch { #endif // CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED +#ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED +#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED + +#include <algorithm> +#include <utility> + +namespace Catch { + namespace Matchers { + + /** + * Matcher for checking that an element contains the same + * elements in the same order + */ + template <typename TargetRangeLike, typename Equality> + class RangeEqualsMatcher final : public MatcherGenericBase { + TargetRangeLike m_desired; + Equality m_predicate; + + public: + template <typename TargetRangeLike2, typename Equality2> + RangeEqualsMatcher( TargetRangeLike2&& range, + Equality2&& predicate ): + m_desired( CATCH_FORWARD( range ) ), + m_predicate( CATCH_FORWARD( predicate ) ) {} + + template <typename RangeLike> + bool match( RangeLike&& rng ) const { + using std::begin; + using std::end; + return std::equal( begin(m_desired), + end(m_desired), + begin(rng), + end(rng), + m_predicate ); + } + + std::string describe() const override { + return "elements are " + Catch::Detail::stringify( m_desired ); + } + }; + + /** + * Matcher for checking that an element contains the same + * elements (but not necessarily in the same order) + */ + template <typename TargetRangeLike, typename Equality> + class UnorderedRangeEqualsMatcher final : public MatcherGenericBase { + TargetRangeLike m_desired; + Equality m_predicate; + + public: + template <typename TargetRangeLike2, typename Equality2> + UnorderedRangeEqualsMatcher( TargetRangeLike2&& range, + Equality2&& predicate ): + m_desired( CATCH_FORWARD( range ) ), + m_predicate( CATCH_FORWARD( predicate ) ) {} + + template <typename RangeLike> + bool match( RangeLike&& rng ) const { + using std::begin; + using std::end; + return std::is_permutation( begin( m_desired ), + end( m_desired ), + begin( rng ), + end( rng ), + m_predicate ); + } + + std::string describe() const override { + return "unordered elements are " + + ::Catch::Detail::stringify( m_desired ); + } + }; + + /** + * Creates a matcher that checks if all elements in a range are equal + * to all elements in another range. + * + * Uses `std::equal_to` to do the comparison + */ + template <typename RangeLike> + std::enable_if_t<!Detail::is_matcher<RangeLike>::value, + RangeEqualsMatcher<RangeLike, std::equal_to<>>> + RangeEquals( RangeLike&& range ) { + return { CATCH_FORWARD( range ), std::equal_to<>{} }; + } + + /** + * Creates a matcher that checks if all elements in a range are equal + * to all elements in another range. + * + * Uses to provided predicate `predicate` to do the comparisons + */ + template <typename RangeLike, typename Equality> + RangeEqualsMatcher<RangeLike, Equality> + RangeEquals( RangeLike&& range, Equality&& predicate ) { + return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; + } + + /** + * Creates a matcher that checks if all elements in a range are equal + * to all elements in another range, in some permutation + * + * Uses `std::equal_to` to do the comparison + */ + template <typename RangeLike> + std::enable_if_t< + !Detail::is_matcher<RangeLike>::value, + UnorderedRangeEqualsMatcher<RangeLike, std::equal_to<>>> + UnorderedRangeEquals( RangeLike&& range ) { + return { CATCH_FORWARD( range ), std::equal_to<>{} }; + } + + /** + * Creates a matcher that checks if all elements in a range are equal + * to all elements in another range, in some permuation. + * + * Uses to provided predicate `predicate` to do the comparisons + */ + template <typename RangeLike, typename Equality> + UnorderedRangeEqualsMatcher<RangeLike, Equality> + UnorderedRangeEquals( RangeLike&& range, Equality&& predicate ) { + return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; + } + } // namespace Matchers +} // namespace Catch + +#endif // CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED + + #ifndef CATCH_MATCHERS_STRING_HPP_INCLUDED #define CATCH_MATCHERS_STRING_HPP_INCLUDED |