diff options
| author | Martin Hořeňovský | 2026-02-15 22:55:48 +0100 |
|---|---|---|
| committer | Martin Hořeňovský | 2026-02-15 22:55:48 +0100 |
| commit | 29c9844f688acb27c87338c39cd186ebfe41aa19 (patch) | |
| tree | 82526279e11e38f055605e0dcdbfc04ebfe63752 /extras | |
| parent | 56024c04e42172d53a1672b9af6a538afdb79801 (diff) | |
| download | catch3-3.13.0.tar.gz | |
v3.13.0v3.13.0
Diffstat (limited to 'extras')
| -rw-r--r-- | extras/catch_amalgamated.cpp | 324 | ||||
| -rw-r--r-- | extras/catch_amalgamated.hpp | 320 |
2 files changed, 505 insertions, 139 deletions
diff --git a/extras/catch_amalgamated.cpp b/extras/catch_amalgamated.cpp index a4406d0c..adafc64b 100644 --- a/extras/catch_amalgamated.cpp +++ b/extras/catch_amalgamated.cpp @@ -6,8 +6,8 @@ // SPDX-License-Identifier: BSL-1.0 -// Catch v3.12.0 -// Generated: 2025-12-28 22:27:25.828797 +// Catch v3.13.0 +// Generated: 2026-02-15 22:55:00.269529 // ---------------------------------------------------------- // This file is an amalgamation of multiple different files. // You probably shouldn't edit it directly. @@ -798,6 +798,10 @@ namespace Catch { lhs.customOptions == rhs.customOptions; } + bool operator==( PathFilter const& lhs, PathFilter const& rhs ) { + return lhs.type == rhs.type && lhs.filter == rhs.filter; + } + Config::Config( ConfigData const& data ): m_data( data ) { // We need to trim filter specs to avoid trouble with superfluous @@ -807,9 +811,6 @@ namespace Catch { for (auto& elem : m_data.testsOrTags) { elem = trim(elem); } - for (auto& elem : m_data.sectionsToRun) { - elem = trim(elem); - } // Insert the default reporter if user hasn't asked for a specific one if ( m_data.reporterSpecifications.empty() ) { @@ -875,7 +876,8 @@ namespace Catch { bool Config::listListeners() const { return m_data.listListeners; } std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; } - std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } + std::vector<PathFilter> const& Config::getPathFilters() const { return m_data.pathFilters; } + bool Config::useNewFilterBehaviour() const { return m_data.useNewPathFilteringBehaviour; } std::vector<ReporterSpec> const& Config::getReporterSpecs() const { return m_data.reporterSpecifications; @@ -903,6 +905,9 @@ namespace Catch { bool Config::warnAboutUnmatchedTestSpecs() const { return !!( m_data.warnings & WarnAbout::UnmatchedTestSpec ); } + bool Config::warnAboutInfiniteGenerators() const { + return !!( m_data.warnings & WarnAbout::InfiniteGenerator ); + } bool Config::zeroTestsCountAsSuccess() const { return m_data.allowZeroTests; } ShowDurations Config::showDurations() const { return m_data.showDurations; } double Config::minDuration() const { return m_data.minDuration; } @@ -1018,7 +1023,9 @@ namespace Catch { Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, - StringRef names ) { + StringRef names, + bool isScoped): + m_isScoped(isScoped) { auto trimmed = [&] (size_t start, size_t end) { while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) { ++start; @@ -1079,15 +1086,21 @@ namespace Catch { } Capturer::~Capturer() { assert( m_captured == m_messages.size() ); - for (auto const& message : m_messages) { - IResultCapture::popScopedMessage( message.sequence ); + if ( m_isScoped ) { + for ( auto const& message : m_messages ) { + IResultCapture::popScopedMessage( message.sequence ); + } } } void Capturer::captureValue( size_t index, std::string const& value ) { assert( index < m_messages.size() ); m_messages[index].message += value; - IResultCapture::pushScopedMessage( CATCH_MOVE( m_messages[index] ) ); + if ( m_isScoped ) { + IResultCapture::pushScopedMessage( CATCH_MOVE( m_messages[index] ) ); + } else { + IResultCapture::addUnscopedMessage( CATCH_MOVE( m_messages[index] ) ); + } m_captured++; } @@ -2384,7 +2397,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 3, 12, 0, "", 0 ); + static Version version( 3, 13, 0, "", 0 ); return version; } @@ -2410,14 +2423,6 @@ namespace Catch { namespace Generators { -namespace Detail { - - [[noreturn]] - void throw_generator_exception(char const* msg) { - Catch::throw_exception(GeneratorException{ msg }); - } -} // end namespace Detail - GeneratorUntypedBase::~GeneratorUntypedBase() = default; IGeneratorTracker* acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo ) { @@ -2465,6 +2470,27 @@ namespace Catch { m_current_number = m_pimpl->dist( m_pimpl->rng ); return true; } + + bool RandomFloatingGenerator<long double>::isFinite() const { + return false; + } + + } // namespace Generators +} // namespace Catch + + + + +namespace Catch { + namespace Generators { + namespace Detail { + + [[noreturn]] + void throw_generator_exception( char const* msg ) { + Catch::throw_exception( GeneratorException{ msg } ); + } + + } // namespace Detail } // namespace Generators } // namespace Catch @@ -2498,6 +2524,7 @@ namespace Catch { + #include <string> namespace Catch { @@ -2512,6 +2539,31 @@ namespace Catch { return ret; } + void GeneratorUntypedBase::skipToNthElementImpl( std::size_t n ) { + for ( size_t i = m_currentElementIndex; i < n; ++i ) { + bool isValid = next(); + if ( !isValid ) { + Detail::throw_generator_exception( + "Coud not jump to Nth element: not enough elements" ); + } + } + } + + void GeneratorUntypedBase::skipToNthElement( std::size_t n ) { + if ( n < m_currentElementIndex ) { + Detail::throw_generator_exception( + "Tried to jump generator backwards" ); + } + if ( n == m_currentElementIndex ) { return; } + + skipToNthElementImpl(n); + // Fixup tracking after moving the generator forward + // * Ensure that the correct element index is set after skipping + // * Invalidate cache + m_currentElementIndex = n; + m_stringReprCache.clear(); + } + StringRef GeneratorUntypedBase::currentElementAsString() const { if ( m_stringReprCache.empty() ) { m_stringReprCache = stringifyImpl(); @@ -2519,6 +2571,8 @@ namespace Catch { return m_stringReprCache; } + bool GeneratorUntypedBase::isFinite() const { return true; } + } // namespace Generators } // namespace Catch @@ -3199,6 +3253,9 @@ namespace Catch { } else if ( warning == "UnmatchedTestSpec" ) { config.warnings = static_cast<WarnAbout::What>(config.warnings | WarnAbout::UnmatchedTestSpec); return ParserResult::ok( ParseResultType::Matched ); + } else if ( warning == "InfiniteGenerators" ) { + config.warnings = static_cast<WarnAbout::What>(config.warnings | WarnAbout::InfiniteGenerator); + return ParserResult::ok( ParseResultType::Matched ); } return ParserResult ::runtimeError( @@ -3356,6 +3413,19 @@ namespace Catch { config.shardCount = *parsedCount; return ParserResult::ok( ParseResultType::Matched ); }; + auto const setBenchmarkSamples = [&]( std::string const& samples ) { + auto parsedSamples = parseUInt( samples ); + if ( !parsedSamples ) { + return ParserResult::runtimeError( + "Could not parse '" + samples + "' as benchmark samples" ); + } + if ( *parsedSamples == 0 ) { + return ParserResult::runtimeError( + "Benchmark samples must be greater than 0" ); + } + config.benchmarkSamples = *parsedSamples; + return ParserResult::ok( ParseResultType::Matched ); + }; auto const setShardIndex = [&](std::string const& shardIndex) { auto parsedIndex = parseUInt( shardIndex ); @@ -3367,6 +3437,43 @@ namespace Catch { return ParserResult::ok( ParseResultType::Matched ); }; + auto const setSectionFilter = [&]( std::string const& sectionFilter ) { + config.pathFilters.emplace_back( PathFilter::For::Section, trim(sectionFilter) ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setGeneratorFilter = [&]( std::string const& generatorFilter ) { + if (generatorFilter != "*") { + // TODO: avoid re-parsing the index? + auto parsedIndex = parseUInt( generatorFilter ); + if ( !parsedIndex ) { + return ParserResult::runtimeError( "Could not parse '" + + generatorFilter + + "' as generator index" ); + } + } + config.useNewPathFilteringBehaviour = true; + config.pathFilters.emplace_back( PathFilter::For::Generator, trim(generatorFilter) ); + return ParserResult::ok( ParseResultType::Matched ); + }; + // Copy-capturing other `setFoo` functions enables calling them later, + // as the config ref remains valid, but the local lambda vars won't. + auto const setPathFilter = [=, &config]( std::string const& pathFilter ) { + config.useNewPathFilteringBehaviour = true; + if ( pathFilter.size() < 3 ) { + return ParserResult::runtimeError( + "Path filter '" + pathFilter + "' is too short" ); + } + if ( startsWith( pathFilter, "g:" ) ) { + return setGeneratorFilter( pathFilter.substr( 2 ) ); + } + if ( startsWith( pathFilter, "c:" ) ) { + return setSectionFilter( pathFilter.substr( 2 ) ); + } + return ParserResult::runtimeError( "Path filter '" + pathFilter + + "' has unknown type prefix" ); + }; + + auto cli = ExeName( config.processName ) | Help( config.showHelp ) @@ -3412,9 +3519,15 @@ namespace Catch { | Opt( config.filenamesAsTags ) ["-#"]["--filenames-as-tags"] ( "adds a tag for the filename" ) - | Opt( config.sectionsToRun, "section name" ) + | Opt( accept_many, setSectionFilter, "section name" ) ["-c"]["--section"] ( "specify section to run" ) + | Opt( accept_many, setGeneratorFilter, "index spec" ) + ["-g"]["--generator-index"] + ( "specify generator elements to try" ) + | Opt( accept_many, setPathFilter, "path filter spec" ) + ["-p"]["--path-filter"] + ( "qualified path filter" ) | Opt( setVerbosity, "quiet|normal|high" ) ["-v"]["--verbosity"] ( "set output verbosity" ) @@ -3448,7 +3561,7 @@ namespace Catch { | Opt( config.skipBenchmarks) ["--skip-benchmarks"] ( "disable running benchmarks") - | Opt( config.benchmarkSamples, "samples" ) + | Opt( setBenchmarkSamples, "samples" ) ["--benchmark-samples"] ( "number of samples to collect (default: 100)" ) | Opt( config.benchmarkResamples, "resamples" ) @@ -5752,12 +5865,46 @@ namespace Catch { struct GeneratorTracker final : TestCaseTracking::TrackerBase, IGeneratorTracker { GeneratorBasePtr m_generator; + // Filtered generator has moved to specific index due to + // a filter, it needs special handling of `countedNext()` + bool m_isFiltered = false; GeneratorTracker( TestCaseTracking::NameAndLocation&& nameAndLocation, TrackerContext& ctx, - ITracker* parent ): - TrackerBase( CATCH_MOVE( nameAndLocation ), ctx, parent ) {} + ITracker* parent, + GeneratorBasePtr&& generator ): + TrackerBase( CATCH_MOVE( nameAndLocation ), ctx, parent ), + m_generator( CATCH_MOVE( generator ) ) { + assert( m_generator && + "Cannot create tracker without generator" ); + + // Handle potential filter and move forward here... + // Old style filters do not affect generators at all + if (m_newStyleFilters && m_allTrackerDepth < m_filterRef->size()) { + auto const& filter = + ( *m_filterRef )[m_allTrackerDepth]; + // Generator cannot be un-entered the way a section + // can be, so the tracker has to throw for a wrong + // filter to stop the execution flow. + if (filter.type == PathFilter::For::Section) { + // TBD: Explicit SKIP, or new exception that says + // "don't continue", but doesn't show in totals? + SKIP(); + } + // '*' is the wildcard for "all elements in generator" + // used for filtering sections below the generator, but + // not the generator itself. + if ( filter.filter != "*" ) { + m_isFiltered = true; + // TBD: We assume that the filter was validated as + // number during parsing. We should pass it + // as number from the CLI parser. + size_t targetIndex = std::stoul( filter.filter ); + m_generator->skipToNthElement( targetIndex ); + } + } + } static GeneratorTracker* acquire( TrackerContext& ctx, @@ -5801,9 +5948,6 @@ namespace Catch { // TrackerBase interface bool isGeneratorTracker() const override { return true; } - auto hasGenerator() const -> bool override { - return !!m_generator; - } void close() override { TrackerBase::close(); // If a generator has a child (it is followed by a section) @@ -5832,25 +5976,24 @@ namespace Catch { // _can_ start, and thus we should wait for them, or // they cannot start (due to filters), and we shouldn't // wait for them - ITracker* parent = m_parent; - // This is safe: there is always at least one section - // tracker in a test case tracking tree - while ( !parent->isSectionTracker() ) { - parent = parent->parent(); - } - assert( parent && - "Missing root (test case) level section" ); - auto const& parentSection = - static_cast<SectionTracker const&>( *parent ); - auto const& filters = parentSection.getFilters(); - // No filters -> no restrictions on running sections - if ( filters.empty() ) { return true; } + // No filters left -> no restrictions on running sections + size_t childDepth = 1 + (m_newStyleFilters ? m_allTrackerDepth : m_sectionOnlyDepth); + if ( childDepth >= m_filterRef->size() ) { + return true; + } + // If we are using the new style filters, we need to check + // whether the successive filter is for section or a generator. + if ( m_newStyleFilters + && (*m_filterRef)[childDepth].type != PathFilter::For::Section ) { + return false; + } + // Look for any child section that could match the remaining filters for ( auto const& child : m_children ) { if ( child->isSectionTracker() && static_cast<SectionTracker const&>( *child ) - .trimmedName() == filters[0] ) { + .trimmedName() == StringRef((*m_filterRef)[childDepth].filter) ) { return true; } } @@ -5862,9 +6005,10 @@ namespace Catch { // value, but we do not want to invoke the side-effect if // this generator is still waiting for any child to start. assert( m_generator && "Tracker without generator" ); - if ( should_wait_for_child || - ( m_runState == CompletedSuccessfully && - m_generator->countedNext() ) ) { + if ( should_wait_for_child + || ( m_runState == CompletedSuccessfully + && !m_isFiltered // filtered generators cannot meaningfully move forward, as they would get past the filter + && m_generator->countedNext() ) ) { m_children.clear(); m_runState = Executing; } @@ -5874,9 +6018,6 @@ namespace Catch { auto getGenerator() const -> GeneratorBasePtr const& override { return m_generator; } - void setGenerator( GeneratorBasePtr&& generator ) override { - m_generator = CATCH_MOVE( generator ); - } }; } // namespace } @@ -5930,13 +6071,16 @@ namespace Catch { // we only keep around the raw msg ids. ~MessageHolder() = default; + void addUnscopedMessage( MessageInfo&& info ) { + repairUnscopedMessageInvariant(); + unscoped_ids.push_back( info.sequence ); + messages.push_back( CATCH_MOVE( info ) ); + } void addUnscopedMessage(MessageBuilder&& builder) { - repairUnscopedMessageInvariant(); MessageInfo info( CATCH_MOVE( builder.m_info ) ); info.message = builder.m_stream.str(); - unscoped_ids.push_back( info.sequence ); - messages.push_back( CATCH_MOVE( info ) ); + addUnscopedMessage( CATCH_MOVE( info ) ); } void addScopedMessage(MessageInfo&& info) { @@ -6027,7 +6171,8 @@ namespace Catch { ITracker& rootTracker = m_trackerContext.startRun(); assert(rootTracker.isSectionTracker()); - static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun()); + rootTracker.setFilters( &m_config->getPathFilters(), + m_config->useNewFilterBehaviour() ); // We intentionally only seed the internal RNG once per test case, // before it is first invoked. The reason for that is a complex @@ -6199,18 +6344,28 @@ namespace Catch { SourceLineInfo lineInfo, Generators::GeneratorBasePtr&& generator ) { + // TBD: Do we want to avoid the warning if the generator is filtered? + if ( m_config->warnAboutInfiniteGenerators() && + !generator->isFinite() ) { + // TBD: Would it be better to expand this macro inline? + FAIL( "GENERATE() would run infinitely" ); + } + auto nameAndLoc = TestCaseTracking::NameAndLocation( static_cast<std::string>( generatorName ), lineInfo ); auto& currentTracker = m_trackerContext.currentTracker(); assert( currentTracker.nameAndLocation() != nameAndLoc && "Trying to create tracker for a generator that already has one" ); - auto newTracker = Catch::Detail::make_unique<Generators::GeneratorTracker>( - CATCH_MOVE(nameAndLoc), m_trackerContext, ¤tTracker ); + auto newTracker = + Catch::Detail::make_unique<Generators::GeneratorTracker>( + CATCH_MOVE( nameAndLoc ), + m_trackerContext, + ¤tTracker, + CATCH_MOVE( generator ) ); auto ret = newTracker.get(); currentTracker.addChild( CATCH_MOVE( newTracker ) ); - ret->setGenerator( CATCH_MOVE( generator ) ); ret->open(); return ret; } @@ -6613,6 +6768,10 @@ namespace Catch { Detail::g_messageHolder().addUnscopedMessage( CATCH_MOVE( builder ) ); } + void IResultCapture::addUnscopedMessage( MessageInfo&& message ) { + Detail::g_messageHolder().addUnscopedMessage( CATCH_MOVE( message ) ); + } + void seedRng(IConfig const& config) { sharedRng().seed(config.rngSeed()); } @@ -7171,6 +7330,17 @@ namespace TestCaseTracking { location( _location ) {} + ITracker::ITracker( NameAndLocation&& nameAndLoc, ITracker* parent ): + m_nameAndLocation( CATCH_MOVE( nameAndLoc ) ), m_parent( parent ) { + if ( m_parent ) { + m_allTrackerDepth = m_parent->m_allTrackerDepth + 1; + // We leave section trackers to bump themselves up, as + // we cannot use `isSectionTracker` in constructor + m_sectionOnlyDepth = m_parent->m_sectionOnlyDepth; + m_filterRef = m_parent->m_filterRef; + m_newStyleFilters = m_parent->m_newStyleFilters; + } + } ITracker::~ITracker() = default; @@ -7303,25 +7473,32 @@ namespace TestCaseTracking { : TrackerBase( CATCH_MOVE(nameAndLocation), ctx, parent ), m_trimmed_name(trim(StringRef(ITracker::nameAndLocation().name))) { - if( parent ) { - while ( !parent->isSectionTracker() ) { - parent = parent->parent(); - } - - SectionTracker& parentSection = static_cast<SectionTracker&>( *parent ); - addNextFilters( parentSection.m_filters ); + if( m_parent ) { + ++m_sectionOnlyDepth; } } bool SectionTracker::isComplete() const { - bool complete = true; - - if ( m_filters.empty() - || m_filters[0].empty() - || m_filters[0] == m_trimmed_name ) { - complete = TrackerBase::isComplete(); + // If there are active filters AND we do not pass them, + // the section is always "completed" + const size_t filterIndex = + m_newStyleFilters ? m_allTrackerDepth : m_sectionOnlyDepth; + if ( filterIndex < m_filterRef->size() ) { + // There is active filter, check it + // 1) New style filter must explicitly target section + if ( m_newStyleFilters && ( *m_filterRef )[filterIndex].type != + PathFilter::For::Section ) { + return true; + } + // 2) Both style filters must match the trimmed name exactly + if ( m_trimmed_name != + StringRef( ( *m_filterRef )[filterIndex].filter ) ) { + return true; + } } - return complete; + + // Otherwise we delegate to the generic processing + return TrackerBase::isComplete(); } bool SectionTracker::isSectionTracker() const { return true; } @@ -7357,19 +7534,6 @@ namespace TestCaseTracking { open(); } - void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) { - if( !filters.empty() ) { - m_filters.reserve( m_filters.size() + filters.size() + 2 ); - m_filters.emplace_back(StringRef{}); // Root - should never be consulted - m_filters.emplace_back(StringRef{}); // Test Case - not a section filter - m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); - } - } - void SectionTracker::addNextFilters( std::vector<StringRef> const& filters ) { - if( filters.size() > 1 ) - m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() ); - } - StringRef SectionTracker::trimmedName() const { return m_trimmed_name; } diff --git a/extras/catch_amalgamated.hpp b/extras/catch_amalgamated.hpp index 00fc3ee1..6de74f80 100644 --- a/extras/catch_amalgamated.hpp +++ b/extras/catch_amalgamated.hpp @@ -6,8 +6,8 @@ // SPDX-License-Identifier: BSL-1.0 -// Catch v3.12.0 -// Generated: 2025-12-28 22:27:25.408132 +// Catch v3.13.0 +// Generated: 2026-02-15 22:54:59.817776 // ---------------------------------------------------------- // This file is an amalgamation of multiple different files. // You probably shouldn't edit it directly. @@ -299,7 +299,7 @@ //////////////////////////////////////////////////////////////////////////////// // Visual C++ -#if defined(_MSC_VER) +#if defined(_MSC_VER) && !defined(__clang__) // We want to defer to nvcc-specific warning suppression if we are compiled // with nvcc masquerading for MSVC. @@ -310,6 +310,11 @@ __pragma( warning( pop ) ) # endif +// Suppress MSVC C++ Core Guidelines checker warning 26426: +// "Global initializer calls a non-constexpr function (i.22)" +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + __pragma( warning( disable : 26426 ) ) + // Universal Windows platform does not support SEH # if !defined(CATCH_PLATFORM_WINDOWS_UWP) # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH @@ -1033,7 +1038,7 @@ namespace Catch { // We cannot forward declare the type with default template argument // multiple times, so it is split out into a separate header so that - // we can prevent multiple declarations in dependees + // we can prevent multiple declarations in dependencies template <typename Duration = Benchmark::FDuration> struct BenchmarkStats; @@ -1090,6 +1095,7 @@ namespace Catch { static void pushScopedMessage( MessageInfo&& message ); static void popScopedMessage( unsigned int messageId ); + static void addUnscopedMessage( MessageInfo&& message ); static void emplaceUnscopedMessage( MessageBuilder&& builder ); virtual void handleFatalErrorCondition( StringRef message ) = 0; @@ -1189,6 +1195,8 @@ namespace Catch { NoAssertions = 0x01, //! A command line test spec matched no test cases UnmatchedTestSpec = 0x02, + //! The resulting generator in GENERATE is infinite + InfiniteGenerator = 0x04, }; }; enum class ShowDurations { @@ -1220,6 +1228,7 @@ namespace Catch { class TestSpec; class IStream; + struct PathFilter; class IConfig : public Detail::NonCopyable { public: @@ -1231,6 +1240,7 @@ namespace Catch { virtual bool shouldDebugBreak() const = 0; virtual bool warnAboutMissingAssertions() const = 0; virtual bool warnAboutUnmatchedTestSpecs() const = 0; + virtual bool warnAboutInfiniteGenerators() const = 0; virtual bool zeroTestsCountAsSuccess() const = 0; virtual int abortAfter() const = 0; virtual bool showInvisibles() const = 0; @@ -1244,7 +1254,9 @@ namespace Catch { virtual unsigned int shardCount() const = 0; virtual unsigned int shardIndex() const = 0; virtual ColourMode defaultColourMode() const = 0; - virtual std::vector<std::string> const& getSectionsToRun() const = 0; + virtual std::vector<PathFilter> const& getPathFilters() const = 0; + virtual bool useNewFilterBehaviour() const = 0; + virtual Verbosity verbosity() const = 0; virtual bool skipBenchmarks() const = 0; @@ -3630,6 +3642,33 @@ namespace Catch { #endif // CATCH_OPTIONAL_HPP_INCLUDED +#ifndef CATCH_PATH_FILTER_HPP_INCLUDED +#define CATCH_PATH_FILTER_HPP_INCLUDED + + +#include <string> + +namespace Catch { + + struct PathFilter { + enum class For { + Section, + Generator, + }; + PathFilter( For type_, std::string filter_ ): + type( type_ ), filter( CATCH_MOVE( filter_ ) ) {} + + For type; + std::string filter; + + friend bool operator==( PathFilter const& lhs, PathFilter const& rhs ); + }; + +} // end namespace Catch + +#endif // CATCH_PATH_FILTER_HPP_INCLUDED + + #ifndef CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED #define CATCH_RANDOM_SEED_GENERATION_HPP_INCLUDED @@ -3797,7 +3836,8 @@ namespace Catch { std::vector<ReporterSpec> reporterSpecifications; std::vector<std::string> testsOrTags; - std::vector<std::string> sectionsToRun; + std::vector<PathFilter> pathFilters; + bool useNewPathFilteringBehaviour = false; std::string prematureExitGuardFilePath; }; @@ -3820,7 +3860,8 @@ namespace Catch { getProcessedReporterSpecs() const; std::vector<std::string> const& getTestsOrTags() const override; - std::vector<std::string> const& getSectionsToRun() const override; + std::vector<PathFilter> const& getPathFilters() const override; + bool useNewFilterBehaviour() const override; TestSpec const& testSpec() const override; bool hasTestFilters() const override; @@ -3835,6 +3876,7 @@ namespace Catch { bool includeSuccessfulResults() const override; bool warnAboutMissingAssertions() const override; bool warnAboutUnmatchedTestSpecs() const override; + bool warnAboutInfiniteGenerators() const override; bool zeroTestsCountAsSuccess() const override; ShowDurations showDurations() const override; double minDuration() const override; @@ -3943,9 +3985,9 @@ namespace Catch { #if !defined( CATCH_CONFIG_NO_DEPRECATION_ANNOTATIONS ) -# define DEPRECATED( msg ) [[deprecated( msg )]] +# define CATCH_DEPRECATED( msg ) [[deprecated( msg )]] #else -# define DEPRECATED( msg ) +# define CATCH_DEPRECATED( msg ) #endif #endif // CATCH_DEPRECATION_MACRO_HPP_INCLUDED @@ -3966,11 +4008,11 @@ namespace Catch { // The "ID" of the message, used to know when to remove it from reporter context. unsigned int sequence; - DEPRECATED( "Explicitly use the 'sequence' member instead" ) + CATCH_DEPRECATED( "Explicitly use the 'sequence' member instead" ) bool operator == (MessageInfo const& other) const { return sequence == other.sequence; } - DEPRECATED( "Explicitly use the 'sequence' member instead" ) + CATCH_DEPRECATED( "Explicitly use the 'sequence' member instead" ) bool operator < (MessageInfo const& other) const { return sequence < other.sequence; } @@ -4028,8 +4070,9 @@ namespace Catch { class Capturer { std::vector<MessageInfo> m_messages; size_t m_captured = 0; + bool m_isScoped = false; public: - Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); + Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names, bool isScoped ); Capturer(Capturer const&) = delete; Capturer& operator=(Capturer const&) = delete; @@ -4061,11 +4104,12 @@ namespace Catch { } while( false ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ - Catch::Capturer varName( macroName##_catch_sr, \ - CATCH_INTERNAL_LINEINFO, \ - Catch::ResultWas::Info, \ - #__VA_ARGS__##_catch_sr ); \ +#define INTERNAL_CATCH_CAPTURE( varName, macroName, scopedCapture, ... ) \ + Catch::Capturer varName( macroName##_catch_sr, \ + CATCH_INTERNAL_LINEINFO, \ + Catch::ResultWas::Info, \ + #__VA_ARGS__##_catch_sr, \ + scopedCapture ); \ varName.captureValues( 0, __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// @@ -4082,28 +4126,32 @@ namespace Catch { #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) - #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__ ) + #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", true, __VA_ARGS__ ) + #define CATCH_UNSCOPED_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_UNSCOPED_CAPTURE", false, __VA_ARGS__ ) #elif defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE) - #define CATCH_INFO( msg ) (void)(0) - #define CATCH_UNSCOPED_INFO( msg ) (void)(0) - #define CATCH_WARN( msg ) (void)(0) - #define CATCH_CAPTURE( ... ) (void)(0) + #define CATCH_INFO( msg ) (void)(0) + #define CATCH_UNSCOPED_INFO( msg ) (void)(0) + #define CATCH_WARN( msg ) (void)(0) + #define CATCH_CAPTURE( ... ) (void)(0) + #define CATCH_UNSCOPED_CAPTURE( ... ) (void)(0) #elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE) #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) - #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__ ) + #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", true, __VA_ARGS__ ) + #define UNSCOPED_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "UNSCOPED_CAPTURE", false, __VA_ARGS__ ) #elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE) - #define INFO( msg ) (void)(0) - #define UNSCOPED_INFO( msg ) (void)(0) - #define WARN( msg ) (void)(0) - #define CAPTURE( ... ) (void)(0) + #define INFO( msg ) (void)(0) + #define UNSCOPED_INFO( msg ) (void)(0) + #define WARN( msg ) (void)(0) + #define CAPTURE( ... ) (void)(0) + #define UNSCOPED_CAPTURE( ... ) (void)(0) #endif // end of user facing macro declarations @@ -7466,7 +7514,7 @@ namespace Catch { #define CATCH_VERSION_MACROS_HPP_INCLUDED #define CATCH_VERSION_MAJOR 3 -#define CATCH_VERSION_MINOR 12 +#define CATCH_VERSION_MINOR 13 #define CATCH_VERSION_PATCH 0 #endif // CATCH_VERSION_MACROS_HPP_INCLUDED @@ -7521,6 +7569,24 @@ namespace Catch { +#ifndef CATCH_GENERATORS_THROW_HPP_INCLUDED +#define CATCH_GENERATORS_THROW_HPP_INCLUDED + +namespace Catch { + namespace Generators { + namespace Detail { + + //! Throws GeneratorException with the provided message + [[noreturn]] |