mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 05:59:32 +01:00 
			
		
		
		
	Compare commits
	
		
			9 Commits
		
	
	
		
			v3.11.0
			...
			devel-gene
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					b4a98791d5 | ||
| 
						 | 
					49d79e9e9c | ||
| 
						 | 
					33e6fd217a | ||
| 
						 | 
					a58df2d7c5 | ||
| 
						 | 
					a9223b2bb3 | ||
| 
						 | 
					363ca5af18 | ||
| 
						 | 
					cb6d713774 | ||
| 
						 | 
					8e4ab5dd8f | ||
| 
						 | 
					8219ed79f2 | 
@@ -252,9 +252,23 @@ struct IGenerator : GeneratorUntypedBase {
 | 
			
		||||
    // Returns user-friendly string showing the current generator element
 | 
			
		||||
    // Does not have to be overridden, IGenerator provides default implementation
 | 
			
		||||
    virtual std::string stringifyImpl() const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Customization point for `skipToNthElement`
 | 
			
		||||
     *
 | 
			
		||||
     * Does not have to be overridden, there is a default implementation.
 | 
			
		||||
     * Can be overridden for better performance.
 | 
			
		||||
     *
 | 
			
		||||
     * If there are not enough elements, shall throw an error.
 | 
			
		||||
     *
 | 
			
		||||
     * Going backwards is not supported.
 | 
			
		||||
     */
 | 
			
		||||
    virtual void skipToNthElementImpl( std::size_t n );
 | 
			
		||||
};
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
> `skipToNthElementImpl` was added in Catch2 vX.Y.Z
 | 
			
		||||
 | 
			
		||||
However, to be able to use your custom generator inside `GENERATE`, it
 | 
			
		||||
will need to be wrapped inside a `GeneratorWrapper<T>`.
 | 
			
		||||
`GeneratorWrapper<T>` is a value wrapper around a
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,22 @@ public:
 | 
			
		||||
        current_number = m_dist(m_rand);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Note: this improves the performance only a bit, but it is here
 | 
			
		||||
    //       to show how you can override the skip functionality.
 | 
			
		||||
    void skipToNthElementImpl( std::size_t n ) override {
 | 
			
		||||
        auto current_index = currentElementIndex();
 | 
			
		||||
        assert(current_index <= n);
 | 
			
		||||
        // We cannot jump forward the underlying generator directly,
 | 
			
		||||
        // because we do not know how many bits each distributed number
 | 
			
		||||
        // would consume to be generated.
 | 
			
		||||
        for (; current_index < n; ++current_index) {
 | 
			
		||||
            (void)m_dist(m_rand);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // We do not have to touch the current element index; it is handled
 | 
			
		||||
        // by the base class.
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Avoids -Wweak-vtables
 | 
			
		||||
 
 | 
			
		||||
@@ -98,6 +98,7 @@ set(IMPL_HEADERS
 | 
			
		||||
  ${SOURCES_DIR}/internal/catch_jsonwriter.hpp
 | 
			
		||||
  ${SOURCES_DIR}/internal/catch_lazy_expr.hpp
 | 
			
		||||
  ${SOURCES_DIR}/internal/catch_leak_detector.hpp
 | 
			
		||||
  ${SOURCES_DIR}/internal/catch_lifetimebound.hpp
 | 
			
		||||
  ${SOURCES_DIR}/internal/catch_list.hpp
 | 
			
		||||
  ${SOURCES_DIR}/internal/catch_logical_traits.hpp
 | 
			
		||||
  ${SOURCES_DIR}/internal/catch_message_info.hpp
 | 
			
		||||
 
 | 
			
		||||
@@ -79,6 +79,7 @@
 | 
			
		||||
#include <catch2/internal/catch_jsonwriter.hpp>
 | 
			
		||||
#include <catch2/internal/catch_lazy_expr.hpp>
 | 
			
		||||
#include <catch2/internal/catch_leak_detector.hpp>
 | 
			
		||||
#include <catch2/internal/catch_lifetimebound.hpp>
 | 
			
		||||
#include <catch2/internal/catch_list.hpp>
 | 
			
		||||
#include <catch2/internal/catch_logical_traits.hpp>
 | 
			
		||||
#include <catch2/internal/catch_message_info.hpp>
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,36 @@ namespace Detail {
 | 
			
		||||
        }
 | 
			
		||||
    } // end unnamed namespace
 | 
			
		||||
 | 
			
		||||
    std::size_t catch_strnlen( const char* str, std::size_t n ) {
 | 
			
		||||
        auto ret = std::char_traits<char>::find( str, n, '\0' );
 | 
			
		||||
        if ( ret != nullptr ) { return static_cast<std::size_t>( ret - str ); }
 | 
			
		||||
        return n;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string formatTimeT(std::time_t time) {
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
        std::tm timeInfo = {};
 | 
			
		||||
        const auto err = gmtime_s( &timeInfo, &time );
 | 
			
		||||
        if ( err ) {
 | 
			
		||||
            return "gmtime from provided timepoint has failed. This "
 | 
			
		||||
                   "happens e.g. with pre-1970 dates using Microsoft libc";
 | 
			
		||||
        }
 | 
			
		||||
#else
 | 
			
		||||
        std::tm* timeInfo = std::gmtime( &time );
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        auto const timeStampSize = sizeof( "2017-01-16T17:06:45Z" );
 | 
			
		||||
        char timeStamp[timeStampSize];
 | 
			
		||||
        const char* const fmt = "%Y-%m-%dT%H:%M:%SZ";
 | 
			
		||||
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
        std::strftime( timeStamp, timeStampSize, fmt, &timeInfo );
 | 
			
		||||
#else
 | 
			
		||||
        std::strftime( timeStamp, timeStampSize, fmt, timeInfo );
 | 
			
		||||
#endif
 | 
			
		||||
        return std::string( timeStamp, timeStampSize - 1 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string convertIntoString(StringRef string, bool escapeInvisibles) {
 | 
			
		||||
        std::string ret;
 | 
			
		||||
        // This is enough for the "don't escape invisibles" case, and a good
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
#ifndef CATCH_TOSTRING_HPP_INCLUDED
 | 
			
		||||
#define CATCH_TOSTRING_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <ctime>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
@@ -40,13 +40,9 @@ namespace Catch {
 | 
			
		||||
 | 
			
		||||
    namespace Detail {
 | 
			
		||||
 | 
			
		||||
        inline std::size_t catch_strnlen(const char *str, std::size_t n) {
 | 
			
		||||
            auto ret = std::char_traits<char>::find(str, n, '\0');
 | 
			
		||||
            if (ret != nullptr) {
 | 
			
		||||
                return static_cast<std::size_t>(ret - str);
 | 
			
		||||
            }
 | 
			
		||||
            return n;
 | 
			
		||||
        }
 | 
			
		||||
        std::size_t catch_strnlen(const char *str, std::size_t n);
 | 
			
		||||
 | 
			
		||||
        std::string formatTimeT( std::time_t time );
 | 
			
		||||
 | 
			
		||||
        constexpr StringRef unprintableString = "{?}"_sr;
 | 
			
		||||
 | 
			
		||||
@@ -411,44 +407,38 @@ namespace Catch {
 | 
			
		||||
 | 
			
		||||
// Separate std::tuple specialization
 | 
			
		||||
#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
 | 
			
		||||
#include <tuple>
 | 
			
		||||
#    include <tuple>
 | 
			
		||||
#    include <utility>
 | 
			
		||||
namespace Catch {
 | 
			
		||||
    namespace Detail {
 | 
			
		||||
        template<
 | 
			
		||||
            typename Tuple,
 | 
			
		||||
            std::size_t N = 0,
 | 
			
		||||
            bool = (N < std::tuple_size<Tuple>::value)
 | 
			
		||||
            >
 | 
			
		||||
            struct TupleElementPrinter {
 | 
			
		||||
            static void print(const Tuple& tuple, std::ostream& os) {
 | 
			
		||||
                os << (N ? ", " : " ")
 | 
			
		||||
                    << ::Catch::Detail::stringify(std::get<N>(tuple));
 | 
			
		||||
                TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        template <typename Tuple, std::size_t... Is>
 | 
			
		||||
        void PrintTuple( const Tuple& tuple,
 | 
			
		||||
                         std::ostream& os,
 | 
			
		||||
                         std::index_sequence<Is...> ) {
 | 
			
		||||
            // 1 + Account for when the tuple is empty
 | 
			
		||||
            char a[1 + sizeof...( Is )] = {
 | 
			
		||||
                ( ( os << ( Is ? ", " : " " )
 | 
			
		||||
                       << ::Catch::Detail::stringify( std::get<Is>( tuple ) ) ),
 | 
			
		||||
                  '\0' )... };
 | 
			
		||||
            (void)a;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        template<
 | 
			
		||||
            typename Tuple,
 | 
			
		||||
            std::size_t N
 | 
			
		||||
        >
 | 
			
		||||
            struct TupleElementPrinter<Tuple, N, false> {
 | 
			
		||||
            static void print(const Tuple&, std::ostream&) {}
 | 
			
		||||
        };
 | 
			
		||||
    } // namespace Detail
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    template<typename ...Types>
 | 
			
		||||
    template <typename... Types>
 | 
			
		||||
    struct StringMaker<std::tuple<Types...>> {
 | 
			
		||||
        static std::string convert(const std::tuple<Types...>& tuple) {
 | 
			
		||||
        static std::string convert( const std::tuple<Types...>& tuple ) {
 | 
			
		||||
            ReusableStringStream rss;
 | 
			
		||||
            rss << '{';
 | 
			
		||||
            Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
 | 
			
		||||
            Detail::PrintTuple(
 | 
			
		||||
                tuple,
 | 
			
		||||
                rss.get(),
 | 
			
		||||
                std::make_index_sequence<sizeof...( Types )>{} );
 | 
			
		||||
            rss << " }";
 | 
			
		||||
            return rss.str();
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
} // namespace Catch
 | 
			
		||||
#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
 | 
			
		||||
 | 
			
		||||
#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
 | 
			
		||||
@@ -635,28 +625,7 @@ struct ratio_string<std::milli> {
 | 
			
		||||
            const auto systemish = std::chrono::time_point_cast<
 | 
			
		||||
                std::chrono::system_clock::duration>( time_point );
 | 
			
		||||
            const auto as_time_t = std::chrono::system_clock::to_time_t( systemish );
 | 
			
		||||
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
            std::tm timeInfo = {};
 | 
			
		||||
            const auto err = gmtime_s( &timeInfo, &as_time_t );
 | 
			
		||||
            if ( err ) {
 | 
			
		||||
                return "gmtime from provided timepoint has failed. This "
 | 
			
		||||
                       "happens e.g. with pre-1970 dates using Microsoft libc";
 | 
			
		||||
            }
 | 
			
		||||
#else
 | 
			
		||||
            std::tm* timeInfo = std::gmtime( &as_time_t );
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
 | 
			
		||||
            char timeStamp[timeStampSize];
 | 
			
		||||
            const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
 | 
			
		||||
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
 | 
			
		||||
#else
 | 
			
		||||
            std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
 | 
			
		||||
#endif
 | 
			
		||||
            return std::string(timeStamp, timeStampSize - 1);
 | 
			
		||||
            return ::Catch::Detail::formatTimeT( as_time_t );
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,8 @@
 | 
			
		||||
// SPDX-License-Identifier: BSL-1.0
 | 
			
		||||
 | 
			
		||||
#include <catch2/interfaces/catch_interfaces_generatortracker.hpp>
 | 
			
		||||
#include <catch2/generators/catch_generators.hpp>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
@@ -21,6 +23,30 @@ 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" );
 | 
			
		||||
            }
 | 
			
		||||
            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();
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,15 @@ namespace Catch {
 | 
			
		||||
            //! Customization point for `currentElementAsString`
 | 
			
		||||
            virtual std::string stringifyImpl() const = 0;
 | 
			
		||||
 | 
			
		||||
            /**
 | 
			
		||||
             * Customization point for skipping to the n-th element
 | 
			
		||||
             *
 | 
			
		||||
             * Defaults to successively calling `countedNext`. If there
 | 
			
		||||
             * are not enough elements to reach the nth one, will throw
 | 
			
		||||
             * an error.
 | 
			
		||||
             */
 | 
			
		||||
            virtual void skipToNthElementImpl( std::size_t n );
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
            GeneratorUntypedBase() = default;
 | 
			
		||||
            // Generation of copy ops is deprecated (and Clang will complain)
 | 
			
		||||
@@ -58,6 +67,13 @@ namespace Catch {
 | 
			
		||||
 | 
			
		||||
            std::size_t currentElementIndex() const { return m_currentElementIndex; }
 | 
			
		||||
 | 
			
		||||
            /**
 | 
			
		||||
             * Moves the generator forward **to** the n-th element
 | 
			
		||||
             *
 | 
			
		||||
             * Cannot move backwards.
 | 
			
		||||
             */
 | 
			
		||||
            void skipToNthElement( std::size_t n );
 | 
			
		||||
 | 
			
		||||
            /**
 | 
			
		||||
             * Returns generator's current element as user-friendly string.
 | 
			
		||||
             *
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								src/catch2/internal/catch_lifetimebound.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/catch2/internal/catch_lifetimebound.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
 | 
			
		||||
//              Copyright Catch2 Authors
 | 
			
		||||
// Distributed under the Boost Software License, Version 1.0.
 | 
			
		||||
//   (See accompanying file LICENSE.txt or copy at
 | 
			
		||||
//        https://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
 | 
			
		||||
// SPDX-License-Identifier: BSL-1.0
 | 
			
		||||
 | 
			
		||||
#ifndef CATCH_LIFETIMEBOUND_HPP_INCLUDED
 | 
			
		||||
#define CATCH_LIFETIMEBOUND_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
#if !defined( __has_cpp_attribute )
 | 
			
		||||
#    define CATCH_ATTR_LIFETIMEBOUND
 | 
			
		||||
#elif __has_cpp_attribute( msvc::lifetimebound )
 | 
			
		||||
#    define CATCH_ATTR_LIFETIMEBOUND [[msvc::lifetimebound]]
 | 
			
		||||
#elif __has_cpp_attribute( clang::lifetimebound )
 | 
			
		||||
#    define CATCH_ATTR_LIFETIMEBOUND [[clang::lifetimebound]]
 | 
			
		||||
#elif __has_cpp_attribute( lifetimebound )
 | 
			
		||||
#    define CATCH_ATTR_LIFETIMEBOUND [[lifetimebound]]
 | 
			
		||||
#else
 | 
			
		||||
#    define CATCH_ATTR_LIFETIMEBOUND
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // CATCH_LIFETIMEBOUND_HPP_INCLUDED
 | 
			
		||||
@@ -129,12 +129,8 @@ namespace Catch {
 | 
			
		||||
 | 
			
		||||
                        for ( auto const& child : m_children ) {
 | 
			
		||||
                            if ( child->isSectionTracker() &&
 | 
			
		||||
                                 std::find( filters.begin(),
 | 
			
		||||
                                            filters.end(),
 | 
			
		||||
                                            static_cast<SectionTracker const&>(
 | 
			
		||||
                                                *child )
 | 
			
		||||
                                                .trimmedName() ) !=
 | 
			
		||||
                                     filters.end() ) {
 | 
			
		||||
                                 static_cast<SectionTracker const&>( *child )
 | 
			
		||||
                                         .trimmedName() == filters[0] ) {
 | 
			
		||||
                                return true;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
#ifndef CATCH_STRING_MANIP_HPP_INCLUDED
 | 
			
		||||
#define CATCH_STRING_MANIP_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <catch2/internal/catch_lifetimebound.hpp>
 | 
			
		||||
#include <catch2/internal/catch_stringref.hpp>
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
@@ -28,10 +29,10 @@ namespace Catch {
 | 
			
		||||
    //! Returns a new string without whitespace at the start/end
 | 
			
		||||
    std::string trim( std::string const& str );
 | 
			
		||||
    //! Returns a substring of the original ref without whitespace. Beware lifetimes!
 | 
			
		||||
    StringRef trim(StringRef ref);
 | 
			
		||||
    StringRef trim( StringRef ref CATCH_ATTR_LIFETIMEBOUND );
 | 
			
		||||
 | 
			
		||||
    // !!! Be aware, returns refs into original string - make sure original string outlives them
 | 
			
		||||
    std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
 | 
			
		||||
    std::vector<StringRef> splitStringRef( StringRef str CATCH_ATTR_LIFETIMEBOUND, char delimiter );
 | 
			
		||||
    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -49,7 +50,7 @@ namespace Catch {
 | 
			
		||||
        StringRef m_label;
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        constexpr pluralise(std::uint64_t count, StringRef label):
 | 
			
		||||
        constexpr pluralise(std::uint64_t count, StringRef label CATCH_ATTR_LIFETIMEBOUND):
 | 
			
		||||
            m_count(count),
 | 
			
		||||
            m_label(label)
 | 
			
		||||
        {}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,11 +8,12 @@
 | 
			
		||||
#ifndef CATCH_STRINGREF_HPP_INCLUDED
 | 
			
		||||
#define CATCH_STRINGREF_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <catch2/internal/catch_lifetimebound.hpp>
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <iosfwd>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
 | 
			
		||||
namespace Catch {
 | 
			
		||||
@@ -36,14 +37,16 @@ namespace Catch {
 | 
			
		||||
    public: // construction
 | 
			
		||||
        constexpr StringRef() noexcept = default;
 | 
			
		||||
 | 
			
		||||
        StringRef( char const* rawChars ) noexcept;
 | 
			
		||||
        StringRef( char const* rawChars CATCH_ATTR_LIFETIMEBOUND ) noexcept;
 | 
			
		||||
 | 
			
		||||
        constexpr StringRef( char const* rawChars, size_type size ) noexcept
 | 
			
		||||
        constexpr StringRef( char const* rawChars CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                             size_type size ) noexcept
 | 
			
		||||
        :   m_start( rawChars ),
 | 
			
		||||
            m_size( size )
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
        StringRef( std::string const& stdString ) noexcept
 | 
			
		||||
        StringRef(
 | 
			
		||||
            std::string const& stdString CATCH_ATTR_LIFETIMEBOUND ) noexcept
 | 
			
		||||
        :   m_start( stdString.c_str() ),
 | 
			
		||||
            m_size( stdString.size() )
 | 
			
		||||
        {}
 | 
			
		||||
@@ -89,7 +92,7 @@ namespace Catch {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Returns the current start pointer. May not be null-terminated.
 | 
			
		||||
        constexpr char const* data() const noexcept {
 | 
			
		||||
        constexpr char const* data() const noexcept CATCH_ATTR_LIFETIMEBOUND {
 | 
			
		||||
            return m_start;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -172,9 +172,9 @@ namespace TestCaseTracking {
 | 
			
		||||
    bool SectionTracker::isComplete() const {
 | 
			
		||||
        bool complete = true;
 | 
			
		||||
 | 
			
		||||
        if (m_filters.empty()
 | 
			
		||||
        if ( m_filters.empty()
 | 
			
		||||
            || m_filters[0].empty()
 | 
			
		||||
            || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
 | 
			
		||||
            || m_filters[0] == m_trimmed_name ) {
 | 
			
		||||
            complete = TrackerBase::isComplete();
 | 
			
		||||
        }
 | 
			
		||||
        return complete;
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
#ifndef CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
 | 
			
		||||
#define CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <catch2/internal/catch_lifetimebound.hpp>
 | 
			
		||||
#include <catch2/internal/catch_source_line_info.hpp>
 | 
			
		||||
#include <catch2/internal/catch_unique_ptr.hpp>
 | 
			
		||||
#include <catch2/internal/catch_stringref.hpp>
 | 
			
		||||
@@ -48,7 +49,7 @@ namespace TestCaseTracking {
 | 
			
		||||
        StringRef name;
 | 
			
		||||
        SourceLineInfo location;
 | 
			
		||||
 | 
			
		||||
        constexpr NameAndLocationRef( StringRef name_,
 | 
			
		||||
        constexpr NameAndLocationRef( StringRef name_ CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                                      SourceLineInfo location_ ):
 | 
			
		||||
            name( name_ ), location( location_ ) {}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
 | 
			
		||||
#include <catch2/matchers/internal/catch_matchers_impl.hpp>
 | 
			
		||||
#include <catch2/internal/catch_move_and_forward.hpp>
 | 
			
		||||
#include <catch2/internal/catch_lifetimebound.hpp>
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
@@ -79,11 +80,15 @@ namespace Matchers {
 | 
			
		||||
                return description;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            friend MatchAllOf operator&& (MatchAllOf&& lhs, MatcherBase<ArgT> const& rhs) {
 | 
			
		||||
            friend MatchAllOf operator&&( MatchAllOf&& lhs,
 | 
			
		||||
                                          MatcherBase<ArgT> const& rhs
 | 
			
		||||
                                              CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
                lhs.m_matchers.push_back(&rhs);
 | 
			
		||||
                return CATCH_MOVE(lhs);
 | 
			
		||||
            }
 | 
			
		||||
            friend MatchAllOf operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf&& rhs) {
 | 
			
		||||
            friend MatchAllOf
 | 
			
		||||
            operator&&( MatcherBase<ArgT> const& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                        MatchAllOf&& rhs ) {
 | 
			
		||||
                rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
 | 
			
		||||
                return CATCH_MOVE(rhs);
 | 
			
		||||
            }
 | 
			
		||||
@@ -131,11 +136,15 @@ namespace Matchers {
 | 
			
		||||
                return description;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            friend MatchAnyOf operator|| (MatchAnyOf&& lhs, MatcherBase<ArgT> const& rhs) {
 | 
			
		||||
            friend MatchAnyOf operator||( MatchAnyOf&& lhs,
 | 
			
		||||
                                          MatcherBase<ArgT> const& rhs
 | 
			
		||||
                                              CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
                lhs.m_matchers.push_back(&rhs);
 | 
			
		||||
                return CATCH_MOVE(lhs);
 | 
			
		||||
            }
 | 
			
		||||
            friend MatchAnyOf operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf&& rhs) {
 | 
			
		||||
            friend MatchAnyOf
 | 
			
		||||
            operator||( MatcherBase<ArgT> const& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                        MatchAnyOf&& rhs ) {
 | 
			
		||||
                rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs);
 | 
			
		||||
                return CATCH_MOVE(rhs);
 | 
			
		||||
            }
 | 
			
		||||
@@ -155,7 +164,8 @@ namespace Matchers {
 | 
			
		||||
            MatcherBase<ArgT> const& m_underlyingMatcher;
 | 
			
		||||
 | 
			
		||||
        public:
 | 
			
		||||
            explicit MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ):
 | 
			
		||||
            explicit MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher
 | 
			
		||||
                                     CATCH_ATTR_LIFETIMEBOUND ):
 | 
			
		||||
                m_underlyingMatcher( underlyingMatcher )
 | 
			
		||||
            {}
 | 
			
		||||
 | 
			
		||||
@@ -171,16 +181,22 @@ namespace Matchers {
 | 
			
		||||
    } // namespace Detail
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    Detail::MatchAllOf<T> operator&& (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) {
 | 
			
		||||
    Detail::MatchAllOf<T>
 | 
			
		||||
    operator&&( MatcherBase<T> const& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatcherBase<T> const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
        return Detail::MatchAllOf<T>{} && lhs && rhs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    Detail::MatchAnyOf<T> operator|| (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) {
 | 
			
		||||
    Detail::MatchAnyOf<T>
 | 
			
		||||
    operator||( MatcherBase<T> const& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatcherBase<T> const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
        return Detail::MatchAnyOf<T>{} || lhs || rhs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    Detail::MatchNotOf<T> operator! (MatcherBase<T> const& matcher) {
 | 
			
		||||
    Detail::MatchNotOf<T>
 | 
			
		||||
    operator!( MatcherBase<T> const& matcher CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
        return Detail::MatchNotOf<T>{ matcher };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@
 | 
			
		||||
#include <catch2/matchers/catch_matchers.hpp>
 | 
			
		||||
#include <catch2/internal/catch_stringref.hpp>
 | 
			
		||||
#include <catch2/internal/catch_move_and_forward.hpp>
 | 
			
		||||
#include <catch2/internal/catch_lifetimebound.hpp>
 | 
			
		||||
#include <catch2/internal/catch_logical_traits.hpp>
 | 
			
		||||
 | 
			
		||||
#include <array>
 | 
			
		||||
@@ -114,7 +115,8 @@ namespace Matchers {
 | 
			
		||||
            MatchAllOfGeneric(MatchAllOfGeneric&&) = default;
 | 
			
		||||
            MatchAllOfGeneric& operator=(MatchAllOfGeneric&&) = default;
 | 
			
		||||
 | 
			
		||||
            MatchAllOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {}
 | 
			
		||||
            MatchAllOfGeneric(MatcherTs const&... matchers CATCH_ATTR_LIFETIMEBOUND)
 | 
			
		||||
                : m_matchers{ {std::addressof(matchers)...} } {}
 | 
			
		||||
            explicit MatchAllOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
 | 
			
		||||
 | 
			
		||||
            template<typename Arg>
 | 
			
		||||
@@ -136,8 +138,8 @@ namespace Matchers {
 | 
			
		||||
            template<typename... MatchersRHS>
 | 
			
		||||
            friend
 | 
			
		||||
            MatchAllOfGeneric<MatcherTs..., MatchersRHS...> operator && (
 | 
			
		||||
                    MatchAllOfGeneric<MatcherTs...>&& lhs,
 | 
			
		||||
                    MatchAllOfGeneric<MatchersRHS...>&& rhs) {
 | 
			
		||||
                MatchAllOfGeneric<MatcherTs...>&& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatchAllOfGeneric<MatchersRHS...>&& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
                return MatchAllOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -145,8 +147,8 @@ namespace Matchers {
 | 
			
		||||
            template<typename MatcherRHS>
 | 
			
		||||
            friend std::enable_if_t<is_matcher_v<MatcherRHS>,
 | 
			
		||||
            MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && (
 | 
			
		||||
                    MatchAllOfGeneric<MatcherTs...>&& lhs,
 | 
			
		||||
                    MatcherRHS const& rhs) {
 | 
			
		||||
                MatchAllOfGeneric<MatcherTs...>&& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
                return MatchAllOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(&rhs))};
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -154,8 +156,8 @@ namespace Matchers {
 | 
			
		||||
            template<typename MatcherLHS>
 | 
			
		||||
            friend std::enable_if_t<is_matcher_v<MatcherLHS>,
 | 
			
		||||
            MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && (
 | 
			
		||||
                    MatcherLHS const& lhs,
 | 
			
		||||
                    MatchAllOfGeneric<MatcherTs...>&& rhs) {
 | 
			
		||||
                MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatchAllOfGeneric<MatcherTs...>&& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
                return MatchAllOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))};
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
@@ -169,7 +171,8 @@ namespace Matchers {
 | 
			
		||||
            MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default;
 | 
			
		||||
            MatchAnyOfGeneric& operator=(MatchAnyOfGeneric&&) = default;
 | 
			
		||||
 | 
			
		||||
            MatchAnyOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {}
 | 
			
		||||
            MatchAnyOfGeneric(MatcherTs const&... matchers CATCH_ATTR_LIFETIMEBOUND)
 | 
			
		||||
                : m_matchers{ {std::addressof(matchers)...} } {}
 | 
			
		||||
            explicit MatchAnyOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {}
 | 
			
		||||
 | 
			
		||||
            template<typename Arg>
 | 
			
		||||
@@ -190,8 +193,8 @@ namespace Matchers {
 | 
			
		||||
            //! Avoids type nesting for `GenericAnyOf || GenericAnyOf` case
 | 
			
		||||
            template<typename... MatchersRHS>
 | 
			
		||||
            friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...> operator || (
 | 
			
		||||
                    MatchAnyOfGeneric<MatcherTs...>&& lhs,
 | 
			
		||||
                    MatchAnyOfGeneric<MatchersRHS...>&& rhs) {
 | 
			
		||||
                MatchAnyOfGeneric<MatcherTs...>&& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatchAnyOfGeneric<MatchersRHS...>&& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
                return MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))};
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -199,8 +202,8 @@ namespace Matchers {
 | 
			
		||||
            template<typename MatcherRHS>
 | 
			
		||||
            friend std::enable_if_t<is_matcher_v<MatcherRHS>,
 | 
			
		||||
            MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || (
 | 
			
		||||
                    MatchAnyOfGeneric<MatcherTs...>&& lhs,
 | 
			
		||||
                    MatcherRHS const& rhs) {
 | 
			
		||||
                    MatchAnyOfGeneric<MatcherTs...>&& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                    MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
                return MatchAnyOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))};
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -208,8 +211,8 @@ namespace Matchers {
 | 
			
		||||
            template<typename MatcherLHS>
 | 
			
		||||
            friend std::enable_if_t<is_matcher_v<MatcherLHS>,
 | 
			
		||||
            MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || (
 | 
			
		||||
                MatcherLHS const& lhs,
 | 
			
		||||
                MatchAnyOfGeneric<MatcherTs...>&& rhs) {
 | 
			
		||||
                MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatchAnyOfGeneric<MatcherTs...>&& rhs CATCH_ATTR_LIFETIMEBOUND) {
 | 
			
		||||
                return MatchAnyOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))};
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
@@ -225,7 +228,8 @@ namespace Matchers {
 | 
			
		||||
            MatchNotOfGeneric(MatchNotOfGeneric&&) = default;
 | 
			
		||||
            MatchNotOfGeneric& operator=(MatchNotOfGeneric&&) = default;
 | 
			
		||||
 | 
			
		||||
            explicit MatchNotOfGeneric(MatcherT const& matcher) : m_matcher{matcher} {}
 | 
			
		||||
            explicit MatchNotOfGeneric(MatcherT const& matcher CATCH_ATTR_LIFETIMEBOUND)
 | 
			
		||||
                : m_matcher{matcher} {}
 | 
			
		||||
 | 
			
		||||
            template<typename Arg>
 | 
			
		||||
            bool match(Arg&& arg) const {
 | 
			
		||||
@@ -237,7 +241,9 @@ namespace Matchers {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            //! Negating negation can just unwrap and return underlying matcher
 | 
			
		||||
            friend MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) {
 | 
			
		||||
            friend MatcherT const&
 | 
			
		||||
            operator!( MatchNotOfGeneric<MatcherT> const& matcher
 | 
			
		||||
                           CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
                return matcher.m_matcher;
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
@@ -247,20 +253,22 @@ namespace Matchers {
 | 
			
		||||
    // compose only generic matchers
 | 
			
		||||
    template<typename MatcherLHS, typename MatcherRHS>
 | 
			
		||||
    std::enable_if_t<Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>>
 | 
			
		||||
        operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) {
 | 
			
		||||
    operator&&( MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
        return { lhs, rhs };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename MatcherLHS, typename MatcherRHS>
 | 
			
		||||
    std::enable_if_t<Detail::are_generic_matchers_v<MatcherLHS, MatcherRHS>, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>>
 | 
			
		||||
        operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) {
 | 
			
		||||
    operator||( MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
        return { lhs, rhs };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //! Wrap provided generic matcher in generic negator
 | 
			
		||||
    template<typename MatcherT>
 | 
			
		||||
    std::enable_if_t<Detail::is_generic_matcher_v<MatcherT>, Detail::MatchNotOfGeneric<MatcherT>>
 | 
			
		||||
        operator ! (MatcherT const& matcher) {
 | 
			
		||||
    operator!( MatcherT const& matcher CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
        return Detail::MatchNotOfGeneric<MatcherT>{matcher};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -268,25 +276,29 @@ namespace Matchers {
 | 
			
		||||
    // compose mixed generic and non-generic matchers
 | 
			
		||||
    template<typename MatcherLHS, typename ArgRHS>
 | 
			
		||||
    std::enable_if_t<Detail::is_generic_matcher_v<MatcherLHS>, Detail::MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
 | 
			
		||||
        operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
 | 
			
		||||
    operator&&( MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatcherBase<ArgRHS> const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
        return { lhs, rhs };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename ArgLHS, typename MatcherRHS>
 | 
			
		||||
    std::enable_if_t<Detail::is_generic_matcher_v<MatcherRHS>, Detail::MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
 | 
			
		||||
        operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
 | 
			
		||||
    operator&&( MatcherBase<ArgLHS> const& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
        return { lhs, rhs };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename MatcherLHS, typename ArgRHS>
 | 
			
		||||
    std::enable_if_t<Detail::is_generic_matcher_v<MatcherLHS>, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>>
 | 
			
		||||
        operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) {
 | 
			
		||||
    operator||( MatcherLHS const& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatcherBase<ArgRHS> const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
        return { lhs, rhs };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template<typename ArgLHS, typename MatcherRHS>
 | 
			
		||||
    std::enable_if_t<Detail::is_generic_matcher_v<MatcherRHS>, Detail::MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>>
 | 
			
		||||
        operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) {
 | 
			
		||||
    operator||( MatcherBase<ArgLHS> const& lhs CATCH_ATTR_LIFETIMEBOUND,
 | 
			
		||||
                MatcherRHS const& rhs CATCH_ATTR_LIFETIMEBOUND ) {
 | 
			
		||||
        return { lhs, rhs };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -105,6 +105,7 @@ internal_headers = [
 | 
			
		||||
  'internal/catch_jsonwriter.hpp',
 | 
			
		||||
  'internal/catch_lazy_expr.hpp',
 | 
			
		||||
  'internal/catch_leak_detector.hpp',
 | 
			
		||||
  'internal/catch_lifetimebound.hpp',
 | 
			
		||||
  'internal/catch_list.hpp',
 | 
			
		||||
  'internal/catch_logical_traits.hpp',
 | 
			
		||||
  'internal/catch_message_info.hpp',
 | 
			
		||||
 
 | 
			
		||||
@@ -310,38 +310,23 @@ set_tests_properties(UnmatchedOutputFilter
 | 
			
		||||
    PASS_REGULAR_EXPRESSION "No test cases matched '\\[this-tag-does-not-exist\\]'"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
add_test(NAME FilteredSection-1 COMMAND $<TARGET_FILE:SelfTest> \#1394 -c RunSection)
 | 
			
		||||
set_tests_properties(FilteredSection-1 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
 | 
			
		||||
add_test(NAME FilteredSection-2 COMMAND $<TARGET_FILE:SelfTest> \#1394\ nested -c NestedRunSection -c s1)
 | 
			
		||||
set_tests_properties(FilteredSection-2 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
 | 
			
		||||
add_test(NAME FilteredSections::SimpleExample::1 COMMAND $<TARGET_FILE:SelfTest> \#1394 -c RunSection)
 | 
			
		||||
set_tests_properties(FilteredSections::SimpleExample::1 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
 | 
			
		||||
add_test(NAME FilteredSections::SimpleExample::2 COMMAND $<TARGET_FILE:SelfTest> \#1394\ nested -c NestedRunSection -c s1)
 | 
			
		||||
set_tests_properties(FilteredSections::SimpleExample::2 PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran")
 | 
			
		||||
 | 
			
		||||
add_test(
 | 
			
		||||
  NAME
 | 
			
		||||
    FilteredSection::GeneratorsDontCauseInfiniteLoop-1
 | 
			
		||||
    FilteredSections::GeneratorsDontCauseInfiniteLoop
 | 
			
		||||
  COMMAND
 | 
			
		||||
    $<TARGET_FILE:SelfTest> "#2025: original repro" -c "fov_0"
 | 
			
		||||
)
 | 
			
		||||
set_tests_properties(FilteredSection::GeneratorsDontCauseInfiniteLoop-1
 | 
			
		||||
set_tests_properties(FilteredSections::GeneratorsDontCauseInfiniteLoop
 | 
			
		||||
  PROPERTIES
 | 
			
		||||
    PASS_REGULAR_EXPRESSION "inside with fov: 0" # This should happen
 | 
			
		||||
    FAIL_REGULAR_EXPRESSION "inside with fov: 1" # This would mean there was no filtering
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# GENERATE between filtered sections (both are selected)
 | 
			
		||||
add_test(
 | 
			
		||||
  NAME
 | 
			
		||||
    FilteredSection::GeneratorsDontCauseInfiniteLoop-2
 | 
			
		||||
  COMMAND
 | 
			
		||||
    $<TARGET_FILE:SelfTest> "#2025: same-level sections"
 | 
			
		||||
    -c "A"
 | 
			
		||||
    -c "B"
 | 
			
		||||
    --colour-mode none
 | 
			
		||||
)
 | 
			
		||||
set_tests_properties(FilteredSection::GeneratorsDontCauseInfiniteLoop-2
 | 
			
		||||
  PROPERTIES
 | 
			
		||||
    PASS_REGULAR_EXPRESSION "All tests passed \\(4 assertions in 1 test case\\)"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
add_test(NAME ApprovalTests
 | 
			
		||||
  COMMAND
 | 
			
		||||
    Python3::Interpreter
 | 
			
		||||
@@ -694,6 +679,14 @@ set_tests_properties("Bazel::RngSeedEnvVar::MalformedValueIsIgnored"
 | 
			
		||||
    PASS_REGULAR_EXPRESSION "Randomness seeded to: 17171717"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
add_test(NAME "FilteredSections::DifferentSimpleFilters"
 | 
			
		||||
  COMMAND
 | 
			
		||||
      Python3::Interpreter "${CMAKE_CURRENT_LIST_DIR}/TestScripts/testSectionFiltering.py" $<TARGET_FILE:SelfTest>
 | 
			
		||||
)
 | 
			
		||||
set_tests_properties("FilteredSections::DifferentSimpleFilters"
 | 
			
		||||
  PROPERTIES
 | 
			
		||||
    LABELS "uses-python"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
list(APPEND CATCH_TEST_TARGETS SelfTest)
 | 
			
		||||
set(CATCH_TEST_TARGETS ${CATCH_TEST_TARGETS} PARENT_SCOPE)
 | 
			
		||||
 
 | 
			
		||||
@@ -168,6 +168,7 @@ Nor would this
 | 
			
		||||
:test-result: PASS GENERATE can combine literals and generators
 | 
			
		||||
:test-result: PASS Generators -- adapters
 | 
			
		||||
:test-result: PASS Generators -- simple
 | 
			
		||||
:test-result: PASS Generators can be skipped forward
 | 
			
		||||
:test-result: PASS Generators internals
 | 
			
		||||
:test-result: PASS Greater-than inequalities with different epsilons
 | 
			
		||||
:test-result: PASS Hashers with different seed produce different hash with same test case
 | 
			
		||||
 
 | 
			
		||||
@@ -166,6 +166,7 @@
 | 
			
		||||
:test-result: PASS GENERATE can combine literals and generators
 | 
			
		||||
:test-result: PASS Generators -- adapters
 | 
			
		||||
:test-result: PASS Generators -- simple
 | 
			
		||||
:test-result: PASS Generators can be skipped forward
 | 
			
		||||
:test-result: PASS Generators internals
 | 
			
		||||
:test-result: PASS Greater-than inequalities with different epsilons
 | 
			
		||||
:test-result: PASS Hashers with different seed produce different hash with same test case
 | 
			
		||||
 
 | 
			
		||||
@@ -787,6 +787,13 @@ Generators.tests.cpp:<line number>: passed: j < i for: -1 < 3
 | 
			
		||||
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 1
 | 
			
		||||
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 2
 | 
			
		||||
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 3
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.currentElementIndex() == 0 for: 0 == 0
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.currentElementIndex() == 3 for: 3 == 3
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.get() == 3 for: 3 == 3
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.currentElementIndex() == 5 for: 5 == 5
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.get() == 5 for: 5 == 5
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.skipToNthElement( 3 )
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.skipToNthElement( 6 )
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 123 for: 123 == 123
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
 | 
			
		||||
@@ -2888,7 +2895,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
 | 
			
		||||
InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
 | 
			
		||||
Misc.tests.cpp:<line number>: passed:
 | 
			
		||||
Misc.tests.cpp:<line number>: passed:
 | 
			
		||||
test cases:  435 |  317 passed |  95 failed | 6 skipped | 17 failed as expected
 | 
			
		||||
assertions: 2303 | 2105 passed | 157 failed | 41 failed as expected
 | 
			
		||||
test cases:  436 |  318 passed |  95 failed | 6 skipped | 17 failed as expected
 | 
			
		||||
assertions: 2310 | 2112 passed | 157 failed | 41 failed as expected
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -785,6 +785,13 @@ Generators.tests.cpp:<line number>: passed: j < i for: -1 < 3
 | 
			
		||||
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 1
 | 
			
		||||
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 2
 | 
			
		||||
Generators.tests.cpp:<line number>: passed: 4u * i > str.size() for: 12 > 3
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.currentElementIndex() == 0 for: 0 == 0
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.currentElementIndex() == 3 for: 3 == 3
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.get() == 3 for: 3 == 3
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.currentElementIndex() == 5 for: 5 == 5
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.get() == 5 for: 5 == 5
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.skipToNthElement( 3 )
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: generator.skipToNthElement( 6 )
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 123 for: 123 == 123
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
 | 
			
		||||
@@ -2877,7 +2884,7 @@ InternalBenchmark.tests.cpp:<line number>: passed: med == 18. for: 18.0 == 18.0
 | 
			
		||||
InternalBenchmark.tests.cpp:<line number>: passed: q3 == 23. for: 23.0 == 23.0
 | 
			
		||||
Misc.tests.cpp:<line number>: passed:
 | 
			
		||||
Misc.tests.cpp:<line number>: passed:
 | 
			
		||||
test cases:  435 |  317 passed |  95 failed | 6 skipped | 17 failed as expected
 | 
			
		||||
assertions: 2303 | 2105 passed | 157 failed | 41 failed as expected
 | 
			
		||||
test cases:  436 |  318 passed |  95 failed | 6 skipped | 17 failed as expected
 | 
			
		||||
assertions: 2310 | 2112 passed | 157 failed | 41 failed as expected
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1719,6 +1719,6 @@ due to unexpected exception with message:
 | 
			
		||||
  Why would you throw a std::string?
 | 
			
		||||
 | 
			
		||||
===============================================================================
 | 
			
		||||
test cases:  435 |  335 passed |  76 failed | 7 skipped | 17 failed as expected
 | 
			
		||||
assertions: 2282 | 2105 passed | 136 failed | 41 failed as expected
 | 
			
		||||
test cases:  436 |  336 passed |  76 failed | 7 skipped | 17 failed as expected
 | 
			
		||||
assertions: 2289 | 2112 passed | 136 failed | 41 failed as expected
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5831,6 +5831,43 @@ Generators.tests.cpp:<line number>: PASSED:
 | 
			
		||||
with expansion:
 | 
			
		||||
  12 > 3
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Generators can be skipped forward
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>
 | 
			
		||||
...............................................................................
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE( generator.currentElementIndex() == 0 )
 | 
			
		||||
with expansion:
 | 
			
		||||
  0 == 0
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE( generator.currentElementIndex() == 3 )
 | 
			
		||||
with expansion:
 | 
			
		||||
  3 == 3
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE( generator.get() == 3 )
 | 
			
		||||
with expansion:
 | 
			
		||||
  3 == 3
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE( generator.currentElementIndex() == 5 )
 | 
			
		||||
with expansion:
 | 
			
		||||
  5 == 5
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE( generator.get() == 5 )
 | 
			
		||||
with expansion:
 | 
			
		||||
  5 == 5
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE_THROWS( generator.skipToNthElement( 3 ) )
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE_THROWS( generator.skipToNthElement( 6 ) )
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Generators internals
 | 
			
		||||
  Single value
 | 
			
		||||
@@ -19295,6 +19332,6 @@ Misc.tests.cpp:<line number>
 | 
			
		||||
Misc.tests.cpp:<line number>: PASSED:
 | 
			
		||||
 | 
			
		||||
===============================================================================
 | 
			
		||||
test cases:  435 |  317 passed |  95 failed | 6 skipped | 17 failed as expected
 | 
			
		||||
assertions: 2303 | 2105 passed | 157 failed | 41 failed as expected
 | 
			
		||||
test cases:  436 |  318 passed |  95 failed | 6 skipped | 17 failed as expected
 | 
			
		||||
assertions: 2310 | 2112 passed | 157 failed | 41 failed as expected
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5829,6 +5829,43 @@ Generators.tests.cpp:<line number>: PASSED:
 | 
			
		||||
with expansion:
 | 
			
		||||
  12 > 3
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Generators can be skipped forward
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>
 | 
			
		||||
...............................................................................
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE( generator.currentElementIndex() == 0 )
 | 
			
		||||
with expansion:
 | 
			
		||||
  0 == 0
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE( generator.currentElementIndex() == 3 )
 | 
			
		||||
with expansion:
 | 
			
		||||
  3 == 3
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE( generator.get() == 3 )
 | 
			
		||||
with expansion:
 | 
			
		||||
  3 == 3
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE( generator.currentElementIndex() == 5 )
 | 
			
		||||
with expansion:
 | 
			
		||||
  5 == 5
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE( generator.get() == 5 )
 | 
			
		||||
with expansion:
 | 
			
		||||
  5 == 5
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE_THROWS( generator.skipToNthElement( 3 ) )
 | 
			
		||||
 | 
			
		||||
GeneratorsImpl.tests.cpp:<line number>: PASSED:
 | 
			
		||||
  REQUIRE_THROWS( generator.skipToNthElement( 6 ) )
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------------------
 | 
			
		||||
Generators internals
 | 
			
		||||
  Single value
 | 
			
		||||
@@ -19284,6 +19321,6 @@ Misc.tests.cpp:<line number>
 | 
			
		||||
Misc.tests.cpp:<line number>: PASSED:
 | 
			
		||||
 | 
			
		||||
===============================================================================
 | 
			
		||||
test cases:  435 |  317 passed |  95 failed | 6 skipped | 17 failed as expected
 | 
			
		||||
assertions: 2303 | 2105 passed | 157 failed | 41 failed as expected
 | 
			
		||||
test cases:  436 |  318 passed |  95 failed | 6 skipped | 17 failed as expected
 | 
			
		||||
assertions: 2310 | 2112 passed | 157 failed | 41 failed as expected
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<testsuitesloose text artifact
 | 
			
		||||
>
 | 
			
		||||
  <testsuite name="<exe-name>" errors="17" failures="140" skipped="12" tests="2315" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
 | 
			
		||||
  <testsuite name="<exe-name>" errors="17" failures="140" skipped="12" tests="2322" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
 | 
			
		||||
    <properties>
 | 
			
		||||
      <property name="random-seed" value="1"/>
 | 
			
		||||
      <property name="filters" value=""*" ~[!nonportable] ~[!benchmark] ~[approvals]"/>
 | 
			
		||||
@@ -837,6 +837,7 @@ at Message.tests.cpp:<line number>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators -- simple" time="{duration}" status="run"/>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators -- simple/one" time="{duration}" status="run"/>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators -- simple/two" time="{duration}" status="run"/>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators can be skipped forward" time="{duration}" status="run"/>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators internals" time="{duration}" status="run"/>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators internals/Single value" time="{duration}" status="run"/>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators internals/Preset values" time="{duration}" status="run"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<testsuites>
 | 
			
		||||
  <testsuite name="<exe-name>" errors="17" failures="140" skipped="12" tests="2315" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
 | 
			
		||||
  <testsuite name="<exe-name>" errors="17" failures="140" skipped="12" tests="2322" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
 | 
			
		||||
    <properties>
 | 
			
		||||
      <property name="random-seed" value="1"/>
 | 
			
		||||
      <property name="filters" value=""*" ~[!nonportable] ~[!benchmark] ~[approvals]"/>
 | 
			
		||||
@@ -836,6 +836,7 @@ at Message.tests.cpp:<line number>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators -- simple" time="{duration}" status="run"/>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators -- simple/one" time="{duration}" status="run"/>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators -- simple/two" time="{duration}" status="run"/>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators can be skipped forward" time="{duration}" status="run"/>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators internals" time="{duration}" status="run"/>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators internals/Single value" time="{duration}" status="run"/>
 | 
			
		||||
    <testcase classname="<exe-name>.global" name="Generators internals/Preset values" time="{duration}" status="run"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -144,6 +144,7 @@ at AssertionHandler.tests.cpp:<line number>
 | 
			
		||||
  </file>
 | 
			
		||||
  <file path="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp">
 | 
			
		||||
    <testCase name="Filter generator throws exception for empty generator" duration="{duration}"/>
 | 
			
		||||
    <testCase name="Generators can be skipped forward" duration="{duration}"/>
 | 
			
		||||
    <testCase name="Generators internals" duration="{duration}"/>
 | 
			
		||||
    <testCase name="Generators internals/Single value" duration="{duration}"/>
 | 
			
		||||
    <testCase name="Generators internals/Preset values" duration="{duration}"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -143,6 +143,7 @@ at AssertionHandler.tests.cpp:<line number>
 | 
			
		||||
  </file>
 | 
			
		||||
  <file path="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp">
 | 
			
		||||
    <testCase name="Filter generator throws exception for empty generator" duration="{duration}"/>
 | 
			
		||||
    <testCase name="Generators can be skipped forward" duration="{duration}"/>
 | 
			
		||||
    <testCase name="Generators internals" duration="{duration}"/>
 | 
			
		||||
    <testCase name="Generators internals/Single value" duration="{duration}"/>
 | 
			
		||||
    <testCase name="Generators internals/Preset values" duration="{duration}"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -1430,6 +1430,20 @@ ok {test-number} - 4u * i > str.size() for: 12 > 1
 | 
			
		||||
ok {test-number} - 4u * i > str.size() for: 12 > 2
 | 
			
		||||
# Generators -- simple
 | 
			
		||||
ok {test-number} - 4u * i > str.size() for: 12 > 3
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.currentElementIndex() == 0 for: 0 == 0
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.currentElementIndex() == 3 for: 3 == 3
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.get() == 3 for: 3 == 3
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.currentElementIndex() == 5 for: 5 == 5
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.get() == 5 for: 5 == 5
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.skipToNthElement( 3 )
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.skipToNthElement( 6 )
 | 
			
		||||
# Generators internals
 | 
			
		||||
ok {test-number} - gen.get() == 123 for: 123 == 123
 | 
			
		||||
# Generators internals
 | 
			
		||||
@@ -4627,5 +4641,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
 | 
			
		||||
ok {test-number} -
 | 
			
		||||
# xmlentitycheck
 | 
			
		||||
ok {test-number} -
 | 
			
		||||
1..2315
 | 
			
		||||
1..2322
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1428,6 +1428,20 @@ ok {test-number} - 4u * i > str.size() for: 12 > 1
 | 
			
		||||
ok {test-number} - 4u * i > str.size() for: 12 > 2
 | 
			
		||||
# Generators -- simple
 | 
			
		||||
ok {test-number} - 4u * i > str.size() for: 12 > 3
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.currentElementIndex() == 0 for: 0 == 0
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.currentElementIndex() == 3 for: 3 == 3
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.get() == 3 for: 3 == 3
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.currentElementIndex() == 5 for: 5 == 5
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.get() == 5 for: 5 == 5
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.skipToNthElement( 3 )
 | 
			
		||||
# Generators can be skipped forward
 | 
			
		||||
ok {test-number} - generator.skipToNthElement( 6 )
 | 
			
		||||
# Generators internals
 | 
			
		||||
ok {test-number} - gen.get() == 123 for: 123 == 123
 | 
			
		||||
# Generators internals
 | 
			
		||||
@@ -4616,5 +4630,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0
 | 
			
		||||
ok {test-number} -
 | 
			
		||||
# xmlentitycheck
 | 
			
		||||
ok {test-number} -
 | 
			
		||||
1..2315
 | 
			
		||||
1..2322
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -414,6 +414,8 @@
 | 
			
		||||
##teamcity[testFinished name='Generators -- adapters' duration="{duration}"]
 | 
			
		||||
##teamcity[testStarted name='Generators -- simple']
 | 
			
		||||
##teamcity[testFinished name='Generators -- simple' duration="{duration}"]
 | 
			
		||||
##teamcity[testStarted name='Generators can be skipped forward']
 | 
			
		||||
##teamcity[testFinished name='Generators can be skipped forward' duration="{duration}"]
 | 
			
		||||
##teamcity[testStarted name='Generators internals']
 | 
			
		||||
##teamcity[testFinished name='Generators internals' duration="{duration}"]
 | 
			
		||||
##teamcity[testStarted name='Greater-than inequalities with different epsilons']
 | 
			
		||||
 
 | 
			
		||||
@@ -414,6 +414,8 @@
 | 
			
		||||
##teamcity[testFinished name='Generators -- adapters' duration="{duration}"]
 | 
			
		||||
##teamcity[testStarted name='Generators -- simple']
 | 
			
		||||
##teamcity[testFinished name='Generators -- simple' duration="{duration}"]
 | 
			
		||||
##teamcity[testStarted name='Generators can be skipped forward']
 | 
			
		||||
##teamcity[testFinished name='Generators can be skipped forward' duration="{duration}"]
 | 
			
		||||
##teamcity[testStarted name='Generators internals']
 | 
			
		||||
##teamcity[testFinished name='Generators internals' duration="{duration}"]
 | 
			
		||||
##teamcity[testStarted name='Greater-than inequalities with different epsilons']
 | 
			
		||||
 
 | 
			
		||||
@@ -6605,6 +6605,65 @@ Approx( 1.30000000000000004 )
 | 
			
		||||
    </Section>
 | 
			
		||||
    <OverallResult success="true" skips="0"/>
 | 
			
		||||
  </TestCase>
 | 
			
		||||
  <TestCase name="Generators can be skipped forward" tags="[generators]" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
    <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.currentElementIndex() == 0
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        0 == 0
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.currentElementIndex() == 3
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        3 == 3
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.get() == 3
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        3 == 3
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.currentElementIndex() == 5
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        5 == 5
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.get() == 5
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        5 == 5
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <Expression success="true" type="REQUIRE_THROWS" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.skipToNthElement( 3 )
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        generator.skipToNthElement( 3 )
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <Expression success="true" type="REQUIRE_THROWS" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.skipToNthElement( 6 )
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        generator.skipToNthElement( 6 )
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <OverallResult success="true" skips="0"/>
 | 
			
		||||
  </TestCase>
 | 
			
		||||
  <TestCase name="Generators internals" tags="[generators][internals]" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
    <Section name="Single value" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
@@ -22324,6 +22383,6 @@ Approx( -1.95996398454005449 )
 | 
			
		||||
    </Section>
 | 
			
		||||
    <OverallResult success="true" skips="0"/>
 | 
			
		||||
  </TestCase>
 | 
			
		||||
  <OverallResults successes="2105" failures="157" expectedFailures="41" skips="12"/>
 | 
			
		||||
  <OverallResultsCases successes="317" failures="95" expectedFailures="17" skips="6"/>
 | 
			
		||||
  <OverallResults successes="2112" failures="157" expectedFailures="41" skips="12"/>
 | 
			
		||||
  <OverallResultsCases successes="318" failures="95" expectedFailures="17" skips="6"/>
 | 
			
		||||
</Catch2TestRun>
 | 
			
		||||
 
 | 
			
		||||
@@ -6605,6 +6605,65 @@ Approx( 1.30000000000000004 )
 | 
			
		||||
    </Section>
 | 
			
		||||
    <OverallResult success="true" skips="0"/>
 | 
			
		||||
  </TestCase>
 | 
			
		||||
  <TestCase name="Generators can be skipped forward" tags="[generators]" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
    <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.currentElementIndex() == 0
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        0 == 0
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.currentElementIndex() == 3
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        3 == 3
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.get() == 3
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        3 == 3
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.currentElementIndex() == 5
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        5 == 5
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.get() == 5
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        5 == 5
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <Expression success="true" type="REQUIRE_THROWS" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.skipToNthElement( 3 )
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        generator.skipToNthElement( 3 )
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <Expression success="true" type="REQUIRE_THROWS" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Original>
 | 
			
		||||
        generator.skipToNthElement( 6 )
 | 
			
		||||
      </Original>
 | 
			
		||||
      <Expanded>
 | 
			
		||||
        generator.skipToNthElement( 6 )
 | 
			
		||||
      </Expanded>
 | 
			
		||||
    </Expression>
 | 
			
		||||
    <OverallResult success="true" skips="0"/>
 | 
			
		||||
  </TestCase>
 | 
			
		||||
  <TestCase name="Generators internals" tags="[generators][internals]" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
    <Section name="Single value" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
      <Expression success="true" type="REQUIRE" filename="tests/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
 | 
			
		||||
@@ -22323,6 +22382,6 @@ Approx( -1.95996398454005449 )
 | 
			
		||||
    </Section>
 | 
			
		||||
    <OverallResult success="true" skips="0"/>
 | 
			
		||||
  </TestCase>
 | 
			
		||||
  <OverallResults successes="2105" failures="157" expectedFailures="41" skips="12"/>
 | 
			
		||||
  <OverallResultsCases successes="317" failures="95" expectedFailures="17" skips="6"/>
 | 
			
		||||
  <OverallResults successes="2112" failures="157" expectedFailures="41" skips="12"/>
 | 
			
		||||
  <OverallResultsCases successes="318" failures="95" expectedFailures="17" skips="6"/>
 | 
			
		||||
</Catch2TestRun>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
// SPDX-License-Identifier: BSL-1.0
 | 
			
		||||
 | 
			
		||||
#include <catch2/catch_test_macros.hpp>
 | 
			
		||||
#include <catch2/generators/catch_generators.hpp>
 | 
			
		||||
#include <catch2/internal/catch_enforce.hpp>
 | 
			
		||||
#include <catch2/internal/catch_case_insensitive_comparisons.hpp>
 | 
			
		||||
#include <catch2/internal/catch_optional.hpp>
 | 
			
		||||
@@ -170,3 +171,64 @@ TEST_CASE( "Decomposer checks that the argument is 0 when handling "
 | 
			
		||||
 | 
			
		||||
    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_CASE( "foo", "[approvals]" ) {
 | 
			
		||||
    SECTION( "A" ) {
 | 
			
		||||
        SECTION( "B1" ) { REQUIRE( true ); }
 | 
			
		||||
        SECTION( "B2" ) { REQUIRE( true ); }
 | 
			
		||||
        SECTION( "B3" ) { REQUIRE( true ); }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE( "bar", "[approvals]" ) {
 | 
			
		||||
    REQUIRE( true );
 | 
			
		||||
    SECTION( "A" ) {
 | 
			
		||||
        SECTION( "B1" ) { REQUIRE( true ); }
 | 
			
		||||
        SECTION( "B2" ) { REQUIRE( true ); }
 | 
			
		||||
        SECTION( "B3" ) { REQUIRE( true ); }
 | 
			
		||||
    }
 | 
			
		||||
    REQUIRE( true );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE( "baz", "[approvals]" ) {
 | 
			
		||||
    SECTION( "A" ) { REQUIRE( true ); }
 | 
			
		||||
    auto _ = GENERATE( 1, 2, 3 );
 | 
			
		||||
    (void)_;
 | 
			
		||||
    SECTION( "B" ) { REQUIRE( true ); }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE( "qux", "[approvals]" ) {
 | 
			
		||||
    REQUIRE( true );
 | 
			
		||||
    SECTION( "A" ) { REQUIRE( true ); }
 | 
			
		||||
    auto _ = GENERATE( 1, 2, 3 );
 | 
			
		||||
    (void)_;
 | 
			
		||||
    SECTION( "B" ) { REQUIRE( true ); }
 | 
			
		||||
    REQUIRE( true );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE( "corge", "[approvals]" ) {
 | 
			
		||||
    REQUIRE( true );
 | 
			
		||||
    SECTION( "A" ) {
 | 
			
		||||
        REQUIRE( true );
 | 
			
		||||
    }
 | 
			
		||||
    auto i = GENERATE( 1, 2, 3 );
 | 
			
		||||
    DYNAMIC_SECTION( "i=" << i ) {
 | 
			
		||||
        REQUIRE( true );
 | 
			
		||||
    }
 | 
			
		||||
    REQUIRE( true );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("grault", "[approvals]") {
 | 
			
		||||
    REQUIRE( true );
 | 
			
		||||
    SECTION( "A" ) {
 | 
			
		||||
        REQUIRE( true );
 | 
			
		||||
    }
 | 
			
		||||
    SECTION("B") {
 | 
			
		||||
        auto i = GENERATE( 1, 2, 3 );
 | 
			
		||||
        DYNAMIC_SECTION( "i=" << i ) {
 | 
			
		||||
            REQUIRE( true );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    REQUIRE( true );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -85,7 +85,7 @@ TEST_CASE("Generators internals", "[generators][internals]") {
 | 
			
		||||
                filter([](int) { return false; }, values({ 1, 2, 3 })),
 | 
			
		||||
                Catch::GeneratorException);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // Non-trivial usage
 | 
			
		||||
        SECTION("Out-of-line predicates are copied into the generator") {
 | 
			
		||||
            auto evilNumber = Catch::Detail::make_unique<int>(2);
 | 
			
		||||
@@ -586,3 +586,21 @@ TEST_CASE("from_range(container) supports ADL begin/end and arrays", "[generator
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE( "Generators can be skipped forward", "[generators]" ) {
 | 
			
		||||
    auto generator = Catch::Generators::FixedValuesGenerator<int>( { 0, 1, 2, 3, 4, 5 } );
 | 
			
		||||
    REQUIRE( generator.currentElementIndex() == 0 );
 | 
			
		||||
 | 
			
		||||
    generator.skipToNthElement( 3 );
 | 
			
		||||
    REQUIRE( generator.currentElementIndex() == 3 );
 | 
			
		||||
    REQUIRE( generator.get() == 3 );
 | 
			
		||||
 | 
			
		||||
    generator.skipToNthElement( 5 );
 | 
			
		||||
    REQUIRE( generator.currentElementIndex() == 5 );
 | 
			
		||||
    REQUIRE( generator.get() == 5 );
 | 
			
		||||
 | 
			
		||||
    // Backwards
 | 
			
		||||
    REQUIRE_THROWS( generator.skipToNthElement( 3 ) );
 | 
			
		||||
    // Past the end
 | 
			
		||||
    REQUIRE_THROWS( generator.skipToNthElement( 6 ) );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -354,27 +354,9 @@ TEST_CASE("#1514: stderr/stdout is not captured in tests aborted by an exception
 | 
			
		||||
    FAIL("1514");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_CASE( "#2025: -c shouldn't cause infinite loop", "[sections][generators][regression][.approvals]" ) {
 | 
			
		||||
    SECTION( "Check cursor from buffer offset" ) {
 | 
			
		||||
        auto bufPos = GENERATE_REF( range( 0, 44 ) );
 | 
			
		||||
        WHEN( "Buffer position is " << bufPos ) { REQUIRE( 1 == 1 ); }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("#2025: original repro", "[sections][generators][regression][.approvals]") {
 | 
			
		||||
    auto fov = GENERATE(true, false);
 | 
			
		||||
    DYNAMIC_SECTION("fov_" << fov) {
 | 
			
		||||
        std::cout << "inside with fov: " << fov << '\n';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST_CASE("#2025: same-level sections", "[sections][generators][regression][.approvals]") {
 | 
			
		||||
    SECTION("A") {
 | 
			
		||||
        SUCCEED();
 | 
			
		||||
    }
 | 
			
		||||
    auto i = GENERATE(1, 2, 3);
 | 
			
		||||
    SECTION("B") {
 | 
			
		||||
        REQUIRE(i < 4);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										128
									
								
								tests/TestScripts/testSectionFiltering.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										128
									
								
								tests/TestScripts/testSectionFiltering.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,128 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
#              Copyright Catch2 Authors
 | 
			
		||||
# Distributed under the Boost Software License, Version 1.0.
 | 
			
		||||
#   (See accompanying file LICENSE.txt or copy at
 | 
			
		||||
#        https://www.boost.org/LICENSE_1_0.txt)
 | 
			
		||||
 | 
			
		||||
# SPDX-License-Identifier: BSL-1.0
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
This test script verifies the behaviour of the legacy section filtering
 | 
			
		||||
using `-c`, `--section` CLI parameters.
 | 
			
		||||
 | 
			
		||||
This is done by having a hardcoded set of test filter + section filter
 | 
			
		||||
combinations, together with the expected number of assertions that will
 | 
			
		||||
be run inside the test for given filter combo.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import subprocess
 | 
			
		||||
import sys
 | 
			
		||||
from typing import Tuple, List
 | 
			
		||||
import xml.etree.ElementTree as ET
 | 
			
		||||
 | 
			
		||||
def make_cli_filter(section_names: Tuple[str, ...]) -> List[str]:
 | 
			
		||||
    final = []
 | 
			
		||||
    for name in section_names:
 | 
			
		||||
        final.append('--section')
 | 
			
		||||
        final.append(name)
 | 
			
		||||
    return final
 | 
			
		||||
 | 
			
		||||
def run_one_test(binary_path: str, test_name: str, section_names: Tuple[str, ...], expected_assertions: int):
 | 
			
		||||
    cmd = [
 | 
			
		||||
      binary_path,
 | 
			
		||||
      '--reporter', 'xml',
 | 
			
		||||
      test_name
 | 
			
		||||
    ]
 | 
			
		||||
    cmd.extend(make_cli_filter(section_names))
 | 
			
		||||
    try:
 | 
			
		||||
        ret = subprocess.run(
 | 
			
		||||
            cmd,
 | 
			
		||||
            stdout=subprocess.PIPE,
 | 
			
		||||
            stderr=subprocess.PIPE,
 | 
			
		||||
            check=True,
 | 
			
		||||
            universal_newlines=True,
 | 
			
		||||
        )
 | 
			
		||||
        stdout = ret.stdout
 | 
			
		||||
    except subprocess.SubprocessError as ex:
 | 
			
		||||
        print('Could not run "{}"'.format(cmd))
 | 
			
		||||
        print("Return code: {}".format(ex.returncode))
 | 
			
		||||
        print("stdout: {}".format(ex.stdout))
 | 
			
		||||
        print("stderr: {}".format(ex.stderr))
 | 
			
		||||
        raise
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        tree = ET.fromstring(stdout)
 | 
			
		||||
    except ET.ParseError as ex:
 | 
			
		||||
        print("Invalid XML: '{}'".format(ex))
 | 
			
		||||
        raise
 | 
			
		||||
 | 
			
		||||
    # Validate that we ran exactly 1 test case, and it passed
 | 
			
		||||
    test_case_stats = tree.find('OverallResultsCases')
 | 
			
		||||
    expected_testcases = {'successes' : '1', 'failures' : '0', 'expectedFailures': '0', 'skips': '0'}
 | 
			
		||||
    assert test_case_stats.attrib == expected_testcases, f'We did not run single passing test case as expected. {test_name}: {test_case_stats.attrib}'
 | 
			
		||||
 | 
			
		||||
    # Validate that we got exactly the expected number of passing assertions
 | 
			
		||||
    expected_assertions = {'successes' : str(expected_assertions), 'failures' : '0', 'expectedFailures': '0', 'skips': '0'}
 | 
			
		||||
    assertion_stats = tree.find('OverallResults')
 | 
			
		||||
    assert assertion_stats.attrib == expected_assertions, f'"{test_name}": {assertion_stats.attrib} vs {expected_assertions}'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Inputs taken from issue #3038
 | 
			
		||||
tests = {
 | 
			
		||||
  'foo': (
 | 
			
		||||
    ((), 3),
 | 
			
		||||
    (('A',), 3),
 | 
			
		||||
    (('A', 'B'), 0),
 | 
			
		||||
    (('A', 'B1'), 1),
 | 
			
		||||
    (('A', 'B2'), 1),
 | 
			
		||||
    (('A', 'B1', 'B2'), 1),
 | 
			
		||||
    (('A', 'B2', 'XXXX'), 1),
 | 
			
		||||
  ),
 | 
			
		||||
  'bar': (
 | 
			
		||||
    ((), 9),
 | 
			
		||||
    (('A',), 9),
 | 
			
		||||
    (('A', 'B1'), 3),
 | 
			
		||||
    (('XXXX',), 2),
 | 
			
		||||
    (('B1',), 2),
 | 
			
		||||
    (('A', 'B1', 'B2'), 3),
 | 
			
		||||
  ),
 | 
			
		||||
  'baz': (
 | 
			
		||||
    ((), 4),
 | 
			
		||||
    (('A',), 1),
 | 
			
		||||
    (('A', 'B'), 1),
 | 
			
		||||
    (('A', 'XXXX'), 1),
 | 
			
		||||
    (('B',), 3),
 | 
			
		||||
    (('XXXX',), 0),
 | 
			
		||||
  ),
 | 
			
		||||
  'qux': (
 | 
			
		||||
    ((), 12),
 | 
			
		||||
    (('A',), 7),
 | 
			
		||||
    (('B',), 9),
 | 
			
		||||
    (('B', 'XXXX'), 9),
 | 
			
		||||
    (('XXXX',), 6),
 | 
			
		||||
  ),
 | 
			
		||||
  'corge': (
 | 
			
		||||
    ((), 12),
 | 
			
		||||
    (('i=2',), 7),
 | 
			
		||||
    (('i=3',), 7),
 | 
			
		||||
  ),
 | 
			
		||||
  'grault': (
 | 
			
		||||
    ((), 12),
 | 
			
		||||
    (('A',), 3),
 | 
			
		||||
    (('B',), 9),
 | 
			
		||||
    (('B', 'i=1'), 7),
 | 
			
		||||
    (('B', 'XXXX'), 6),
 | 
			
		||||
  ),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if len(sys.argv) != 2:
 | 
			
		||||
    print("Wrong number of arguments, expected just the path to Catch2 SelfTest binary")
 | 
			
		||||
    exit(1)
 | 
			
		||||
 | 
			
		||||
bin_path = os.path.abspath(sys.argv[1])
 | 
			
		||||
 | 
			
		||||
for test_filter, specs in tests.items():
 | 
			
		||||
    for section_path, expected_assertions in specs:
 | 
			
		||||
        run_one_test(bin_path, test_filter, section_path, expected_assertions)
 | 
			
		||||
		Reference in New Issue
	
	Block a user