From ead7cf49d10fc5a387ad19261adeee90198afeb7 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 27 Apr 2019 17:36:10 -0400 Subject: [PATCH] externals: Update Catch to 2.7.2 Updates Catch from 2.7.0 to 2.7.2. Keeps the unit-testing library up to date. --- externals/catch/catch.hpp | 307 +++++++++++++++++++++++--------------- 1 file changed, 188 insertions(+), 119 deletions(-) diff --git a/externals/catch/catch.hpp b/externals/catch/catch.hpp index 1850fff1..df14c357 100644 --- a/externals/catch/catch.hpp +++ b/externals/catch/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.7.0 - * Generated: 2019-03-07 21:34:30.252164 + * Catch v2.7.2 + * Generated: 2019-04-22 23:13:14.687465 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. @@ -15,7 +15,7 @@ #define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MINOR 7 -#define CATCH_VERSION_PATCH 0 +#define CATCH_VERSION_PATCH 2 #ifdef __clang__ # pragma clang system_header @@ -3113,7 +3113,7 @@ public: // The following functions create the actual matcher objects. // The user has to explicitly specify type to the function, because - // infering std::function is hard (but possible) and + // inferring std::function is hard (but possible) and // requires a lot of TMP. template Generic::PredicateMatcher Predicate(std::function const& predicate, std::string const& description = "") { @@ -3201,28 +3201,6 @@ namespace Catch { namespace Matchers { namespace Vector { - namespace Detail { - template - size_t count(InputIterator first, InputIterator last, T const& item) { - size_t cnt = 0; - for (; first != last; ++first) { - if (*first == item) { - ++cnt; - } - } - return cnt; - } - template - bool contains(InputIterator first, InputIterator last, T const& item) { - for (; first != last; ++first) { - if (*first == item) { - return true; - } - } - return false; - } - } - template struct ContainsElementMatcher : MatcherBase> { @@ -3297,6 +3275,42 @@ namespace Matchers { std::vector const& m_comparator; }; + template + struct ApproxMatcher : MatcherBase> { + + ApproxMatcher(std::vector const& comparator) : m_comparator( comparator ) {} + + bool match(std::vector const &v) const override { + if (m_comparator.size() != v.size()) + return false; + for (std::size_t i = 0; i < v.size(); ++i) + if (m_comparator[i] != approx(v[i])) + return false; + return true; + } + std::string describe() const override { + return "is approx: " + ::Catch::Detail::stringify( m_comparator ); + } + template ::value>::type> + ApproxMatcher& epsilon( T const& newEpsilon ) { + approx.epsilon(newEpsilon); + return *this; + } + template ::value>::type> + ApproxMatcher& margin( T const& newMargin ) { + approx.margin(newMargin); + return *this; + } + template ::value>::type> + ApproxMatcher& scale( T const& newScale ) { + approx.scale(newScale); + return *this; + } + + std::vector const& m_comparator; + mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom(); + }; + template struct UnorderedEqualsMatcher : MatcherBase> { UnorderedEqualsMatcher(std::vector const& target) : m_target(target) {} @@ -3306,28 +3320,7 @@ namespace Matchers { if (m_target.size() != vec.size()) { return false; } - auto lfirst = m_target.begin(), llast = m_target.end(); - auto rfirst = vec.begin(), rlast = vec.end(); - // Cut common prefix to optimize checking of permuted parts - while (lfirst != llast && *lfirst == *rfirst) { - ++lfirst; ++rfirst; - } - if (lfirst == llast) { - return true; - } - - for (auto mid = lfirst; mid != llast; ++mid) { - // Skip already counted items - if (Detail::contains(lfirst, mid, *mid)) { - continue; - } - size_t num_vec = Detail::count(rfirst, rlast, *mid); - if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) { - return false; - } - } - - return true; + return std::is_permutation(m_target.begin(), m_target.end(), vec.begin()); } std::string describe() const override { @@ -3357,6 +3350,11 @@ namespace Matchers { return Vector::EqualsMatcher( comparator ); } + template + Vector::ApproxMatcher Approx( std::vector const& comparator ) { + return Vector::ApproxMatcher( comparator ); + } + template Vector::UnorderedEqualsMatcher UnorderedEquals(std::vector const& target) { return Vector::UnorderedEqualsMatcher(target); @@ -3686,7 +3684,11 @@ namespace Generators { } // namespace Catch #define GENERATE( ... ) \ - Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) + Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) +#define GENERATE_COPY( ... ) \ + Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) +#define GENERATE_REF( ... ) \ + Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) // end catch_generators.hpp // start catch_generators_generic.hpp @@ -3849,16 +3851,28 @@ namespace Generators { } }; - template +#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703 + // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is + // replaced with std::invoke_result here. Also *_t format is preferred over + // typename *::type format. + template + using MapFunctionReturnType = std::remove_reference_t>>; +#else + template + using MapFunctionReturnType = typename std::remove_reference::type>::type>::type; +#endif + + template > GeneratorWrapper map(Func&& function, GeneratorWrapper&& generator) { return GeneratorWrapper( pf::make_unique>(std::forward(function), std::move(generator)) ); } - template - GeneratorWrapper map(Func&& function, GeneratorWrapper&& generator) { + + template + GeneratorWrapper map(Func&& function, GeneratorWrapper&& generator) { return GeneratorWrapper( - pf::make_unique>(std::forward(function), std::move(generator)) + pf::make_unique>(std::forward(function), std::move(generator)) ); } @@ -4022,6 +4036,7 @@ namespace Catch { virtual ShowDurations::OrNot showDurations() const = 0; virtual TestSpec const& testSpec() const = 0; virtual bool hasTestFilters() const = 0; + virtual std::vector const& getTestsOrTags() const = 0; virtual RunTests::InWhatOrder runOrder() const = 0; virtual unsigned int rngSeed() const = 0; virtual int benchmarkResolutionMultiple() const = 0; @@ -4352,7 +4367,7 @@ namespace Catch { arcSafeRelease( m_substr ); } - bool match( NSString* arg ) const override { + bool match( NSString* const& str ) const override { return false; } @@ -4362,7 +4377,7 @@ namespace Catch { struct Equals : StringHolder { Equals( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* str ) const override { + bool match( NSString* const& str ) const override { return (str != nil || m_substr == nil ) && [str isEqualToString:m_substr]; } @@ -4375,7 +4390,7 @@ namespace Catch { struct Contains : StringHolder { Contains( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* str ) const { + bool match( NSString* const& str ) const override { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location != NSNotFound; } @@ -4388,7 +4403,7 @@ namespace Catch { struct StartsWith : StringHolder { StartsWith( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* str ) const override { + bool match( NSString* const& str ) const override { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == 0; } @@ -4400,7 +4415,7 @@ namespace Catch { struct EndsWith : StringHolder { EndsWith( NSString* substr ) : StringHolder( substr ){} - bool match( NSString* str ) const override { + bool match( NSString* const& str ) const override { return (str != nil || m_substr == nil ) && [str rangeOfString:m_substr].location == [str length] - [m_substr length]; } @@ -4518,7 +4533,7 @@ namespace Catch { public: NamePattern( std::string const& name ); virtual ~NamePattern(); - virtual bool matches( TestCaseInfo const& testCase ) const override; + bool matches( TestCaseInfo const& testCase ) const override; private: WildcardPattern m_wildcardPattern; }; @@ -4527,7 +4542,7 @@ namespace Catch { public: TagPattern( std::string const& tag ); virtual ~TagPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const override; + bool matches( TestCaseInfo const& testCase ) const override; private: std::string m_tag; }; @@ -4536,7 +4551,7 @@ namespace Catch { public: ExcludedPattern( PatternPtr const& underlyingPattern ); virtual ~ExcludedPattern(); - virtual bool matches( TestCaseInfo const& testCase ) const override; + bool matches( TestCaseInfo const& testCase ) const override; private: PatternPtr m_underlyingPattern; }; @@ -4708,10 +4723,10 @@ namespace Catch { std::string getProcessName() const; std::string const& getReporterName() const; - std::vector const& getTestsOrTags() const; + std::vector const& getTestsOrTags() const override; std::vector const& getSectionsToRun() const override; - virtual TestSpec const& testSpec() const override; + TestSpec const& testSpec() const override; bool hasTestFilters() const override; bool showHelp() const; @@ -5082,6 +5097,8 @@ namespace Catch { // Returns double formatted as %.3f (format expected on output) std::string getFormattedDuration( double duration ); + std::string serializeFilters( std::vector const& container ); + template struct StreamingReporterBase : IStreamingReporter { @@ -5109,6 +5126,7 @@ namespace Catch { void testRunStarting(TestRunInfo const& _testRunInfo) override { currentTestRunInfo = _testRunInfo; } + void testGroupStarting(GroupInfo const& _groupInfo) override { currentGroupInfo = _groupInfo; } @@ -5399,11 +5417,11 @@ namespace Catch { class ReporterFactory : public IReporterFactory { - virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { + IStreamingReporterPtr create( ReporterConfig const& config ) const override { return std::unique_ptr( new T( config ) ); } - virtual std::string getDescription() const override { + std::string getDescription() const override { return T::getDescription(); } }; @@ -5420,10 +5438,10 @@ namespace Catch { class ListenerFactory : public IReporterFactory { - virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { + IStreamingReporterPtr create( ReporterConfig const& config ) const override { return std::unique_ptr( new T( config ) ); } - virtual std::string getDescription() const override { + std::string getDescription() const override { return std::string(); } }; @@ -5521,7 +5539,7 @@ namespace Catch { void testCaseEnded(TestCaseStats const& _testCaseStats) override; void testGroupEnded(TestGroupStats const& _testGroupStats) override; void testRunEnded(TestRunStats const& _testRunStats) override; - + void testRunStarting(TestRunInfo const& _testRunInfo) override; private: void lazyPrint(); @@ -5543,6 +5561,7 @@ namespace Catch { void printTotalsDivider(Totals const& totals); void printSummaryDivider(); + void printTestFilters(); private: bool m_headerPrinted = false; @@ -5823,8 +5842,6 @@ namespace TestCaseTracking { public: - static TrackerContext& instance(); - ITracker& startRun(); void endRun(); @@ -5970,18 +5987,18 @@ namespace Detail { return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); } - void Approx::setMargin(double margin) { - CATCH_ENFORCE(margin >= 0, - "Invalid Approx::margin: " << margin << '.' + void Approx::setMargin(double newMargin) { + CATCH_ENFORCE(newMargin >= 0, + "Invalid Approx::margin: " << newMargin << '.' << " Approx::Margin has to be non-negative."); - m_margin = margin; + m_margin = newMargin; } - void Approx::setEpsilon(double epsilon) { - CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0, - "Invalid Approx::epsilon: " << epsilon << '.' + void Approx::setEpsilon(double newEpsilon) { + CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0, + "Invalid Approx::epsilon: " << newEpsilon << '.' << " Approx::epsilon has to be in [0, 1]"); - m_epsilon = epsilon; + m_epsilon = newEpsilon; } } // end namespace Detail @@ -6617,6 +6634,9 @@ public: m_suffix = false; auto width = m_column.m_width - indent(); m_end = m_pos; + if (line()[m_pos] == '\n') { + ++m_end; + } while (m_end < line().size() && line()[m_end] != '\n') ++m_end; @@ -8021,10 +8041,7 @@ namespace Catch { m_stream( openStream() ) { TestSpecParser parser(ITagAliasRegistry::get()); - if (data.testsOrTags.empty()) { - parser.parse("~[.]"); // All not hidden tests - } - else { + if (!data.testsOrTags.empty()) { m_hasTestFilters = true; for( auto const& testOrTags : data.testsOrTags ) parser.parse( testOrTags ); @@ -8142,7 +8159,7 @@ namespace { originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); } - virtual void use( Colour::Code _colourCode ) override { + void use( Colour::Code _colourCode ) override { switch( _colourCode ) { case Colour::None: return setTextAttribute( originalForegroundAttributes ); case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); @@ -8205,7 +8222,7 @@ namespace { // https://github.com/philsquared/Catch/pull/131 class PosixColourImpl : public IColourImpl { public: - virtual void use( Colour::Code _colourCode ) override { + void use( Colour::Code _colourCode ) override { switch( _colourCode ) { case Colour::None: case Colour::White: return setColour( "[0m" ); @@ -8316,27 +8333,27 @@ namespace Catch { class Context : public IMutableContext, NonCopyable { public: // IContext - virtual IResultCapture* getResultCapture() override { + IResultCapture* getResultCapture() override { return m_resultCapture; } - virtual IRunner* getRunner() override { + IRunner* getRunner() override { return m_runner; } - virtual IConfigPtr const& getConfig() const override { + IConfigPtr const& getConfig() const override { return m_config; } - virtual ~Context() override; + ~Context() override; public: // IMutableContext - virtual void setResultCapture( IResultCapture* resultCapture ) override { + void setResultCapture( IResultCapture* resultCapture ) override { m_resultCapture = resultCapture; } - virtual void setRunner( IRunner* runner ) override { + void setRunner( IRunner* runner ) override { m_runner = runner; } - virtual void setConfig( IConfigPtr const& config ) override { + void setConfig( IConfigPtr const& config ) override { m_config = config; } @@ -8402,19 +8419,23 @@ namespace Catch { # include # include # include -# include # include # include -namespace Catch { +#ifdef __apple_build_version__ + // These headers will only compile with AppleClang (XCode) + // For other compilers (Clang, GCC, ... ) we need to exclude them +# include +#endif + namespace Catch { + #ifdef __apple_build_version__ // The following function is taken directly from the following technical note: - // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + // https://developer.apple.com/library/archive/qa/qa1361/_index.html // Returns true if the current process is being debugged (either // running under the debugger or has a debugger attached post facto). bool isDebuggerActive(){ - int mib[4]; struct kinfo_proc info; std::size_t size; @@ -8444,6 +8465,12 @@ namespace Catch { return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); } + #else + bool isDebuggerActive() { + // We need to find another way to determine this for non-appleclang compilers on macOS + return false; + } + #endif } // namespace Catch #elif defined(CATCH_PLATFORM_LINUX) @@ -8548,7 +8575,7 @@ namespace Catch { public: ~ExceptionTranslatorRegistry(); virtual void registerTranslator( const IExceptionTranslator* translator ); - virtual std::string translateActiveException() const override; + std::string translateActiveException() const override; std::string tryTranslators() const; private: @@ -8660,10 +8687,10 @@ namespace Catch { // Windows can easily distinguish between SO and SigSegV, // but SigInt, SigTerm, etc are handled differently. static SignalDefs signalDefs[] = { - { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, - { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, - { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, - { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, + { static_cast(EXCEPTION_ILLEGAL_INSTRUCTION), "SIGILL - Illegal instruction signal" }, + { static_cast(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow" }, + { static_cast(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal" }, + { static_cast(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" }, }; LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { @@ -9821,7 +9848,7 @@ namespace Catch { if (strerror_s(buffer, errno)) { CATCH_RUNTIME_ERROR("Could not translate errno to a string"); } - CATCH_RUNTIME_ERROR("Coul dnot open the temp file: '" << m_buffer << "' because: " << buffer); + CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer); } } #else @@ -10899,7 +10926,10 @@ namespace Catch { auto const& allTestCases = getAllTestCasesSorted(*config); for (auto const& testCase : allTestCases) { - if (!context.aborting() && matchTest(testCase, testSpec, *config)) + bool matching = (!testSpec.hasFilters() && !testCase.isHidden()) || + (testSpec.hasFilters() && matchTest(testCase, testSpec, *config)); + + if (!context.aborting() && matching) totals += context.runTest(testCase); else context.reporter().skipTest(testCase); @@ -11625,7 +11655,7 @@ namespace Catch { void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { CATCH_ENFORCE( !isReservedTag(tag), "Tag name: [" << tag << "] is not allowed.\n" - << "Tag names starting with non alpha-numeric characters are reserved\n" + << "Tag names starting with non alphanumeric characters are reserved\n" << _lineInfo ); } } @@ -11657,6 +11687,12 @@ namespace Catch { else if( prop == TestCaseInfo::None ) enforceNotReservedTag( tag, _lineInfo ); + // Merged hide tags like `[.approvals]` should be added as + // `[.][approvals]`. The `[.]` is added at later point, so + // we only strip the prefix + if (startsWith(tag, '.') && tag.size() > 1) { + tag.erase(0, 1); + } tags.push_back( tag ); tag.clear(); inTag = false; @@ -11801,9 +11837,12 @@ namespace Catch { std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { std::vector filtered; filtered.reserve( testCases.size() ); - for( auto const& testCase : testCases ) - if( matchTest( testCase, testSpec, config ) ) - filtered.push_back( testCase ); + for (auto const& testCase : testCases) { + if ((!testSpec.hasFilters() && !testCase.isHidden()) || + (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) { + filtered.push_back(testCase); + } + } return filtered; } std::vector const& getAllTestCasesSorted( IConfig const& config ) { @@ -11879,11 +11918,6 @@ namespace TestCaseTracking { ITracker::~ITracker() = default; - TrackerContext& TrackerContext::instance() { - static TrackerContext s_instance; - return s_instance; - } - ITracker& TrackerContext::startRun() { m_rootTracker = std::make_shared( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); m_currentTracker = nullptr; @@ -12665,7 +12699,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 7, 0, "", 0 ); + static Version version( 2, 7, 2, "", 0 ); return version; } @@ -13022,6 +13056,21 @@ namespace Catch { return std::string(buffer); } + std::string serializeFilters( std::vector const& container ) { + ReusableStringStream oss; + bool first = true; + for (auto&& filter : container) + { + if (!first) + oss << ' '; + else + first = false; + + oss << filter; + } + return oss.str(); + } + TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) :StreamingReporterBase(_config) {} @@ -13746,6 +13795,10 @@ void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) { stream << std::endl; StreamingReporterBase::testRunEnded(_testRunStats); } +void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) { + StreamingReporterBase::testRunStarting(_testInfo); + printTestFilters(); +} void ConsoleReporter::lazyPrint() { @@ -13927,6 +13980,11 @@ void ConsoleReporter::printSummaryDivider() { stream << getLineOfChars<'-'>() << '\n'; } +void ConsoleReporter::printTestFilters() { + if (m_config->testSpec().hasFilters()) + stream << Colour(Colour::BrightYellow) << "Filters: " << serializeFilters( m_config->getTestsOrTags() ) << '\n'; +} + CATCH_REGISTER_REPORTER("console", ConsoleReporter) } // end namespace Catch @@ -14000,13 +14058,6 @@ namespace Catch { void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) { CumulativeReporterBase::testRunStarting( runInfo ); xml.startElement( "testsuites" ); - if( m_config->rngSeed() != 0 ) { - xml.startElement( "properties" ); - xml.scopedElement( "property" ) - .writeAttribute( "name", "random-seed" ) - .writeAttribute( "value", m_config->rngSeed() ); - xml.endElement(); - } } void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) { @@ -14045,6 +14096,7 @@ namespace Catch { void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) { XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; xml.writeAttribute( "name", stats.groupInfo.name ); xml.writeAttribute( "errors", unexpectedExceptions ); @@ -14057,6 +14109,21 @@ namespace Catch { xml.writeAttribute( "time", suiteTime ); xml.writeAttribute( "timestamp", getCurrentTimestamp() ); + // Write properties if there are any + if (m_config->hasTestFilters() || m_config->rngSeed() != 0) { + auto properties = xml.scopedElement("properties"); + if (m_config->hasTestFilters()) { + xml.scopedElement("property") + .writeAttribute("name", "filters") + .writeAttribute("value", serializeFilters(m_config->getTestsOrTags())); + } + if (m_config->rngSeed() != 0) { + xml.scopedElement("property") + .writeAttribute("name", "random-seed") + .writeAttribute("value", m_config->rngSeed()); + } + } + // Write test cases for( auto const& child : groupNode.children ) writeTestCase( *child ); @@ -14357,6 +14424,8 @@ namespace Catch { m_xml.startElement( "Catch" ); if( !m_config->name().empty() ) m_xml.writeAttribute( "name", m_config->name() ); + if (m_config->testSpec().hasFilters()) + m_xml.writeAttribute( "filters", serializeFilters( m_config->getTestsOrTags() ) ); if( m_config->rngSeed() != 0 ) m_xml.scopedElement( "Randomness" ) .writeAttribute( "seed", m_config->rngSeed() );