(
x & 0xFF'FF'FF'FF ) std::uint64_t lhs_low =
Digits( lhs ); std::uint64_t rhs_low =
Digits( rhs ); std::uint64_t low_low = ( lhs_low * rhs_low ); std::uint64_t high_high =
CarryBits( lhs ) *
CarryBits( rhs ); std::uint64_t high_low = (
CarryBits( lhs ) * rhs_low ) +
CarryBits( low_low ); std::uint64_t low_high = ( lhs_low *
CarryBits( rhs ) ) +
Digits( high_low );
return { high_high +
CarryBits( high_low ) +
CarryBits( low_high ), ( low_high << 32 ) |
Digits( low_low ) };#undef
CarryBits#undef
Digits }
inline ExtendedMultResult<std::uint64_t> extendedMult( std::uint64_t lhs, std::uint64_t rhs ) {#
if defined( CATCH_CONFIG_UINT128 )
auto result = __uint128_t( lhs ) * __uint128_t( rhs );
return {
static_cast<std::uint64_t
>( result >> 64 ),
static_cast<std::uint64_t
>( result ) };#elif defined( CATCH_CONFIG_MSVC_UMUL128 ) std::uint64_t high; std::uint64_t low = _umul128( lhs, rhs, &high );
return { high, low };#
else return extendedMultPortable( lhs, rhs );#endif }
template <
typename UInt>
constexpr ExtendedMultResult<UInt> extendedMult( UInt lhs, UInt rhs ) {
static_assert( std::is_unsigned<UInt>::value,
"extendedMult can only handle unsigned integers" );
static_assert(
sizeof( UInt ) <
sizeof( std::uint64_t ),
"Generic extendedMult can only handle types smaller " "than uint64_t" );
using WideType = DoubleWidthUnsignedType_t<UInt>;
auto result = WideType( lhs ) * WideType( rhs );
return {
static_cast<UInt
>( result >> ( CHAR_BIT *
sizeof( UInt ) ) ),
static_cast<UInt
>( result & UInt( -1 ) ) }; }
template <
typename TargetType,
typename Generator> std::enable_if_t<
sizeof(
typename Generator::result_type) >=
sizeof(TargetType), TargetType> fillBitsFrom(Generator& gen) {
using gresult_type =
typename Generator::result_type;
static_assert( std::is_unsigned<TargetType>::value,
"Only unsigned integers are supported" );
static_assert( Generator::min() == 0 && Generator::max() ==
static_cast<gresult_type
>( -1 ),
"Generator must be able to output all numbers in its result type (effectively it must be a random bit generator)" );
constexpr auto generated_bits =
sizeof( gresult_type ) * CHAR_BIT;
constexpr auto return_bits =
sizeof( TargetType ) * CHAR_BIT;
return static_cast<TargetType
>( gen() >> ( generated_bits - return_bits) ); }
template <
typename TargetType,
typename Generator> std::enable_if_t<
sizeof(
typename Generator::result_type) <
sizeof(TargetType), TargetType> fillBitsFrom(Generator& gen) {
using gresult_type =
typename Generator::result_type;
static_assert( std::is_unsigned<TargetType>::value,
"Only unsigned integers are supported" );
static_assert( Generator::min() == 0 && Generator::max() ==
static_cast<gresult_type
>( -1 ),
"Generator must be able to output all numbers in its result type (effectively it must be a random bit generator)" );
constexpr auto generated_bits =
sizeof( gresult_type ) * CHAR_BIT;
constexpr auto return_bits =
sizeof( TargetType ) * CHAR_BIT; std::size_t filled_bits = 0; TargetType ret = 0;
do { ret <<= generated_bits; ret |= gen(); filled_bits += generated_bits; }
while ( filled_bits < return_bits );
return ret; }
template <
typename OriginalType,
typename Un
signedType>
constexpr std::enable_if_t<std::is_signed<OriginalType>::value, UnsignedType> transposeToNaturalOrder( UnsignedType in ) {
static_assert(
sizeof( OriginalType ) ==
sizeof( UnsignedType ),
"reordering requires the same sized types on both sides" );
static_assert( std::is_unsigned<UnsignedType>::value,
"Input type must be unsigned" );
constexpr auto highest_bit = UnsignedType( 1 ) << (
sizeof( UnsignedType ) * CHAR_BIT - 1 );
return static_cast<UnsignedType
>( in ^ highest_bit ); }
template <
typename OriginalType,
typename Un
signedType>
constexpr std::enable_if_t<std::is_unsigned<OriginalType>::value, UnsignedType> transposeToNaturalOrder(UnsignedType in) {
static_assert(
sizeof( OriginalType ) ==
sizeof( UnsignedType ),
"reordering requires the same sized types on both sides" );
static_assert( std::is_unsigned<UnsignedType>::value,
"Input type must be unsigned" );
return in; } } } #endif
namespace Catch {
template <
typename IntegerType>
class uniform_integer_distribution {
static_assert(std::is_integral<IntegerType>::value,
"...");
using UnsignedIntegerType = Detail::SizedUnsignedType_t<
sizeof(IntegerType)>; UnsignedIntegerType m_a; UnsignedIntegerType m_ab_distance; UnsignedIntegerType m_rejection_threshold = 0;
static constexpr UnsignedIntegerType computeDistance(IntegerType a, IntegerType b) {
return transposeTo(b) - transposeTo(a) + 1; }
static constexpr UnsignedIntegerType computeRejectionThreshold(UnsignedIntegerType ab_distance) {
if ( ab_distance == 0 ) {
return 0; }
return ( ~ab_distance + 1 ) % ab_distance; }
static constexpr UnsignedIntegerType transposeTo(IntegerType in) {
return Detail::transposeToNaturalOrder<IntegerType>(
static_cast<UnsignedIntegerType
>( in ) ); }
static constexpr IntegerType transposeBack(UnsignedIntegerType in) {
return static_cast<IntegerType
>( Detail::transposeToNaturalOrder<IntegerType>(in) ); }
public:
using result_type = IntegerType;
constexpr uniform_integer_distribution( IntegerType a, IntegerType b ): m_a( transposeTo(a) ), m_ab_distance( computeDistance(a, b) ), m_rejection_threshold( computeRejectionThreshold(m_ab_distance) ) { assert( a <= b ); }
template <
typename Generator>
constexpr result_type operator()( Generator& g ) {
if ( m_ab_distance == 0 ) {
return transposeBack( Detail::fillBitsFrom<UnsignedIntegerType>( g ) ); }
auto random_number = Detail::fillBitsFrom<UnsignedIntegerType>( g );
auto emul = Detail::extendedMult( random_number, m_ab_distance );
while (emul.lower < m_rejection_threshold) { random_number = Detail::fillBitsFrom<UnsignedIntegerType>( g ); emul = Detail::extendedMult( random_number, m_ab_distance ); }
return transposeBack(m_a + emul.upper); }
constexpr result_type a()
const {
return transposeBack(m_a); }
constexpr result_type b()
const {
return transposeBack(m_ab_distance + m_a - 1); }};} #endif #ifndef CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED#define CATCH_UNIFORM_FLOATING_POINT_DISTRIBUTION_HPP_INCLUDED#ifndef CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED#define CATCH_RANDOM_FLOATING_POINT_HELPERS_HPP_INCLUDED#ifndef CATCH_POLYFILLS_HPP_INCLUDED#define CATCH_POLYFILLS_HPP_INCLUDEDnamespace Catch {
bool isnan(
float f);
bool isnan(
double d);
float nextafter(
float x,
float y);
double nextafter(
double x,
double y);}#endif #include <cassert>#include <cmath>#include <cstdint>#include <limits>#include <type_traits>
namespace Catch {
namespace Detail {
template <
typename FloatType> FloatType gamma(FloatType a, FloatType b) {
static_assert( std::is_floating_point<FloatType>::value,
"gamma returns the largest ULP magnitude within " "floating point range [a, b]. This only makes sense " "for floating point types" ); assert( a <= b );
const auto gamma_up =
Catch::nextafter( a, std::numeric_limits<FloatType>::infinity() ) - a;
const auto gamma_down = b -
Catch::nextafter( b, -std::numeric_limits<FloatType>::infinity() );
return gamma_up < gamma_down ? gamma_down : gamma_up; } template <typename FloatingPoint>
struct DistanceTypePicker;
template <>
struct DistanceTypePicker<float> {
using type = std::uint32_t; };
template <>
struct DistanceTypePicker<double> {
using type = std::uint64_t; };
template <
typename T>
using DistanceType =
typename DistanceTypePicker<T>::type;#
if defined( __GNUC__ ) || defined( __clang__ )
# pragma GCC diagnostic push# pragma GCC diagnostic ignored "-Wfloat-equal"#endif template <typename FloatType> DistanceType<FloatType> count_equidistant_floats( FloatType a, FloatType b, FloatType distance ) { assert( a <= b ); const auto ag = a / distance; const auto bg = b / distance; const auto s = bg - ag; const auto err = ( std::fabs( a ) <= std::fabs( b ) ) ? -ag - ( s - bg ) : bg - ( s + ag ); const auto ceil_s = static_cast<DistanceType<FloatType>>( std::ceil( s ) ); return ( ceil_s != s ) ? ceil_s : ceil_s + ( err > 0 ); }#if defined( __GNUC__ ) || defined( __clang__ )# pragma GCC diagnostic pop#endif }} #endif #include <cmath>#include <type_traits>namespace Catch { namespace Detail {#if defined( __GNUC__ ) || defined( __clang__ )# pragma GCC diagnostic push# pragma GCC diagnostic ignored "-Wfloat-equal"#endif constexpr std::uint64_t calculate_max_steps_in_one_go(double gamma) { if ( gamma == 1.99584030953472e+292 ) { return 9007199254740991; } return static_cast<std::uint64_t>( -1 ); } constexpr std::uint32_t calculate_max_steps_in_one_go(float gamma) { if ( gamma == 2.028241e+31f ) { return 16777215; } return static_cast<std::uint32_t>( -1 ); }#if defined( __GNUC__ ) || defined( __clang__ )# pragma GCC diagnostic pop#endif }template <typename FloatType>class uniform_floating_point_distribution { static_assert(std::is_floating_point<FloatType>::value, "..."); static_assert(!std::is_same<FloatType, long double>::value, "We do not support long double due to inconsistent behaviour between platforms"); using WidthType = Detail::DistanceType<FloatType>; FloatType m_a, m_b; FloatType m_ulp_magnitude; WidthType m_floats_in_range; uniform_integer_distribution<WidthType> m_int_dist; WidthType m_max_steps_in_one_go; bool m_a_has_leq_magnitude;public: using result_type = FloatType; uniform_floating_point_distribution( FloatType a, FloatType b ): m_a( a ), m_b( b ), m_ulp_magnitude( Detail::gamma( m_a, m_b ) ), m_floats_in_range( Detail::count_equidistant_floats( m_a, m_b, m_ulp_magnitude ) ), m_int_dist(0, m_floats_in_range), m_max_steps_in_one_go( Detail::calculate_max_steps_in_one_go(m_ulp_magnitude)), m_a_has_leq_magnitude(std::fabs(m_a) <= std::fabs(m_b)) { assert( a <= b ); } template <typename Generator> result_type operator()( Generator& g ) { WidthType steps = m_int_dist( g ); if ( m_a_has_leq_magnitude ) { if ( steps == m_floats_in_range ) { return m_a; } auto b = m_b; while (steps > m_max_steps_in_one_go) { b -= m_max_steps_in_one_go * m_ulp_magnitude; steps -= m_max_steps_in_one_go; } return b - steps * m_ulp_magnitude; } else { if ( steps == m_floats_in_range ) { return m_b; } auto a = m_a; while (steps > m_max_steps_in_one_go) { a += m_max_steps_in_one_go * m_ulp_magnitude; steps -= m_max_steps_in_one_go; } return a + steps * m_ulp_magnitude; } } result_type a() const { return m_a; } result_type b() const { return m_b; }};} #endif namespace Catch {namespace Generators {namespace Detail { std::uint32_t getSeed();}template <typename Float>class RandomFloatingGenerator final : public IGenerator<Float> { Catch::SimplePcg32 m_rng; Catch::uniform_floating_point_distribution<Float> m_dist; Float m_current_number;public: RandomFloatingGenerator( Float a, Float b, std::uint32_t seed ): m_rng(seed), m_dist(a, b) { static_cast<void>(next()); } Float const& get() const override { return m_current_number; } bool next() override { m_current_number = m_dist(m_rng); return true; }};template <>class RandomFloatingGenerator<long double> final : public IGenerator<long double> { struct PImpl; Catch::Detail::unique_ptr<PImpl> m_pimpl; long double m_current_number;public: RandomFloatingGenerator( long double a, long double b, std::uint32_t seed ); long double const& get() const override { return m_current_number; } bool next() override; ~RandomFloatingGenerator() override; };template <typename Integer>class RandomIntegerGenerator final : public IGenerator<Integer> { Catch::SimplePcg32 m_rng; Catch::uniform_integer_distribution<Integer> m_dist; Integer m_current_number;public: RandomIntegerGenerator( Integer a, Integer b, std::uint32_t seed ): m_rng(seed), m_dist(a, b) { static_cast<void>(next()); } Integer const& get() const override { return m_current_number; } bool next() override { m_current_number = m_dist(m_rng); return true; }};template <typename T>std::enable_if_t<std::is_integral<T>::value, GeneratorWrapper<T>>random(T a, T b) { return GeneratorWrapper<T>( Catch::Detail::make_unique<RandomIntegerGenerator<T>>(a, b, Detail::getSeed()) );}template <typename T>std::enable_if_t<std::is_floating_point<T>::value,GeneratorWrapper<T>>random(T a, T b) { return GeneratorWrapper<T>( Catch::Detail::make_unique<RandomFloatingGenerator<T>>(a, b, Detail::getSeed()) );}} } #endif #ifndef CATCH_GENERATORS_RANGE_HPP_INCLUDED#define CATCH_GENERATORS_RANGE_HPP_INCLUDED#include <iterator>#include <type_traits>namespace Catch {namespace Generators {template <typename T>class RangeGenerator final : public IGenerator<T> { T m_current; T m_end; T m_step; bool m_positive;public: RangeGenerator(T const& start, T const& end, T const& step): m_current(start), m_end(end), m_step(step), m_positive(m_step > T(0)) { assert(m_current != m_end && "Range start and end cannot be equal"); assert(m_step != T(0) && "Step size cannot be zero"); assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end"); } RangeGenerator(T const& start, T const& end): RangeGenerator(start, end, (start < end) ? T(1) : T(-1)) {} T const& get() const override { return m_current; } bool next() override { m_current += m_step; return (m_positive) ? (m_current < m_end) : (m_current > m_end); }};template <typename T>GeneratorWrapper<T> range(T const& start, T const& end, T const& step) { static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric"); return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end, step));}template <typename T>GeneratorWrapper<T> range(T const& start, T const& end) { static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer"); return GeneratorWrapper<T>(Catch::Detail::make_unique<RangeGenerator<T>>(start, end));}template <typename T>class IteratorGenerator final : public IGenerator<T> { static_assert(!std::is_same<T, bool>::value, "IteratorGenerator currently does not support bools" "because of std::vector<bool> specialization"); std::vector<T> m_elems; size_t m_current = 0;public: template <typename InputIterator, typename InputSentinel> IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) { if (m_elems.empty()) { Detail::throw_generator_exception("IteratorGenerator received no valid values"); } } T const& get() const override { return m_elems[m_current]; } bool next() override { ++m_current; return m_current != m_elems.size(); }};template <typename InputIterator, typename InputSentinel, typename ResultType = std::remove_const_t<typename std::iterator_traits<InputIterator>::value_type>>GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) { return GeneratorWrapper<ResultType>(Catch::Detail::make_unique<IteratorGenerator<ResultType>>(from, to));}template <typename Container>auto from_range(Container const& cnt) { using std::begin; using std::end; return from_range( begin( cnt ), end( cnt ) );}} } #endif #endif #ifndef CATCH_INTERFACES_ALL_HPP_INCLUDED#define CATCH_INTERFACES_ALL_HPP_INCLUDED#ifndef CATCH_INTERFACES_REPORTER_HPP_INCLUDED#define CATCH_INTERFACES_REPORTER_HPP_INCLUDED#ifndef CATCH_TEST_RUN_INFO_HPP_INCLUDED#define CATCH_TEST_RUN_INFO_HPP_INCLUDEDnamespace Catch { struct TestRunInfo { constexpr TestRunInfo(StringRef _name) : name(_name) {} StringRef name; };} #endif #include <map>#include <string>#include <vector>#include <iosfwd>namespace Catch { struct ReporterDescription; struct ListenerDescription; struct TagInfo; struct TestCaseInfo; class TestCaseHandle; class IConfig; class IStream; enum class ColourMode : std::uint8_t; struct ReporterConfig { ReporterConfig( IConfig const* _fullConfig, Detail::unique_ptr<IStream> _stream, ColourMode colourMode, std::map<std::string, std::string> customOptions ); ReporterConfig( ReporterConfig&& ) = default; ReporterConfig& operator=( ReporterConfig&& ) = default; ~ReporterConfig(); Detail::unique_ptr<IStream> takeStream() &&; IConfig const* fullConfig() const; ColourMode colourMode() const; std::map<std::string, std::string> const& customOptions() const; private: Detail::unique_ptr<IStream> m_stream; IConfig const* m_fullConfig; ColourMode m_colourMode; std::map<std::string, std::string> m_customOptions; }; struct AssertionStats { AssertionStats( AssertionResult const& _assertionResult, std::vector<MessageInfo> const& _infoMessages, Totals const& _totals ); AssertionStats( AssertionStats const& ) = default; AssertionStats( AssertionStats && ) = default; AssertionStats& operator = ( AssertionStats const& ) = delete; AssertionStats& operator = ( AssertionStats && ) = delete; AssertionResult assertionResult; std::vector<MessageInfo> infoMessages; Totals totals; }; struct SectionStats { SectionStats( SectionInfo&& _sectionInfo, Counts const& _assertions, double _durationInSeconds, bool _missingAssertions ); SectionInfo sectionInfo; Counts assertions; double durationInSeconds; bool missingAssertions; }; struct TestCaseStats { TestCaseStats( TestCaseInfo const& _testInfo, Totals const& _totals, std::string&& _stdOut, std::string&& _stdErr, bool _aborting ); TestCaseInfo const * testInfo; Totals totals; std::string stdOut; std::string stdErr; bool aborting; }; struct TestRunStats { TestRunStats( TestRunInfo const& _runInfo, Totals const& _totals, bool _aborting ); TestRunInfo runInfo; Totals totals; bool aborting; }; struct ReporterPreferences { bool shouldRedirectStdOut = false; bool shouldReportAllAssertions = false; }; class IEventListener { protected: ReporterPreferences m_preferences; IConfig const* m_config; public: IEventListener( IConfig const* config ): m_config( config ) {} virtual ~IEventListener(); ReporterPreferences const& getPreferences() const { return m_preferences; } virtual void noMatchingTestCases( StringRef unmatchedSpec ) = 0; virtual void reportInvalidTestSpec( StringRef invalidArgument ) = 0; virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; virtual void testCasePartialStarting( TestCaseInfo const& testInfo, uint64_t partNumber ) = 0; virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; virtual void benchmarkPreparing( StringRef benchmarkName ) = 0; virtual void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) = 0; virtual void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) = 0; virtual void benchmarkFailed( StringRef benchmarkName ) = 0; virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; virtual void assertionEnded( AssertionStats const& assertionStats ) = 0; virtual void sectionEnded( SectionStats const& sectionStats ) = 0; virtual void testCasePartialEnded(TestCaseStats const& testCaseStats, uint64_t partNumber ) = 0; virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; virtual void skipTest( TestCaseInfo const& testInfo ) = 0; virtual void fatalErrorEncountered( StringRef error ) = 0; virtual void listReporters(std::vector<ReporterDescription> const& descriptions) = 0; virtual void listListeners(std::vector<ListenerDescription> const& descriptions) = 0; virtual void listTests(std::vector<TestCaseHandle> const& tests) = 0; virtual void listTags(std::vector<TagInfo> const& tags) = 0; }; using IEventListenerPtr = Detail::unique_ptr<IEventListener>;} #endif #ifndef CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED#define CATCH_INTERFACES_REPORTER_FACTORY_HPP_INCLUDED#include <string>namespace Catch { struct ReporterConfig; class IConfig; class IEventListener; using IEventListenerPtr = Detail::unique_ptr<IEventListener>; class IReporterFactory { public: virtual ~IReporterFactory(); virtual IEventListenerPtr create( ReporterConfig&& config ) const = 0; virtual std::string getDescription() const = 0; }; using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>; class EventListenerFactory { public: virtual ~EventListenerFactory(); virtual IEventListenerPtr create( IConfig const* config ) const = 0; virtual StringRef getName() const = 0; virtual std::string getDescription() const = 0; };} #endif #ifndef CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED#define CATCH_INTERFACES_TAG_ALIAS_REGISTRY_HPP_INCLUDED#include <string>namespace Catch { struct TagAlias; class ITagAliasRegistry { public: virtual ~ITagAliasRegistry(); virtual TagAlias const* find( std::string const& alias ) const = 0; virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; static ITagAliasRegistry const& get(); };} #endif #ifndef CATCH_INTERFACES_TESTCASE_HPP_INCLUDED#define CATCH_INTERFACES_TESTCASE_HPP_INCLUDED#include <vector>namespace Catch { struct TestCaseInfo; class TestCaseHandle; class IConfig; class ITestCaseRegistry { public: virtual ~ITestCaseRegistry(); virtual std::vector<TestCaseInfo* > const& getAllInfos() const = 0; virtual std::vector<TestCaseHandle> const& getAllTests() const = 0; virtual std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const = 0; };}#endif #endif #ifndef CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDED#define CATCH_CASE_INSENSITIVE_COMPARISONS_HPP_INCLUDEDnamespace Catch { namespace Detail { struct CaseInsensitiveLess { bool operator()( StringRef lhs, StringRef rhs ) const; }; struct CaseInsensitiveEqualTo { bool operator()( StringRef lhs, StringRef rhs ) const; }; } } #endif #ifndef CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED#define CATCH_CONFIG_ANDROID_LOGWRITE_HPP_INCLUDED#if defined(__ANDROID__)# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE#endif#if defined( CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE ) && \ !defined( CATCH_CONFIG_NO_ANDROID_LOGWRITE ) && \ !defined( CATCH_CONFIG_ANDROID_LOGWRITE )# define CATCH_CONFIG_ANDROID_LOGWRITE#endif#endif #ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED#if defined(_MSC_VER)# if _MSC_VER >= 1900 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS# endif#endif#include <exception>#if defined(__cpp_lib_uncaught_exceptions) \ && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS#endif #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \ && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \ && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS#endif#endif #ifndef CATCH_CONSOLE_COLOUR_HPP_INCLUDED#define CATCH_CONSOLE_COLOUR_HPP_INCLUDED#include <iosfwd>#include <cstdint>namespace Catch { enum class ColourMode : std::uint8_t; class IStream; struct Colour { enum Code { None = 0, White, Red, Green, Blue, Cyan, Yellow, Grey, Bright = 0x10, BrightRed = Bright | Red, BrightGreen = Bright | Green, LightGrey = Bright | Grey, BrightWhite = Bright | White, BrightYellow = Bright | Yellow, FileName = LightGrey, Warning = BrightYellow, ResultError = BrightRed, ResultSuccess = BrightGreen, ResultExpectedFailure = Warning, Error = BrightRed, Success = Green, Skip = LightGrey, OriginalExpression = Cyan, ReconstructedExpression = BrightYellow, SecondaryText = LightGrey, Headers = White }; }; class ColourImpl { protected: IStream* m_stream; public: ColourImpl( IStream* stream ): m_stream( stream ) {} class ColourGuard { ColourImpl const* m_colourImpl; Colour::Code m_code; bool m_engaged = false; public: ColourGuard( Colour::Code code, ColourImpl const* colour ); ColourGuard( ColourGuard const& rhs ) = delete; ColourGuard& operator=( ColourGuard const& rhs ) = delete; ColourGuard( ColourGuard&& rhs ) noexcept; ColourGuard& operator=( ColourGuard&& rhs ) noexcept; ~ColourGuard(); ColourGuard& engage( std::ostream& stream ) &; ColourGuard&& engage( std::ostream& stream ) &&; private: friend std::ostream& operator<<( std::ostream& lhs, ColourGuard& guard ) { guard.engageImpl( lhs ); return lhs; } friend std::ostream& operator<<( std::ostream& lhs, ColourGuard&& guard) { guard.engageImpl( lhs ); return lhs; } void engageImpl( std::ostream& stream ); }; virtual ~ColourImpl(); ColourGuard guardColour( Colour::Code colourCode ); private: virtual void use( Colour::Code colourCode ) const = 0; }; Detail::unique_ptr<ColourImpl> makeColourImpl( ColourMode colourSelection, IStream* stream ); bool isColourImplAvailable( ColourMode colourSelection );} #endif #ifndef CATCH_CONSOLE_WIDTH_HPP_INCLUDED#define CATCH_CONSOLE_WIDTH_HPP_INCLUDED#ifndef CATCH_CONFIG_CONSOLE_WIDTH#define CATCH_CONFIG_CONSOLE_WIDTH 80#endif#endif #ifndef CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED#define CATCH_CONTAINER_NONMEMBERS_HPP_INCLUDED#include <cstddef>#include <initializer_list>#if defined(CATCH_CPP17_OR_GREATER) || defined(_MSC_VER)#include <string># if !defined(__cpp_lib_nonmember_container_access)# define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS# endif#else#define CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS#endifnamespace Catch {namespace Detail {#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS) template <typename Container> constexpr auto empty(Container const& cont) -> decltype(cont.empty()) { return cont.empty(); } template <typename T, std::size_t N> constexpr bool empty(const T (&)[N]) noexcept { (void)N; return false; } template <typename T> constexpr bool empty(std::initializer_list<T> list) noexcept { return list.size() > 0; } template <typename Container> constexpr auto size(Container const& cont) -> decltype(cont.size()) { return cont.size(); } template <typename T, std::size_t N> constexpr std::size_t size(const T(&)[N]) noexcept { return N; }#endif } } #endif #ifndef CATCH_DEBUG_CONSOLE_HPP_INCLUDED#define CATCH_DEBUG_CONSOLE_HPP_INCLUDED#include <string>namespace Catch { void writeToDebugConsole( std::string const& text );}#endif #ifndef CATCH_DEBUGGER_HPP_INCLUDED#define CATCH_DEBUGGER_HPP_INCLUDEDnamespace Catch { bool isDebuggerActive();}#ifdef CATCH_PLATFORM_MAC #if defined(__i386__) || defined(__x86_64__) #define CATCH_TRAP() __asm__("int $3\n" : : ) #elif defined(__aarch64__) #define CATCH_TRAP() __asm__(".inst 0xd43e0000") #elif defined(__POWERPC__) #define CATCH_TRAP() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ : : : "memory","r0","r3","r4" ) #endif#elif defined(CATCH_PLATFORM_IPHONE) #if defined(__i386__) || defined(__x86_64__) #define CATCH_TRAP() __asm__("int $3") #elif defined(__aarch64__) #define CATCH_TRAP() __asm__(".inst 0xd4200000") #elif defined(__arm__) && !defined(__thumb__) #define CATCH_TRAP() __asm__(".inst 0xe7f001f0") #elif defined(__arm__) && defined(__thumb__) #define CATCH_TRAP() __asm__(".inst 0xde01") #endif#elif defined(CATCH_PLATFORM_LINUX) #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) #define CATCH_TRAP() asm volatile ("int $3") #else #include <signal.h> #define CATCH_TRAP() raise(SIGTRAP) #endif#elif defined(_MSC_VER) #define CATCH_TRAP() __debugbreak()#elif defined(__MINGW32__) extern "C" __declspec(dllimport) void __stdcall DebugBreak(); #define CATCH_TRAP() DebugBreak()#endif#ifndef CATCH_BREAK_INTO_DEBUGGER #ifdef CATCH_TRAP #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }() #else #define CATCH_BREAK_INTO_DEBUGGER() []{}() #endif#endif#endif #ifndef CATCH_ENFORCE_HPP_INCLUDED#define CATCH_ENFORCE_HPP_INCLUDED#include <exception>namespace Catch {#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) template <typename Ex> [[noreturn]] void throw_exception(Ex const& e) { throw e; }#else [[noreturn]] void throw_exception(std::exception const& e);#endif [[noreturn]] void throw_logic_error(std::string const& msg); [[noreturn]] void throw_domain_error(std::string const& msg); [[noreturn]] void throw_runtime_error(std::string const& msg);} #define CATCH_MAKE_MSG(...) \ (Catch::ReusableStringStream() << __VA_ARGS__).str()#define CATCH_INTERNAL_ERROR(...) \ Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__))#define CATCH_ERROR(...) \ Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ ))#define CATCH_RUNTIME_ERROR(...) \ Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ ))#define CATCH_ENFORCE( condition, ... ) \ do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)#endif #ifndef CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED#define CATCH_ENUM_VALUES_REGISTRY_HPP_INCLUDED#include <vector>namespace Catch { namespace Detail { Catch::Detail::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ); class EnumValuesRegistry : public IMutableEnumValuesRegistry { std::vector<Catch::Detail::unique_ptr<EnumInfo>> m_enumInfos; EnumInfo const& registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values) override; }; std::vector<StringRef> parseEnums( StringRef enums ); } } #endif #ifndef CATCH_ERRNO_GUARD_HPP_INCLUDED#define CATCH_ERRNO_GUARD_HPP_INCLUDEDnamespace Catch { class ErrnoGuard { public: ErrnoGuard(); ~ErrnoGuard(); private: int m_oldErrno; };}#endif #ifndef CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED#define CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED#include <vector>#include <string>namespace Catch { class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { public: ~ExceptionTranslatorRegistry() override; void registerTranslator( Detail::unique_ptr<IExceptionTranslator>&& translator ); std::string translateActiveException() const override; private: ExceptionTranslators m_translators; };}#endif #ifndef CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED#define CATCH_FATAL_CONDITION_HANDLER_HPP_INCLUDED#include <cassert>namespace Catch { class FatalConditionHandler { bool m_started = false; void engage_platform(); void disengage_platform() noexcept; public: FatalConditionHandler(); ~FatalConditionHandler(); void engage() { assert(!m_started && "Handler cannot be installed twice."); m_started = true; engage_platform(); } void disengage() noexcept { assert(m_started && "Handler cannot be uninstalled without being installed first"); m_started = false; disengage_platform(); } }; class FatalConditionHandlerGuard { FatalConditionHandler* m_handler; public: FatalConditionHandlerGuard(FatalConditionHandler* handler): m_handler(handler) { m_handler->engage(); } ~FatalConditionHandlerGuard() { m_handler->disengage(); } };} #endif #ifndef CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED#define CATCH_FLOATING_POINT_HELPERS_HPP_INCLUDED#include <cassert>#include <cmath>#include <cstdint>#include <utility>#include <limits>namespace Catch { namespace Detail { uint32_t convertToBits(float f); uint64_t convertToBits(double d); bool directCompare( float lhs, float rhs ); bool directCompare( double lhs, double rhs ); } #if defined( __GNUC__ ) || defined( __clang__ )# pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wfloat-equal"#endif template <typename FP> uint64_t ulpDistance( FP lhs, FP rhs ) { assert( std::numeric_limits<FP>::is_iec559 && "ulpDistance assumes IEEE-754 format for floating point types" ); assert( !Catch::isnan( lhs ) && "Distance between NaN and number is not meaningful" ); assert( !Catch::isnan( rhs ) && "Distance between NaN and number is not meaningful" ); if ( lhs == rhs ) { return 0; } static constexpr FP positive_zero{}; if ( lhs == positive_zero ) { lhs = positive_zero; } if ( rhs == positive_zero ) { rhs = positive_zero; } if ( std::signbit( lhs ) != std::signbit( rhs ) ) { return ulpDistance( std::abs( lhs ), positive_zero ) + ulpDistance( std::abs( rhs ), positive_zero ); } uint64_t lc = Detail::convertToBits( lhs ); uint64_t rc = Detail::convertToBits( rhs ); if ( lc < rc ) { std::swap( lc, rc ); } return lc - rc; }#if defined( __GNUC__ ) || defined( __clang__ )# pragma GCC diagnostic pop#endif} #endif #ifndef CATCH_GETENV_HPP_INCLUDED#define CATCH_GETENV_HPP_INCLUDEDnamespace Catch {namespace Detail { char const* getEnv(char const* varName);}}#endif #ifndef CATCH_IS_PERMUTATION_HPP_INCLUDED#define CATCH_IS_PERMUTATION_HPP_INCLUDED#include <algorithm>#include <iterator>namespace Catch { namespace Detail { template <typename ForwardIter, typename Sentinel, typename T, typename Comparator> constexpr ForwardIter find_sentinel( ForwardIter start, Sentinel sentinel, T const& value, Comparator cmp ) { while ( start != sentinel ) { if ( cmp( *start, value ) ) { break; } ++start; } return start; } template <typename ForwardIter, typename Sentinel, typename T, typename Comparator> constexpr std::ptrdiff_t count_sentinel( ForwardIter start, Sentinel sentinel, T const& value, Comparator cmp ) { std::ptrdiff_t count = 0; while ( start != sentinel ) { if ( cmp( *start, value ) ) { ++count; } ++start; } return count; } template <typename ForwardIter, typename Sentinel> constexpr std::enable_if_t<!std::is_same<ForwardIter, Sentinel>::value, std::ptrdiff_t> sentinel_distance( ForwardIter iter, const Sentinel sentinel ) { std::ptrdiff_t dist = 0; while ( iter != sentinel ) { ++iter; ++dist; } return dist; } template <typename ForwardIter> constexpr std::ptrdiff_t sentinel_distance( ForwardIter first, ForwardIter last ) { return std::distance( first, last ); } template <typename ForwardIter1, typename Sentinel1, typename ForwardIter2, typename Sentinel2, typename Comparator> constexpr bool check_element_counts( ForwardIter1 first_1, const Sentinel1 end_1, ForwardIter2 first_2, const Sentinel2 end_2, Comparator cmp ) { auto cursor = first_1; while ( cursor != end_1 ) { if ( find_sentinel( first_1, cursor, *cursor, cmp ) == cursor ) { const auto count_in_range_2 = count_sentinel( first_2, end_2, *cursor, cmp ); if ( count_in_range_2 == 0 ) { return false; } const auto count_in_range_1 = count_sentinel( cursor, end_1, *cursor, cmp ); if ( count_in_range_1 != count_in_range_2 ) { return false; } } ++cursor; } return true; } template <typename ForwardIter1, typename Sentinel1, typename ForwardIter2, typename Sentinel2, typename Comparator> constexpr bool is_permutation( ForwardIter1 first_1, const Sentinel1 end_1, ForwardIter2 first_2, const Sentinel2 end_2, Comparator cmp ) { while (first_1 != end_1 && first_2 != end_2 && cmp(*first_1, *first_2)) { ++first_1; ++first_2; } if (first_1 == end_1 || first_2 == end_2) { return first_1 == end_1 && first_2 == end_2; } auto dist_1 = sentinel_distance( first_1, end_1 ); auto dist_2 = sentinel_distance( first_2, end_2 ); if (dist_1 != dist_2) { return false; } return check_element_counts( first_1, end_1, first_2, end_2, cmp ); } } } #endif #ifndef CATCH_ISTREAM_HPP_INCLUDED#define CATCH_ISTREAM_HPP_INCLUDED#include <iosfwd>#include <cstddef>#include <ostream>#include <string>namespace Catch { class IStream { public: virtual ~IStream(); virtual std::ostream& stream() = 0; virtual bool isConsole() const { return false; } }; auto makeStream( std::string const& filename ) -> Detail::unique_ptr<IStream>;}#endif #ifndef CATCH_JSONWRITER_HPP_INCLUDED#define CATCH_JSONWRITER_HPP_INCLUDED#include <cstdint>#include <sstream>namespace Catch { class JsonObjectWriter; class JsonArrayWriter; struct JsonUtils { static void indent( std::ostream& os, std::uint64_t level ); static void appendCommaNewline( std::ostream& os, bool& should_comma, std::uint64_t level ); }; class JsonValueWriter { public: JsonValueWriter( std::ostream& os ); JsonValueWriter( std::ostream& os, std::uint64_t indent_level ); JsonObjectWriter writeObject() &&; JsonArrayWriter writeArray() &&; template <typename T> void write( T const& value ) && { writeImpl( value, !std::is_arithmetic<T>::value ); } void write( StringRef value ) &&; void write( bool value ) &&; private: void writeImpl( StringRef value, bool quote ); template <typename T, typename = typename std::enable_if_t< !std::is_convertible<T, StringRef>::value>> void writeImpl( T const& value, bool quote_value ) { m_sstream << value; writeImpl( m_sstream.str(), quote_value ); } std::ostream& m_os; std::stringstream m_sstream; std::uint64_t m_indent_level; }; class JsonObjectWriter { public: JsonObjectWriter( std::ostream& os ); JsonObjectWriter( std::ostream& os, std::uint64_t indent_level ); JsonObjectWriter( JsonObjectWriter&& source ) noexcept; JsonObjectWriter& operator=( JsonObjectWriter&& source ) = delete; ~JsonObjectWriter(); JsonValueWriter write( StringRef key ); private: std::ostream& m_os; std::uint64_t m_indent_level; bool m_should_comma = false; bool m_active = true; }; class JsonArrayWriter { public: JsonArrayWriter( std::ostream& os ); JsonArrayWriter( std::ostream& os, std::uint64_t indent_level ); JsonArrayWriter( JsonArrayWriter&& source ) noexcept; JsonArrayWriter& operator=( JsonArrayWriter&& source ) = delete; ~JsonArrayWriter(); JsonObjectWriter writeObject(); JsonArrayWriter writeArray(); template <typename T> JsonArrayWriter& write( T const& value ) { return writeImpl( value ); } JsonArrayWriter& write( bool value ); private: template <typename T> JsonArrayWriter& writeImpl( T const& value ) { JsonUtils::appendCommaNewline( m_os, m_should_comma, m_indent_level + 1 ); JsonValueWriter{ m_os }.write( value ); return *this; } std::ostream& m_os; std::uint64_t m_indent_level; bool m_should_comma = false; bool m_active = true; };} #endif #ifndef CATCH_LEAK_DETECTOR_HPP_INCLUDED#define CATCH_LEAK_DETECTOR_HPP_INCLUDEDnamespace Catch { struct LeakDetector { LeakDetector(); ~LeakDetector(); };}#endif #ifndef CATCH_LIST_HPP_INCLUDED#define CATCH_LIST_HPP_INCLUDED#include <set>#include <string>namespace Catch { class IEventListener; class Config; struct ReporterDescription { std::string name, description; }; struct ListenerDescription { StringRef name; std::string description; }; struct TagInfo { void add(StringRef spelling); std::string all() const; std::set<StringRef> spellings; std::size_t count = 0; }; bool list( IEventListener& reporter, Config const& config );} #endif #ifndef CATCH_OUTPUT_REDIRECT_HPP_INCLUDED#define CATCH_OUTPUT_REDIRECT_HPP_INCLUDED#include <cassert>#include <string>namespace Catch { class OutputRedirect { bool m_redirectActive = false; virtual void activateImpl() = 0; virtual void deactivateImpl() = 0; public: enum Kind { None, Streams, FileDescriptors, }; virtual ~OutputRedirect(); virtual std::string getStdout() = 0; virtual std::string getStderr() = 0; virtual void clearBuffers() = 0; bool isActive() const { return m_redirectActive; } void activate() { assert( !m_redirectActive && "redirect is already active" ); activateImpl(); m_redirectActive = true; } void deactivate() { assert( m_redirectActive && "redirect is not active" ); deactivateImpl(); m_redirectActive = false; } }; bool isRedirectAvailable( OutputRedirect::Kind kind); Detail::unique_ptr<OutputRedirect> makeOutputRedirect( bool actual ); class RedirectGuard { OutputRedirect* m_redirect; bool m_activate; bool m_previouslyActive; bool m_moved = false; public: RedirectGuard( bool activate, OutputRedirect& redirectImpl ); ~RedirectGuard() noexcept( false ); RedirectGuard( RedirectGuard const& ) = delete; RedirectGuard& operator=( RedirectGuard const& ) = delete; RedirectGuard( RedirectGuard&& rhs ) noexcept; RedirectGuard& operator=( RedirectGuard&& rhs ) noexcept; }; RedirectGuard scopedActivate( OutputRedirect& redirectImpl ); RedirectGuard scopedDeactivate( OutputRedirect& redirectImpl );} #endif #ifndef CATCH_PARSE_NUMBERS_HPP_INCLUDED#define CATCH_PARSE_NUMBERS_HPP_INCLUDED#include <string>namespace Catch { Optional<unsigned int> parseUInt(std::string const& input, int base = 10);}#endif #ifndef CATCH_REPORTER_REGISTRY_HPP_INCLUDED#define CATCH_REPORTER_REGISTRY_HPP_INCLUDED#include <map>#include <string>#include <vector>namespace Catch { class IEventListener; using IEventListenerPtr = Detail::unique_ptr<IEventListener>; class IReporterFactory; using IReporterFactoryPtr = Detail::unique_ptr<IReporterFactory>; struct ReporterConfig; class EventListenerFactory; class ReporterRegistry { struct ReporterRegistryImpl; Detail::unique_ptr<ReporterRegistryImpl> m_impl; public: ReporterRegistry(); ~ReporterRegistry(); IEventListenerPtr create( std::string const& name, ReporterConfig&& config ) const; void registerReporter( std::string const& name, IReporterFactoryPtr factory ); void registerListener( Detail::unique_ptr<EventListenerFactory> factory ); std::map<std::string, IReporterFactoryPtr, Detail::CaseInsensitiveLess> const& getFactories() const; std::vector<Detail::unique_ptr<EventListenerFactory>> const& getListeners() const; };} #endif #ifndef CATCH_RUN_CONTEXT_HPP_INCLUDED#define CATCH_RUN_CONTEXT_HPP_INCLUDED#ifndef CATCH_TEST_CASE_TRACKER_HPP_INCLUDED#define CATCH_TEST_CASE_TRACKER_HPP_INCLUDED#include <string>#include <vector>namespace Catch {namespace TestCaseTracking { struct NameAndLocation { std::string name; SourceLineInfo location; NameAndLocation( std::string&& _name, SourceLineInfo const& _location ); friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) { if ( lhs.location.line != rhs.location.line ) { return false; } return lhs.name == rhs.name && lhs.location == rhs.location; } friend bool operator!=(NameAndLocation const& lhs, NameAndLocation const& rhs) { return !( lhs == rhs ); } }; struct NameAndLocationRef { StringRef name; SourceLineInfo location; constexpr NameAndLocationRef( StringRef name_, SourceLineInfo location_ ): name( name_ ), location( location_ ) {} friend bool operator==( NameAndLocation const& lhs, NameAndLocationRef const& rhs ) { if ( lhs.location.line != rhs.location.line ) { return false; } return StringRef( lhs.name ) == rhs.name && lhs.location == rhs.location; } friend bool operator==( NameAndLocationRef const& lhs, NameAndLocation const& rhs ) { return rhs == lhs; } }; class ITracker; using ITrackerPtr = Catch::Detail::unique_ptr<ITracker>; class ITracker { NameAndLocation m_nameAndLocation; using Children = std::vector<ITrackerPtr>; protected: enum CycleState { NotStarted, Executing, ExecutingChildren, NeedsAnotherRun, CompletedSuccessfully, Failed }; ITracker* m_parent = nullptr; Children m_children; CycleState m_runState = NotStarted; public: ITracker( NameAndLocation&& nameAndLoc, ITracker* parent ): m_nameAndLocation( CATCH_MOVE(nameAndLoc) ), m_parent( parent ) {} NameAndLocation const& nameAndLocation() const { return m_nameAndLocation; } ITracker* parent() const { return m_parent; } virtual ~ITracker(); virtual bool isComplete() const = 0; bool isSuccessfullyCompleted() const { return m_runState == CompletedSuccessfully; } bool isOpen() const; bool hasStarted() const; virtual void close() = 0; virtual void fail() = 0; void markAsNeedingAnotherRun(); void addChild( ITrackerPtr&& child ); ITracker* findChild( NameAndLocationRef const& nameAndLocation ); bool hasChildren() const { return !m_children.empty(); } void openChild(); virtual bool isSectionTracker() const; virtual bool isGeneratorTracker() const; }; class TrackerContext { enum RunState { NotStarted, Executing, CompletedCycle }; ITrackerPtr m_rootTracker; ITracker* m_currentTracker = nullptr; RunState m_runState = NotStarted; public: ITracker& startRun(); void startCycle() { m_currentTracker = m_rootTracker.get(); m_runState = Executing; } void completeCycle(); bool completedCycle() const; ITracker& currentTracker() { return *m_currentTracker; } void setCurrentTracker( ITracker* tracker ); }; class TrackerBase : public ITracker { protected: TrackerContext& m_ctx; public: TrackerBase( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ); bool isComplete() const override; void open(); void close() override; void fail() override; private: void moveToParent(); void moveToThis(); }; class SectionTracker : public TrackerBase { std::vector<StringRef> m_filters; StringRef m_trimmed_name; public: SectionTracker( NameAndLocation&& nameAndLocation, TrackerContext& ctx, ITracker* parent ); bool isSectionTracker() const override; bool isComplete() const override; static SectionTracker& acquire( TrackerContext& ctx, NameAndLocationRef const& nameAndLocation ); void tryOpen(); void addInitialFilters( std::vector<std::string> const& filters ); void addNextFilters( std::vector<StringRef> const& filters ); std::vector<StringRef> const& getFilters() const { return m_filters; } StringRef trimmedName() const; };} using TestCaseTracking::ITracker;using TestCaseTracking::TrackerContext;using TestCaseTracking::SectionTracker;} #endif #include <string>namespace Catch { class IGeneratorTracker; class IConfig; class IEventListener; using IEventListenerPtr = Detail::unique_ptr<IEventListener>; class OutputRedirect; class RunContext final : public IResultCapture { public: RunContext( RunContext const& ) = delete; RunContext& operator =( RunContext const& ) = delete; explicit RunContext( IConfig const* _config, IEventListenerPtr&& reporter ); ~RunContext() override; Totals runTest(TestCaseHandle const& testCase); public: void handleExpr ( AssertionInfo const& info, ITransientExpression const& expr, AssertionReaction& reaction ) override; void handleMessage ( AssertionInfo const& info, ResultWas::OfType resultType, std::string&& message, AssertionReaction& reaction ) override; void handleUnexpectedExceptionNotThrown ( AssertionInfo const& info, AssertionReaction& reaction ) override; void handleUnexpectedInflightException ( AssertionInfo const& info, std::string&& message, AssertionReaction& reaction ) override; void handleIncomplete ( AssertionInfo const& info ) override; void handleNonExpr ( AssertionInfo const &info, ResultWas::OfType resultType, AssertionReaction &reaction ) override; void notifyAssertionStarted( AssertionInfo const& info ) override; bool sectionStarted( StringRef sectionName, SourceLineInfo const& sectionLineInfo, Counts& assertions ) override; void sectionEnded( SectionEndInfo&& endInfo ) override; void sectionEndedEarly( SectionEndInfo&& endInfo ) override; IGeneratorTracker* acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) override; IGeneratorTracker* createGeneratorTracker( StringRef generatorName, SourceLineInfo lineInfo, Generators::GeneratorBasePtr&& generator ) override; void benchmarkPreparing( StringRef name ) override; void benchmarkStarting( BenchmarkInfo const& info ) override; void benchmarkEnded( BenchmarkStats<> const& stats ) override; void benchmarkFailed( StringRef error ) override; void pushScopedMessage( MessageInfo const& message ) override; void popScopedMessage( MessageInfo const& message ) override; void emplaceUnscopedMessage( MessageBuilder&& builder ) override; std::string getCurrentTestName() const override; const AssertionResult* getLastResult() const override; void exceptionEarlyReported() override; void handleFatalErrorCondition( StringRef message ) override; bool lastAssertionPassed() override; void assertionPassed() override; public: bool aborting() const; private: void runCurrentTest(); void invokeActiveTestCase(); void resetAssertionInfo(); bool testForMissingAssertions( Counts& assertions ); void assertionEnded( AssertionResult&& result ); void reportExpr ( AssertionInfo const &info, ResultWas::OfType resultType, ITransientExpression const *expr, bool negated ); void populateReaction( AssertionReaction& reaction ); private: void handleUnfinishedSections(); TestRunInfo m_runInfo; TestCaseHandle const* m_activeTestCase = nullptr; ITracker* m_testCaseTracker = nullptr; Optional<AssertionResult> m_lastResult; IConfig const* m_config; Totals m_totals; IEventListenerPtr m_reporter; std::vector<MessageInfo> m_messages; std::vector<ScopedMessage> m_messageScopes; AssertionInfo m_lastAssertionInfo; std::vector<SectionEndInfo> m_unfinishedSections; std::vector<ITracker*> m_activeSections; TrackerContext m_trackerContext; Detail::unique_ptr<OutputRedirect> m_outputRedirect; FatalConditionHandler m_fatalConditionhandler; bool m_lastAssertionPassed = false; bool m_shouldReportUnexpected = true; bool m_includeSuccessfulResults; }; void seedRng(IConfig const& config); unsigned int rngSeed();} #endif #ifndef CATCH_SHARDING_HPP_INCLUDED#define CATCH_SHARDING_HPP_INCLUDED#include <cassert>#include <cmath>#include <algorithm>namespace Catch { template<typename Container> Container createShard(Container const& container, std::size_t const shardCount, std::size_t const shardIndex) { assert(shardCount > shardIndex); if (shardCount == 1) { return container; } const std::size_t totalTestCount = container.size(); const std::size_t shardSize = totalTestCount / shardCount; const std::size_t leftoverTests = totalTestCount % shardCount; const std::size_t startIndex = shardIndex * shardSize + (std::min)(shardIndex, leftoverTests); const std::size_t endIndex = (shardIndex + 1) * shardSize + (std::min)(shardIndex + 1, leftoverTests); auto startIterator = std::next(container.begin(), static_cast<std::ptrdiff_t>(startIndex)); auto endIterator = std::next(container.begin(), static_cast<std::ptrdiff_t>(endIndex)); return Container(startIterator, endIterator); }}#endif #ifndef CATCH_SINGLETONS_HPP_INCLUDED#define CATCH_SINGLETONS_HPP_INCLUDEDnamespace Catch { struct ISingleton { virtual ~ISingleton(); }; void addSingleton( ISingleton* singleton ); void cleanupSingletons(); template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT> class Singleton : SingletonImplT, public ISingleton { static auto getInternal() -> Singleton* { static Singleton* s_instance = nullptr; if( !s_instance ) { s_instance = new Singleton; addSingleton( s_instance ); } return s_instance; } public: static auto get() -> InterfaceT const& { return *getInternal(); } static auto getMutable() -> MutableInterfaceT& { return *getInternal(); } };} #endif #ifndef CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED#define CATCH_STARTUP_EXCEPTION_REGISTRY_HPP_INCLUDED#include <vector>#include <exception>namespace Catch { class StartupExceptionRegistry {#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) public: void add(std::exception_ptr const& exception) noexcept; std::vector<std::exception_ptr> const& getExceptions() const noexcept; private: std::vector<std::exception_ptr> m_exceptions;#endif };} #endif #ifndef CATCH_STDSTREAMS_HPP_INCLUDED#define CATCH_STDSTREAMS_HPP_INCLUDED#include <iosfwd>namespace Catch { std::ostream& cout(); std::ostream& cerr(); std::ostream& clog();} #endif#ifndef CATCH_STRING_MANIP_HPP_INCLUDED#define CATCH_STRING_MANIP_HPP_INCLUDED#include <cstdint>#include <string>#include <iosfwd>#include <vector>namespace Catch { bool startsWith( std::string const& s, std::string const& prefix ); bool startsWith( StringRef s, char prefix ); bool endsWith( std::string const& s, std::string const& suffix ); bool endsWith( std::string const& s, char suffix ); bool contains( std::string const& s, std::string const& infix ); void toLowerInPlace( std::string& s ); std::string toLower( std::string const& s ); char toLower( char c ); std::string trim( std::string const& str ); StringRef trim(StringRef ref); std::vector<StringRef> splitStringRef( StringRef str, char delimiter ); bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); class pluralise { std::uint64_t m_count; StringRef m_label; public: constexpr pluralise(std::uint64_t count, StringRef label): m_count(count), m_label(label) {} friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); };}#endif #ifndef CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED#define CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED#include <map>#include <string>namespace Catch { struct SourceLineInfo; class TagAliasRegistry : public ITagAliasRegistry { public: ~TagAliasRegistry() override; TagAlias const* find( std::string const& alias ) const override; std::string expandAliases( std::string const& unexpandedTestSpec ) const override; void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); private: std::map<std::string, TagAlias> m_registry; };} #endif #ifndef CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED#define CATCH_TEST_CASE_INFO_HASHER_HPP_INCLUDED#include <cstdint>namespace Catch { struct TestCaseInfo; class TestCaseInfoHasher { public: using hash_t = std::uint64_t; TestCaseInfoHasher( hash_t seed ); uint32_t operator()( TestCaseInfo const& t ) const; private: hash_t m_seed; };} #endif #ifndef CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED#define CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED#include <vector>namespace Catch { class IConfig; class ITestInvoker; class TestCaseHandle; class TestSpec; std::vector<TestCaseHandle> sortTests( IConfig const& config, std::vector<TestCaseHandle> const& unsortedTestCases ); bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config ); std::vector<TestCaseHandle> filterTests( std::vector<TestCaseHandle> const& testCases, TestSpec const& testSpec, IConfig const& config ); std::vector<TestCaseHandle> const& getAllTestCasesSorted( IConfig const& config ); class TestRegistry : public ITestCaseRegistry { public: void registerTest( Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker ); std::vector<TestCaseInfo*> const& getAllInfos() const override; std::vector<TestCaseHandle> const& getAllTests() const override; std::vector<TestCaseHandle> const& getAllTestsSorted( IConfig const& config ) const override; ~TestRegistry() override; private: std::vector<Detail::unique_ptr<TestCaseInfo>> m_owned_test_infos; std::vector<TestCaseInfo*> m_viewed_test_infos; std::vector<Detail::unique_ptr<ITestInvoker>> m_invokers; std::vector<TestCaseHandle> m_handles; mutable TestRunOrder m_currentSortOrder = TestRunOrder::Declared; mutable std::vector<TestCaseHandle> m_sortedFunctions; }; } #endif #ifndef CATCH_TEST_SPEC_PARSER_HPP_INCLUDED#define CATCH_TEST_SPEC_PARSER_HPP_INCLUDED#ifdef __clang__#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wpadded"#endif#include <vector>#include <string>namespace Catch { class ITagAliasRegistry; class TestSpecParser { enum Mode{ None, Name, QuotedName, Tag, EscapedName }; Mode m_mode = None; Mode lastMode = None; bool m_exclusion = false; std::size_t m_pos = 0; std::size_t m_realPatternPos = 0; std::string m_arg; std::string m_substring; std::string m_patternName; std::vector<std::size_t> m_escapeChars; TestSpec::Filter m_currentFilter; TestSpec m_testSpec; ITagAliasRegistry const* m_tagAliases = nullptr; public: TestSpecParser( ITagAliasRegistry const& tagAliases ); TestSpecParser& parse( std::string const& arg ); TestSpec testSpec(); private: bool visitChar( char c ); void startNewMode( Mode mode ); bool processNoneChar( char c ); void processNameChar( char c ); bool processOtherChar( char c ); void endMode(); void escape(); bool isControlChar( char c ) const; void saveLastMode(); void revertBackToLastMode(); void addFilter(); bool separate(); std::string preprocessPattern(); void addNamePattern(); void addTagPattern(); inline void addCharToPattern(char c) { m_substring += c; m_patternName += c; m_realPatternPos++; } };} #ifdef __clang__#pragma clang diagnostic pop#endif#endif #ifndef CATCH_TEXTFLOW_HPP_INCLUDED#define CATCH_TEXTFLOW_HPP_INCLUDED#include <cassert>#include <string>#include <vector>namespace Catch { namespace TextFlow { class Columns; class AnsiSkippingString { std::string m_string; std::size_t m_size = 0; void preprocessString(); public: class const_iterator; using iterator = const_iterator; static constexpr char sentinel = static_cast<char>( 0xffu ); explicit AnsiSkippingString( std::string const& text ); explicit AnsiSkippingString( std::string&& text ); const_iterator begin() const; const_iterator end() const; size_t size() const { return m_size; } std::string substring( const_iterator begin, const_iterator end ) const; }; class AnsiSkippingString::const_iterator { friend AnsiSkippingString; struct EndTag {}; const std::string* m_string; std::string::const_iterator m_it; explicit const_iterator( const std::string& string, EndTag ): m_string( &string ), m_it( string.end() ) {} void tryParseAnsiEscapes(); void advance(); void unadvance(); public: using difference_type = std::ptrdiff_t; using value_type = char; using pointer = value_type*; using reference = value_type&; using iterator_category = std::bidirectional_iterator_tag; explicit const_iterator( const std::string& string ): m_string( &string ), m_it( string.begin() ) { tryParseAnsiEscapes(); } char operator*() const { return *m_it; } const_iterator& operator++() { advance(); return *this; } const_iterator operator++( int ) { iterator prev( *this ); operator++(); return prev; } const_iterator& operator--() { unadvance(); return *this; } const_iterator operator--( int ) { iterator prev( *this ); operator--(); return prev; } bool operator==( const_iterator const& other ) const { return m_it == other.m_it; } bool operator!=( const_iterator const& other ) const { return !operator==( other ); } bool operator<=( const_iterator const& other ) const { return m_it <= other.m_it; } const_iterator oneBefore() const { auto it = *this; return --it; } }; class Column { AnsiSkippingString m_string; size_t m_width = CATCH_CONFIG_CONSOLE_WIDTH - 1; size_t m_indent = 0; size_t m_initialIndent = std::string::npos; public: class const_iterator { friend Column; struct EndTag {}; Column const& m_column; AnsiSkippingString::const_iterator m_lineStart; AnsiSkippingString::const_iterator m_lineEnd; AnsiSkippingString::const_iterator m_parsedTo; bool m_addHyphen = false; const_iterator( Column const& column, EndTag ): m_column( column ), m_lineStart( m_column.m_string.end() ), m_lineEnd( column.m_string.end() ), m_parsedTo( column.m_string.end() ) {} void calcLength(); size_t indentSize() const; std::string addIndentAndSuffix( AnsiSkippingString::const_iterator start, AnsiSkippingString::const_iterator end ) const; public: using difference_type = std::ptrdiff_t; using value_type = std::string; using pointer = value_type*; using reference = value_type&; using iterator_category = std::forward_iterator_tag; explicit const_iterator( Column const& column ); std::string operator*() const; const_iterator& operator++(); const_iterator operator++( int ); bool operator==( const_iterator const& other ) const { return m_lineStart == other.m_lineStart && &m_column == &other.m_column; } bool operator!=( const_iterator const& other ) const { return !operator==( other ); } }; using iterator = const_iterator; explicit Column( std::string const& text ): m_string( text ) {} explicit Column( std::string&& text ): m_string( CATCH_MOVE( text ) ) {} Column& width( size_t newWidth ) & { assert( newWidth > 0 ); m_width = newWidth; return *this; } Column&& width( size_t newWidth ) && { assert( newWidth > 0 ); m_width = newWidth; return CATCH_MOVE( *this ); } Column& indent( size_t newIndent ) & { m_indent = newIndent; return *this; } Column&& indent( size_t newIndent ) && { m_indent = newIndent; return CATCH_MOVE( *this ); } Column& initialIndent( size_t newIndent ) & { m_initialIndent = newIndent; return *this; } Column&& initialIndent( size_t newIndent ) && { m_initialIndent = newIndent; return CATCH_MOVE( *this ); } size_t width() const { return m_width; } const_iterator begin() const { return const_iterator( *this ); } const_iterator end() const { return { *this, const_iterator::EndTag{} }; } friend std::ostream& operator<<( std::ostream& os, Column const& col ); friend Columns operator+( Column const& lhs, Column const& rhs ); friend Columns operator+( Column&& lhs, Column&& rhs ); }; Column Spacer( size_t spaceWidth ); class Columns { std::vector<Column> m_columns; public: class iterator { friend Columns; struct EndTag {}; std::vector<Column> const& m_columns; std::vector<Column::const_iterator> m_iterators; size_t m_activeIterators; iterator( Columns const& columns, EndTag ); public: using difference_type = std::ptrdiff_t; using value_type = std::string; using pointer = value_type*; using reference = value_type&; using iterator_category = std::forward_iterator_tag; explicit iterator( Columns const& columns ); auto operator==( iterator const& other ) const -> bool { return m_iterators == other.m_iterators; } auto operator!=( iterator const& other ) const -> bool { return m_iterators != other.m_iterators; } std::string operator*() const; iterator& operator++(); iterator operator++( int ); }; using const_iterator = iterator; iterator begin() const { return iterator( *this ); } iterator end() const { return { *this, iterator::EndTag() }; } friend Columns& operator+=( Columns& lhs, Column const& rhs ); friend Columns& operator+=( Columns& lhs, Column&& rhs ); friend Columns operator+( Columns const& lhs, Column const& rhs ); friend Columns operator+( Columns&& lhs, Column&& rhs ); friend std::ostream& operator<<( std::ostream& os, Columns const& cols ); }; } } #endif #ifndef CATCH_TO_STRING_HPP_INCLUDED#define CATCH_TO_STRING_HPP_INCLUDED#include <string>namespace Catch { template <typename T> std::string to_string(T const& t) {#if defined(CATCH_CONFIG_CPP11_TO_STRING) return std::to_string(t);#else ReusableStringStream rss; rss << t; return rss.str();#endif }} #endif #ifndef CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED#define CATCH_UNCAUGHT_EXCEPTIONS_HPP_INCLUDEDnamespace Catch { bool uncaught_exceptions();} #endif #ifndef CATCH_XMLWRITER_HPP_INCLUDED#define CATCH_XMLWRITER_HPP_INCLUDED#include <iosfwd>#include <vector>#include <cstdint>namespace Catch { enum class XmlFormatting : std::uint8_t { None = 0x00, Indent = 0x01, Newline = 0x02, }; constexpr XmlFormatting operator|( XmlFormatting lhs, XmlFormatting rhs ) { return static_cast<XmlFormatting>( static_cast<std::uint8_t>( lhs ) | static_cast<std::uint8_t>( rhs ) ); } constexpr XmlFormatting operator&( XmlFormatting lhs, XmlFormatting rhs ) { return static_cast<XmlFormatting>( static_cast<std::uint8_t>( lhs ) & static_cast<std::uint8_t>( rhs ) ); } class XmlEncode { public: enum ForWhat { ForTextNodes, ForAttributes }; constexpr XmlEncode( StringRef str, ForWhat forWhat = ForTextNodes ): m_str( str ), m_forWhat( forWhat ) {} void encodeTo( std::ostream& os ) const; friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); private: StringRef m_str; ForWhat m_forWhat; }; class XmlWriter { public: class ScopedElement { public: ScopedElement( XmlWriter* writer, XmlFormatting fmt ); ScopedElement( ScopedElement&& other ) noexcept; ScopedElement& operator=( ScopedElement&& other ) noexcept; ~ScopedElement(); ScopedElement& writeText( StringRef text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent ); ScopedElement& writeAttribute( StringRef name, StringRef attribute ); template <typename T, typename = typename std::enable_if_t< !std::is_convertible<T, StringRef>::value>> ScopedElement& writeAttribute( StringRef name, T const& attribute ) { m_writer->writeAttribute( name, attribute ); return *this; } private: XmlWriter* m_writer = nullptr; XmlFormatting m_fmt; }; XmlWriter( std::ostream& os ); ~XmlWriter(); XmlWriter( XmlWriter const& ) = delete; XmlWriter& operator=( XmlWriter const& ) = delete; XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent); XmlWriter& writeAttribute( StringRef name, StringRef attribute ); XmlWriter& writeAttribute( StringRef name, bool attribute ); XmlWriter& writeAttribute( StringRef name, char const* attribute ); template <typename T, typename = typename std::enable_if_t< !std::is_convertible<T, StringRef>::value>> XmlWriter& writeAttribute( StringRef name, T const& attribute ) { ReusableStringStream rss; rss << attribute; return writeAttribute( name, rss.str() ); } XmlWriter& writeText( StringRef text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent ); XmlWriter& writeComment( StringRef text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent ); void writeStylesheetRef( StringRef url ); void ensureTagClosed(); private: void applyFormatting(XmlFormatting fmt); void writeDeclaration(); void newlineIfNecessary(); bool m_tagIsOpen = false; bool m_needsNewline = false; std::vector<std::string> m_tags; std::string m_indent; std::ostream& m_os; };}#endif #ifndef CATCH_MATCHERS_ALL_HPP_INCLUDED#define CATCH_MATCHERS_ALL_HPP_INCLUDED#ifndef CATCH_MATCHERS_HPP_INCLUDED#define CATCH_MATCHERS_HPP_INCLUDED#ifndef CATCH_MATCHERS_IMPL_HPP_INCLUDED#define CATCH_MATCHERS_IMPL_HPP_INCLUDED#include <string>namespace Catch {#ifdef __clang__# pragma clang diagnostic push# pragma clang diagnostic ignored "-Wsign-compare"# pragma clang diagnostic ignored "-Wnon-virtual-dtor"#elif defined __GNUC__# pragma GCC diagnostic push# pragma GCC diagnostic ignored "-Wsign-compare"# pragma GCC diagnostic ignored "-Wnon-virtual-dtor"#endif template<typename ArgT, typename MatcherT> class MatchExpr : public ITransientExpression { ArgT && m_arg; MatcherT const& m_matcher; public: constexpr MatchExpr( ArgT && arg, MatcherT const& matcher ) : ITransientExpression{ true, matcher.match( arg ) }, m_arg( CATCH_FORWARD(arg) ), m_matcher( matcher ) {} void streamReconstructedExpression( std::ostream& os ) const override { os << Catch::Detail::stringify( m_arg ) << ' ' << m_matcher.toString(); } };#ifdef __clang__# pragma clang diagnostic pop#elif defined __GNUC__# pragma GCC diagnostic pop#endif namespace Matchers { template <typename ArgT> class MatcherBase; } using StringMatcher = Matchers::MatcherBase<std::string>; void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher ); template<typename ArgT, typename MatcherT> constexpr MatchExpr<ArgT, MatcherT> makeMatchExpr( ArgT&& arg, MatcherT const& matcher ) { return MatchExpr<ArgT, MatcherT>( CATCH_FORWARD(arg), matcher ); }} #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ do { \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ INTERNAL_CATCH_TRY { \ catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher ) ); \ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ catchAssertionHandler.complete(); \ } while( false )#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ do { \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ if( catchAssertionHandler.allowThrows() ) \ try { \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ static_cast<void>(__VA_ARGS__ ); \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ } \ catch( exceptionType const& ex ) { \ catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher ) ); \ } \ catch( ... ) { \ catchAssertionHandler.handleUnexpectedInflightException(); \ } \ else \ catchAssertionHandler.handleThrowingCallSkipped(); \ catchAssertionHandler.complete(); \ } while( false )#endif #include <string>#include <vector>namespace Catch {namespace Matchers { class MatcherUntypedBase { public: MatcherUntypedBase() = default; MatcherUntypedBase(MatcherUntypedBase const&) = default; MatcherUntypedBase(MatcherUntypedBase&&) = default; MatcherUntypedBase& operator = (MatcherUntypedBase const&) = delete; MatcherUntypedBase& operator = (MatcherUntypedBase&&) = delete; std::string toString() const; protected: virtual ~MatcherUntypedBase(); virtual std::string describe() const = 0; mutable std::string m_cachedToString; }; template<typename T> class MatcherBase : public MatcherUntypedBase { public: virtual bool match( T const& arg ) const = 0; }; namespace Detail { template<typename ArgT> class MatchAllOf final : public MatcherBase<ArgT> { std::vector<MatcherBase<ArgT> const*> m_matchers; public: MatchAllOf() = default; MatchAllOf(MatchAllOf const&) = delete; MatchAllOf& operator=(MatchAllOf const&) = delete; MatchAllOf(MatchAllOf&&) = default; MatchAllOf& operator=(MatchAllOf&&) = default; bool match( ArgT const& arg ) const override { for( auto matcher : m_matchers ) { if (!matcher->match(arg)) return false; } return true; } std::string describe() const override { std::string description; description.reserve( 4 + m_matchers.size()*32 ); description += "( "; bool first = true; for( auto matcher : m_matchers ) { if( first ) first = false; else description += " and "; description += matcher->toString(); } description += " )"; return description; } friend MatchAllOf operator&& (MatchAllOf&& lhs, MatcherBase<ArgT> const& rhs) { lhs.m_matchers.push_back(&rhs); return CATCH_MOVE(lhs); } friend MatchAllOf operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf&& rhs) { rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs); return CATCH_MOVE(rhs); } }; template<typename ArgT> MatchAllOf<ArgT> operator&& (MatchAllOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete; template<typename ArgT> MatchAllOf<ArgT> operator&& (MatcherBase<ArgT> const& lhs, MatchAllOf<ArgT> const& rhs) = delete; template<typename ArgT> class MatchAnyOf final : public MatcherBase<ArgT> { std::vector<MatcherBase<ArgT> const*> m_matchers; public: MatchAnyOf() = default; MatchAnyOf(MatchAnyOf const&) = delete; MatchAnyOf& operator=(MatchAnyOf const&) = delete; MatchAnyOf(MatchAnyOf&&) = default; MatchAnyOf& operator=(MatchAnyOf&&) = default; bool match( ArgT const& arg ) const override { for( auto matcher : m_matchers ) { if (matcher->match(arg)) return true; } return false; } std::string describe() const override { std::string description; description.reserve( 4 + m_matchers.size()*32 ); description += "( "; bool first = true; for( auto matcher : m_matchers ) { if( first ) first = false; else description += " or "; description += matcher->toString(); } description += " )"; return description; } friend MatchAnyOf operator|| (MatchAnyOf&& lhs, MatcherBase<ArgT> const& rhs) { lhs.m_matchers.push_back(&rhs); return CATCH_MOVE(lhs); } friend MatchAnyOf operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf&& rhs) { rhs.m_matchers.insert(rhs.m_matchers.begin(), &lhs); return CATCH_MOVE(rhs); } }; template<typename ArgT> MatchAnyOf<ArgT> operator|| (MatchAnyOf<ArgT> const& lhs, MatcherBase<ArgT> const& rhs) = delete; template<typename ArgT> MatchAnyOf<ArgT> operator|| (MatcherBase<ArgT> const& lhs, MatchAnyOf<ArgT> const& rhs) = delete; template<typename ArgT> class MatchNotOf final : public MatcherBase<ArgT> { MatcherBase<ArgT> const& m_underlyingMatcher; public: explicit MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ): m_underlyingMatcher( underlyingMatcher ) {} bool match( ArgT const& arg ) const override { return !m_underlyingMatcher.match( arg ); } std::string describe() const override { return "not " + m_underlyingMatcher.toString(); } }; } template <typename T> Detail::MatchAllOf<T> operator&& (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) { return Detail::MatchAllOf<T>{} && lhs && rhs; } template <typename T> Detail::MatchAnyOf<T> operator|| (MatcherBase<T> const& lhs, MatcherBase<T> const& rhs) { return Detail::MatchAnyOf<T>{} || lhs || rhs; } template <typename T> Detail::MatchNotOf<T> operator! (MatcherBase<T> const& matcher) { return Detail::MatchNotOf<T>{ matcher }; }} } #if defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )#elif defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) #define CATCH_CHECK_THAT( arg, matcher ) (void)(0) #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)#elif !defined(CATCH_CONFIG_PREFIX_ALL) && !defined(CATCH_CONFIG_DISABLE) #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )#elif !defined(CATCH_CONFIG_PREFIX_ALL) && defined(CATCH_CONFIG_DISABLE) #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) #define CHECK_THROWS_WITH( expr, matcher ) (void)(0) #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) #define CHECK_THAT( arg, matcher ) (void)(0) #define REQUIRE_THAT( arg, matcher ) (void)(0)#endif #endif #ifndef CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED#define CATCH_MATCHERS_CONTAINER_PROPERTIES_HPP_INCLUDED#ifndef CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED#define CATCH_MATCHERS_TEMPLATED_HPP_INCLUDED#include <array>#include <algorithm>#include <string>#include <type_traits>namespace Catch {namespace Matchers { class MatcherGenericBase : public MatcherUntypedBase { public: MatcherGenericBase() = default; ~MatcherGenericBase() override; MatcherGenericBase(MatcherGenericBase const&) = default; MatcherGenericBase(MatcherGenericBase&&) = default; MatcherGenericBase& operator=(MatcherGenericBase const&) = delete; MatcherGenericBase& operator=(MatcherGenericBase&&) = delete; }; namespace Detail { template<std::size_t N, std::size_t M> std::array<void const*, N + M> array_cat(std::array<void const*, N> && lhs, std::array<void const*, M> && rhs) { std::array<void const*, N + M> arr{}; std::copy_n(lhs.begin(), N, arr.begin()); std::copy_n(rhs.begin(), M, arr.begin() + N); return arr; } template<std::size_t N> std::array<void const*, N+1> array_cat(std::array<void const*, N> && lhs, void const* rhs) { std::array<void const*, N+1> arr{}; std::copy_n(lhs.begin(), N, arr.begin()); arr[N] = rhs; return arr; } template<std::size_t N> std::array<void const*, N+1> array_cat(void const* lhs, std::array<void const*, N> && rhs) { std::array<void const*, N + 1> arr{ {lhs} }; std::copy_n(rhs.begin(), N, arr.begin() + 1); return arr; } template<typename T> using is_generic_matcher = std::is_base_of< Catch::Matchers::MatcherGenericBase, std::remove_cv_t<std::remove_reference_t<T>> >; template<typename... Ts> using are_generic_matchers = Catch::Detail::conjunction<is_generic_matcher<Ts>...>; template<typename T> using is_matcher = std::is_base_of< Catch::Matchers::MatcherUntypedBase, std::remove_cv_t<std::remove_reference_t<T>> >; template<std::size_t N, typename Arg> bool match_all_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) { return true; } template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices> bool match_all_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) { return static_cast<T const*>(matchers[Idx])->match(arg) && match_all_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{}); } template<std::size_t N, typename Arg> bool match_any_of(Arg&&, std::array<void const*, N> const&, std::index_sequence<>) { return false; } template<typename T, typename... MatcherTs, std::size_t N, typename Arg, std::size_t Idx, std::size_t... Indices> bool match_any_of(Arg&& arg, std::array<void const*, N> const& matchers, std::index_sequence<Idx, Indices...>) { return static_cast<T const*>(matchers[Idx])->match(arg) || match_any_of<MatcherTs...>(arg, matchers, std::index_sequence<Indices...>{}); } std::string describe_multi_matcher(StringRef combine, std::string const* descriptions_begin, std::string const* descriptions_end); template<typename... MatcherTs, std::size_t... Idx> std::string describe_multi_matcher(StringRef combine, std::array<void const*, sizeof...(MatcherTs)> const& matchers, std::index_sequence<Idx...>) { std::array<std::string, sizeof...(MatcherTs)> descriptions {{ static_cast<MatcherTs const*>(matchers[Idx])->toString()... }}; return describe_multi_matcher(combine, descriptions.data(), descriptions.data() + descriptions.size()); } template<typename... MatcherTs> class MatchAllOfGeneric final : public MatcherGenericBase { public: MatchAllOfGeneric(MatchAllOfGeneric const&) = delete; MatchAllOfGeneric& operator=(MatchAllOfGeneric const&) = delete; MatchAllOfGeneric(MatchAllOfGeneric&&) = default; MatchAllOfGeneric& operator=(MatchAllOfGeneric&&) = default; MatchAllOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {} explicit MatchAllOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {} template<typename Arg> bool match(Arg&& arg) const { return match_all_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{}); } std::string describe() const override { return describe_multi_matcher<MatcherTs...>(" and "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{}); } std::array<void const*, sizeof...( MatcherTs )> m_matchers; template<typename... MatchersRHS> friend MatchAllOfGeneric<MatcherTs..., MatchersRHS...> operator && ( MatchAllOfGeneric<MatcherTs...>&& lhs, MatchAllOfGeneric<MatchersRHS...>&& rhs) { return MatchAllOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))}; } template<typename MatcherRHS> friend std::enable_if_t<is_matcher<MatcherRHS>::value, MatchAllOfGeneric<MatcherTs..., MatcherRHS>> operator && ( MatchAllOfGeneric<MatcherTs...>&& lhs, MatcherRHS const& rhs) { return MatchAllOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(&rhs))}; } template<typename MatcherLHS> friend std::enable_if_t<is_matcher<MatcherLHS>::value, MatchAllOfGeneric<MatcherLHS, MatcherTs...>> operator && ( MatcherLHS const& lhs, MatchAllOfGeneric<MatcherTs...>&& rhs) { return MatchAllOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))}; } }; template<typename... MatcherTs> class MatchAnyOfGeneric final : public MatcherGenericBase { public: MatchAnyOfGeneric(MatchAnyOfGeneric const&) = delete; MatchAnyOfGeneric& operator=(MatchAnyOfGeneric const&) = delete; MatchAnyOfGeneric(MatchAnyOfGeneric&&) = default; MatchAnyOfGeneric& operator=(MatchAnyOfGeneric&&) = default; MatchAnyOfGeneric(MatcherTs const&... matchers) : m_matchers{ {std::addressof(matchers)...} } {} explicit MatchAnyOfGeneric(std::array<void const*, sizeof...(MatcherTs)> matchers) : m_matchers{matchers} {} template<typename Arg> bool match(Arg&& arg) const { return match_any_of<MatcherTs...>(arg, m_matchers, std::index_sequence_for<MatcherTs...>{}); } std::string describe() const override { return describe_multi_matcher<MatcherTs...>(" or "_sr, m_matchers, std::index_sequence_for<MatcherTs...>{}); } std::array<void const*, sizeof...( MatcherTs )> m_matchers; template<typename... MatchersRHS> friend MatchAnyOfGeneric<MatcherTs..., MatchersRHS...> operator || ( MatchAnyOfGeneric<MatcherTs...>&& lhs, MatchAnyOfGeneric<MatchersRHS...>&& rhs) { return MatchAnyOfGeneric<MatcherTs..., MatchersRHS...>{array_cat(CATCH_MOVE(lhs.m_matchers), CATCH_MOVE(rhs.m_matchers))}; } template<typename MatcherRHS> friend std::enable_if_t<is_matcher<MatcherRHS>::value, MatchAnyOfGeneric<MatcherTs..., MatcherRHS>> operator || ( MatchAnyOfGeneric<MatcherTs...>&& lhs, MatcherRHS const& rhs) { return MatchAnyOfGeneric<MatcherTs..., MatcherRHS>{array_cat(CATCH_MOVE(lhs.m_matchers), static_cast<void const*>(std::addressof(rhs)))}; } template<typename MatcherLHS> friend std::enable_if_t<is_matcher<MatcherLHS>::value, MatchAnyOfGeneric<MatcherLHS, MatcherTs...>> operator || ( MatcherLHS const& lhs, MatchAnyOfGeneric<MatcherTs...>&& rhs) { return MatchAnyOfGeneric<MatcherLHS, MatcherTs...>{array_cat(static_cast<void const*>(std::addressof(lhs)), CATCH_MOVE(rhs.m_matchers))}; } }; template<typename MatcherT> class MatchNotOfGeneric final : public MatcherGenericBase { MatcherT const& m_matcher; public: MatchNotOfGeneric(MatchNotOfGeneric const&) = delete; MatchNotOfGeneric& operator=(MatchNotOfGeneric const&) = delete; MatchNotOfGeneric(MatchNotOfGeneric&&) = default; MatchNotOfGeneric& operator=(MatchNotOfGeneric&&) = default; explicit MatchNotOfGeneric(MatcherT const& matcher) : m_matcher{matcher} {} template<typename Arg> bool match(Arg&& arg) const { return !m_matcher.match(arg); } std::string describe() const override { return "not " + m_matcher.toString(); } friend MatcherT const& operator ! (MatchNotOfGeneric<MatcherT> const& matcher) { return matcher.m_matcher; } }; } template<typename MatcherLHS, typename MatcherRHS> std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherRHS>> operator && (MatcherLHS const& lhs, MatcherRHS const& rhs) { return { lhs, rhs }; } template<typename MatcherLHS, typename MatcherRHS> std::enable_if_t<Detail::are_generic_matchers<MatcherLHS, MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherRHS>> operator || (MatcherLHS const& lhs, MatcherRHS const& rhs) { return { lhs, rhs }; } template<typename MatcherT> std::enable_if_t<Detail::is_generic_matcher<MatcherT>::value, Detail::MatchNotOfGeneric<MatcherT>> operator ! (MatcherT const& matcher) { return Detail::MatchNotOfGeneric<MatcherT>{matcher}; } template<typename MatcherLHS, typename ArgRHS> std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAllOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>> operator && (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) { return { lhs, rhs }; } template<typename ArgLHS, typename MatcherRHS> std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAllOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>> operator && (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) { return { lhs, rhs }; } template<typename MatcherLHS, typename ArgRHS> std::enable_if_t<Detail::is_generic_matcher<MatcherLHS>::value, Detail::MatchAnyOfGeneric<MatcherLHS, MatcherBase<ArgRHS>>> operator || (MatcherLHS const& lhs, MatcherBase<ArgRHS> const& rhs) { return { lhs, rhs }; } template<typename ArgLHS, typename MatcherRHS> std::enable_if_t<Detail::is_generic_matcher<MatcherRHS>::value, Detail::MatchAnyOfGeneric<MatcherBase<ArgLHS>, MatcherRHS>> operator || (MatcherBase<ArgLHS> const& lhs, MatcherRHS const& rhs) { return { lhs, rhs }; }} } #endif namespace Catch { namespace Matchers { class IsEmptyMatcher final : public MatcherGenericBase { public: template <typename RangeLike> bool match(RangeLike&& rng) const {#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS) using Catch::Detail::empty;#else using std::empty;#endif return empty(rng); } std::string describe() const override; }; class HasSizeMatcher final : public MatcherGenericBase { std::size_t m_target_size; public: explicit HasSizeMatcher(std::size_t target_size): m_target_size(target_size) {} template <typename RangeLike> bool match(RangeLike&& rng) const {#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS) using Catch::Detail::size;#else using std::size;#endif return size(rng) == m_target_size; } std::string describe() const override; }; template <typename Matcher> class SizeMatchesMatcher final : public MatcherGenericBase { Matcher m_matcher; public: explicit SizeMatchesMatcher(Matcher m): m_matcher(CATCH_MOVE(m)) {} template <typename RangeLike> bool match(RangeLike&& rng) const {#if defined(CATCH_CONFIG_POLYFILL_NONMEMBER_CONTAINER_ACCESS) using Catch::Detail::size;#else using std::size;#endif return m_matcher.match(size(rng)); } std::string describe() const override { return "size matches " + m_matcher.describe(); } }; IsEmptyMatcher IsEmpty(); HasSizeMatcher SizeIs(std::size_t sz); template <typename Matcher> std::enable_if_t<Detail::is_matcher<Matcher>::value, SizeMatchesMatcher<Matcher>> SizeIs(Matcher&& m) { return SizeMatchesMatcher<Matcher>{CATCH_FORWARD(m)}; } } } #endif #ifndef CATCH_MATCHERS_CONTAINS_HPP_INCLUDED#define CATCH_MATCHERS_CONTAINS_HPP_INCLUDED#include <algorithm>#include <functional>namespace Catch { namespace Matchers { template <typename T, typename Equality> class ContainsElementMatcher final : public MatcherGenericBase { T m_desired; Equality m_eq; public: template <typename T2, typename Equality2> ContainsElementMatcher(T2&& target, Equality2&& predicate): m_desired(CATCH_FORWARD(target)), m_eq(CATCH_FORWARD(predicate)) {} std::string describe() const override { return "contains element " + Catch::Detail::stringify(m_desired); } template <typename RangeLike> bool match( RangeLike&& rng ) const { for ( auto&& elem : rng ) { if ( m_eq( elem, m_desired ) ) { return true; } } return false; } }; template <typename Matcher> class ContainsMatcherMatcher final : public MatcherGenericBase { Matcher m_matcher; public: ContainsMatcherMatcher(Matcher matcher): m_matcher(CATCH_MOVE(matcher)) {} template <typename RangeLike> bool match(RangeLike&& rng) const { for (auto&& elem : rng) { if (m_matcher.match(elem)) { return true; } } return false; } std::string describe() const override { return "contains element matching " + m_matcher.describe(); } }; template <typename T> std::enable_if_t<!Detail::is_matcher<T>::value, ContainsElementMatcher<T, std::equal_to<>>> Contains(T&& elem) { return { CATCH_FORWARD(elem), std::equal_to<>{} }; } template <typename Matcher> std::enable_if_t<Detail::is_matcher<Matcher>::value, ContainsMatcherMatcher<Matcher>> Contains(Matcher&& matcher) { return { CATCH_FORWARD(matcher) }; } template <typename T, typename Equality> ContainsElementMatcher<T, Equality> Contains(T&& elem, Equality&& eq) { return { CATCH_FORWARD(elem), CATCH_FORWARD(eq) }; } }}#endif #ifndef CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED#define CATCH_MATCHERS_EXCEPTION_HPP_INCLUDEDnamespace Catch {namespace Matchers {class ExceptionMessageMatcher final : public MatcherBase<std::exception> { std::string m_message;public: ExceptionMessageMatcher(std::string const& message): m_message(message) {} bool match(std::exception const& ex) const override; std::string describe() const override;};ExceptionMessageMatcher Message(std::string const& message);template <typename StringMatcherType>class ExceptionMessageMatchesMatcher final : public MatcherBase<std::exception> { StringMatcherType m_matcher;public: ExceptionMessageMatchesMatcher( StringMatcherType matcher ): m_matcher( CATCH_MOVE( matcher ) ) {} bool match( std::exception const& ex ) const override { return m_matcher.match( ex.what() ); } std::string describe() const override { return " matches \"" + m_matcher.describe() + '"'; }};template <typename StringMatcherType>ExceptionMessageMatchesMatcher<StringMatcherType>MessageMatches( StringMatcherType&& matcher ) { return { CATCH_FORWARD( matcher ) };}} // namespace Matchers} // namespace Catch#endif // CATCH_MATCHERS_EXCEPTION_HPP_INCLUDED#ifndef CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED#define CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDEDnamespace Catch {namespace Matchers { namespace Detail { enum class FloatingPointKind : uint8_t; } class WithinAbsMatcher final : public MatcherBase<double> { public: WithinAbsMatcher(double target, double margin); bool match(double const& matchee) const override; std::string describe() const override; private: double m_target; double m_margin; }; WithinAbsMatcher WithinAbs( double target, double margin ); class WithinUlpsMatcher final : public MatcherBase<double> { public: WithinUlpsMatcher( double target, uint64_t ulps, Detail::FloatingPointKind baseType ); bool match(double const& matchee) const override; std::string describe() const override; private: double m_target; uint64_t m_ulps; Detail::FloatingPointKind m_type; }; WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff); WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff); // Given IEEE-754 format for floats and doubles, we can assume // that float -> double promotion is lossless. Given this, we can // assume that if we do the standard relative comparison of // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get // the same result if we do this for floats, as if we do this for // doubles that were promoted from floats. class WithinRelMatcher final : public MatcherBase<double> { public: WithinRelMatcher( double target, double epsilon ); bool match(double const& matchee) const override; std::string describe() const override; private: double m_target; double m_epsilon; }; WithinRelMatcher WithinRel(double target, double eps); WithinRelMatcher WithinRel(double target); WithinRelMatcher WithinRel(float target, float eps); WithinRelMatcher WithinRel(float target); class IsNaNMatcher final : public MatcherBase<double> { public: IsNaNMatcher() = default; bool match( double const& matchee ) const override; std::string describe() const override; }; IsNaNMatcher IsNaN();} // namespace Matchers} // namespace Catch#endif // CATCH_MATCHERS_FLOATING_POINT_HPP_INCLUDED#ifndef CATCH_MATCHERS_PREDICATE_HPP_INCLUDED#define CATCH_MATCHERS_PREDICATE_HPP_INCLUDED#include <string>namespace Catch {namespace Matchers {namespace Detail { std::string finalizeDescription(const std::string& desc);} // namespace Detailtemplate <typename T, typename Predicate>class PredicateMatcher final : public MatcherBase<T> { Predicate m_predicate; std::string m_description;public: PredicateMatcher(Predicate&& elem, std::string const& descr) :m_predicate(CATCH_FORWARD(elem)), m_description(Detail::finalizeDescription(descr)) {} bool match( T const& item ) const override { return m_predicate(item); } std::string describe() const override { return m_description; }}; /** * Creates a matcher that calls delegates `match` to the provided predicate. * * The user has to explicitly specify the argument type to the matcher */ template<typename T, typename Pred> PredicateMatcher<T, Pred> Predicate(Pred&& predicate, std::string const& description = "") { static_assert(is_callable<Pred(T)>::value, "Predicate not callable with argument T"); static_assert(std::is_same<bool, FunctionReturnType<Pred, T>>::value, "Predicate does not return bool"); return PredicateMatcher<T, Pred>(CATCH_FORWARD(predicate), description); }} // namespace Matchers} // namespace Catch#endif // CATCH_MATCHERS_PREDICATE_HPP_INCLUDED#ifndef CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED#define CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDEDnamespace Catch { namespace Matchers { // Matcher for checking that all elements in range matches a given matcher. template <typename Matcher> class AllMatchMatcher final : public MatcherGenericBase { Matcher m_matcher; public: AllMatchMatcher(Matcher matcher): m_matcher(CATCH_MOVE(matcher)) {} std::string describe() const override { return "all match " + m_matcher.describe(); } template <typename RangeLike> bool match(RangeLike&& rng) const { for (auto&& elem : rng) { if (!m_matcher.match(elem)) { return false; } } return true; } }; // Matcher for checking that no element in range matches a given matcher. template <typename Matcher> class NoneMatchMatcher final : public MatcherGenericBase { Matcher m_matcher; public: NoneMatchMatcher(Matcher matcher): m_matcher(CATCH_MOVE(matcher)) {} std::string describe() const override { return "none match " + m_matcher.describe(); } template <typename RangeLike> bool match(RangeLike&& rng) const { for (auto&& elem : rng) { if (m_matcher.match(elem)) { return false; } } return true; } }; // Matcher for checking that at least one element in range matches a given matcher. template <typename Matcher> class AnyMatchMatcher final : public MatcherGenericBase { Matcher m_matcher; public: AnyMatchMatcher(Matcher matcher): m_matcher(CATCH_MOVE(matcher)) {} std::string describe() const override { return "any match " + m_matcher.describe(); } template <typename RangeLike> bool match(RangeLike&& rng) const { for (auto&& elem : rng) { if (m_matcher.match(elem)) { return true; } } return false; } }; // Matcher for checking that all elements in range are true. class AllTrueMatcher final : public MatcherGenericBase { public: std::string describe() const override; template <typename RangeLike> bool match(RangeLike&& rng) const { for (auto&& elem : rng) { if (!elem) { return false; } } return true; } }; // Matcher for checking that no element in range is true. class NoneTrueMatcher final : public MatcherGenericBase { public: std::string describe() const override; template <typename RangeLike> bool match(RangeLike&& rng) const { for (auto&& elem : rng) { if (elem) { return false; } } return true; } }; // Matcher for checking that any element in range is true. class AnyTrueMatcher final : public MatcherGenericBase { public: std::string describe() const override; template <typename RangeLike> bool match(RangeLike&& rng) const { for (auto&& elem : rng) { if (elem) { return true; } } return false; } }; // Creates a matcher that checks whether all elements in a range match a matcher template <typename Matcher> AllMatchMatcher<Matcher> AllMatch(Matcher&& matcher) { return { CATCH_FORWARD(matcher) }; } // Creates a matcher that checks whether no element in a range matches a matcher. template <typename Matcher> NoneMatchMatcher<Matcher> NoneMatch(Matcher&& matcher) { return { CATCH_FORWARD(matcher) }; } // Creates a matcher that checks whether any element in a range matches a matcher. template <typename Matcher> AnyMatchMatcher<Matcher> AnyMatch(Matcher&& matcher) { return { CATCH_FORWARD(matcher) }; } // Creates a matcher that checks whether all elements in a range are true AllTrueMatcher AllTrue(); // Creates a matcher that checks whether no element in a range is true NoneTrueMatcher NoneTrue(); // Creates a matcher that checks whether any element in a range is true AnyTrueMatcher AnyTrue(); }}#endif // CATCH_MATCHERS_QUANTIFIERS_HPP_INCLUDED#ifndef CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED#define CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED#include <algorithm>#include <utility>namespace Catch { namespace Matchers { /** * Matcher for checking that an element contains the same * elements in the same order */ template <typename TargetRangeLike, typename Equality> class RangeEqualsMatcher final : public MatcherGenericBase { TargetRangeLike m_desired; Equality m_predicate; public: template <typename TargetRangeLike2, typename Equality2> constexpr RangeEqualsMatcher( TargetRangeLike2&& range, Equality2&& predicate ): m_desired( CATCH_FORWARD( range ) ), m_predicate( CATCH_FORWARD( predicate ) ) {} template <typename RangeLike> constexpr bool match( RangeLike&& rng ) const { auto rng_start = begin( rng ); const auto rng_end = end( rng ); auto target_start = begin( m_desired ); const auto target_end = end( m_desired ); while (rng_start != rng_end && target_start != target_end) { if (!m_predicate(*rng_start, *target_start)) { return false; } ++rng_start; ++target_start; } return rng_start == rng_end && target_start == target_end; } std::string describe() const override { return "elements are " + Catch::Detail::stringify( m_desired ); } }; /** * Matcher for checking that an element contains the same * elements (but not necessarily in the same order) */ template <typename TargetRangeLike, typename Equality> class UnorderedRangeEqualsMatcher final : public MatcherGenericBase { TargetRangeLike m_desired; Equality m_predicate; public: template <typename TargetRangeLike2, typename Equality2> constexpr UnorderedRangeEqualsMatcher( TargetRangeLike2&& range, Equality2&& predicate ): m_desired( CATCH_FORWARD( range ) ), m_predicate( CATCH_FORWARD( predicate ) ) {} template <typename RangeLike> constexpr bool match( RangeLike&& rng ) const { using std::begin; using std::end; return Catch::Detail::is_permutation( begin( m_desired ), end( m_desired ), begin( rng ), end( rng ), m_predicate ); } std::string describe() const override { return "unordered elements are " + ::Catch::Detail::stringify( m_desired ); } }; /** * Creates a matcher that checks if all elements in a range are equal * to all elements in another range. * * Uses the provided predicate `predicate` to do the comparisons * (defaulting to `std::equal_to`) */ template <typename RangeLike, typename Equality = decltype( std::equal_to<>{} )> constexpr RangeEqualsMatcher<RangeLike, Equality> RangeEquals( RangeLike&& range, Equality&& predicate = std::equal_to<>{} ) { return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; } /** * Creates a matcher that checks if all elements in a range are equal * to all elements in an initializer list. * * Uses the provided predicate `predicate` to do the comparisons * (defaulting to `std::equal_to`) */ template <typename T, typename Equality = decltype( std::equal_to<>{} )> constexpr RangeEqualsMatcher<std::initializer_list<T>, Equality> RangeEquals( std::initializer_list<T> range, Equality&& predicate = std::equal_to<>{} ) { return { range, CATCH_FORWARD( predicate ) }; } /** * Creates a matcher that checks if all elements in a range are equal * to all elements in another range, in some permutation. * * Uses the provided predicate `predicate` to do the comparisons * (defaulting to `std::equal_to`) */ template <typename RangeLike, typename Equality = decltype( std::equal_to<>{} )> constexpr UnorderedRangeEqualsMatcher<RangeLike, Equality> UnorderedRangeEquals( RangeLike&& range, Equality&& predicate = std::equal_to<>{} ) { return { CATCH_FORWARD( range ), CATCH_FORWARD( predicate ) }; } /** * Creates a matcher that checks if all elements in a range are equal * to all elements in an initializer list, in some permutation. * * Uses the provided predicate `predicate` to do the comparisons * (defaulting to `std::equal_to`) */ template <typename T, typename Equality = decltype( std::equal_to<>{} )> constexpr UnorderedRangeEqualsMatcher<std::initializer_list<T>, Equality> UnorderedRangeEquals( std::initializer_list<T> range, Equality&& predicate = std::equal_to<>{} ) { return { range, CATCH_FORWARD( predicate ) }; } } // namespace Matchers} // namespace Catch#endif // CATCH_MATCHERS_RANGE_EQUALS_HPP_INCLUDED#ifndef CATCH_MATCHERS_STRING_HPP_INCLUDED#define CATCH_MATCHERS_STRING_HPP_INCLUDED#include <string>namespace Catch {namespace Matchers { struct CasedString { CasedString( std::string const& str, CaseSensitive caseSensitivity ); std::string adjustString( std::string const& str ) const; StringRef caseSensitivitySuffix() const; CaseSensitive m_caseSensitivity; std::string m_str; }; class StringMatcherBase : public MatcherBase<std::string> { protected: CasedString m_comparator; StringRef m_operation; public: StringMatcherBase( StringRef operation, CasedString const& comparator ); std::string describe() const override; }; class StringEqualsMatcher final : public StringMatcherBase { public: StringEqualsMatcher( CasedString const& comparator ); bool match( std::string const& source ) const override; }; class StringContainsMatcher final : public StringMatcherBase { public: StringContainsMatcher( CasedString const& comparator ); bool match( std::string const& source ) const override; }; class StartsWithMatcher final : public StringMatcherBase { public: StartsWithMatcher( CasedString const& comparator ); bool match( std::string const& source ) const override; }; class EndsWithMatcher final : public StringMatcherBase { public: EndsWithMatcher( CasedString const& comparator ); bool match( std::string const& source ) const override; }; class RegexMatcher final : public MatcherBase<std::string> { std::string m_regex; CaseSensitive m_caseSensitivity; public: RegexMatcher( std::string regex, CaseSensitive caseSensitivity ); bool match( std::string const& matchee ) const override; std::string describe() const override; }; StringEqualsMatcher Equals( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes ); StringContainsMatcher ContainsSubstring( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes ); EndsWithMatcher EndsWith( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes ); StartsWithMatcher StartsWith( std::string const& str, CaseSensitive caseSensitivity = CaseSensitive::Yes ); RegexMatcher Matches( std::string const& regex, CaseSensitive caseSensitivity = CaseSensitive::Yes );} // namespace Matchers} // namespace Catch#endif // CATCH_MATCHERS_STRING_HPP_INCLUDED#ifndef CATCH_MATCHERS_VECTOR_HPP_INCLUDED#define CATCH_MATCHERS_VECTOR_HPP_INCLUDED#include <algorithm>namespace Catch {namespace Matchers { template<typename T, typename Alloc> class VectorContainsElementMatcher final : public MatcherBase<std::vector<T, Alloc>> { T const& m_comparator; public: VectorContainsElementMatcher(T const& comparator): m_comparator(comparator) {} bool match(std::vector<T, Alloc> const& v) const override { for (auto const& el : v) { if (el == m_comparator) { return true; } } return false; } std::string describe() const override { return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } }; template<typename T, typename AllocComp, typename AllocMatch> class ContainsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> { std::vector<T, AllocComp> const& m_comparator; public: ContainsMatcher(std::vector<T, AllocComp> const& comparator): m_comparator( comparator ) {} bool match(std::vector<T, AllocMatch> const& v) const override { // !TBD: see note in EqualsMatcher if (m_comparator.size() > v.size()) return false; for (auto const& comparator : m_comparator) { auto present = false; for (const auto& el : v) { if (el == comparator) { present = true; break; } } if (!present) { return false; } } return true; } std::string describe() const override { return "Contains: " + ::Catch::Detail::stringify( m_comparator ); } }; template<typename T, typename AllocComp, typename AllocMatch> class EqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> { std::vector<T, AllocComp> const& m_comparator; public: EqualsMatcher(std::vector<T, AllocComp> const& comparator): m_comparator( comparator ) {} bool match(std::vector<T, AllocMatch> const& v) const override { // !TBD: This currently works if all elements can be compared using != // - a more general approach would be via a compare template that defaults // to using !=. but could be specialised for, e.g. std::vector<T> etc // - then just call that directly if ( m_comparator.size() != v.size() ) { return false; } for ( std::size_t i = 0; i < v.size(); ++i ) { if ( !( m_comparator[i] == v[i] ) ) { return false; } } return true; } std::string describe() const override { return "Equals: " + ::Catch::Detail::stringify( m_comparator ); } }; template<typename T, typename AllocComp, typename AllocMatch> class ApproxMatcher final : public MatcherBase<std::vector<T, AllocMatch>> { std::vector<T, AllocComp> const& m_comparator; mutable Catch::Approx approx = Catch::Approx::custom(); public: ApproxMatcher(std::vector<T, AllocComp> const& comparator): m_comparator( comparator ) {} bool match(std::vector<T, AllocMatch> const& v) const override { if (m_comparator.size() != v.size()) return false; for (std::size_t i = 0; i < v.size(); ++i) if (m_comparator[i] != approx(v[i])) return false; return true; } std::string describe() const override { return "is approx: " + ::Catch::Detail::stringify( m_comparator ); } template <typename = std::enable_if_t<std::is_constructible<double, T>::value>> ApproxMatcher& epsilon( T const& newEpsilon ) { approx.epsilon(static_cast<double>(newEpsilon)); return *this; } template <typename = std::enable_if_t<std::is_constructible<double, T>::value>> ApproxMatcher& margin( T const& newMargin ) { approx.margin(static_cast<double>(newMargin)); return *this; } template <typename = std::enable_if_t<std::is_constructible<double, T>::value>> ApproxMatcher& scale( T const& newScale ) { approx.scale(static_cast<double>(newScale)); return *this; } }; template<typename T, typename AllocComp, typename AllocMatch> class UnorderedEqualsMatcher final : public MatcherBase<std::vector<T, AllocMatch>> { std::vector<T, AllocComp> const& m_target; public: UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target): m_target(target) {} bool match(std::vector<T, AllocMatch> const& vec) const override { if (m_target.size() != vec.size()) { return false; } return std::is_permutation(m_target.begin(), m_target.end(), vec.begin()); } std::string describe() const override { return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); } }; // The following functions create the actual matcher objects. // This allows the types to be inferred template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) { return ContainsMatcher<T, AllocComp, AllocMatch>(comparator); } template<typename T, typename Alloc = std::allocator<T>> VectorContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) { return VectorContainsElementMatcher<T, Alloc>(comparator); } template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) { return EqualsMatcher<T, AllocComp, AllocMatch>(comparator); } template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) { return ApproxMatcher<T, AllocComp, AllocMatch>(comparator); } template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp> UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) { return UnorderedEqualsMatcher<T, AllocComp, AllocMatch>(target); }} // namespace Matchers} // namespace Catch#endif // CATCH_MATCHERS_VECTOR_HPP_INCLUDED#endif // CATCH_MATCHERS_ALL_HPP_INCLUDED/** \file * This is a convenience header for Catch2's Reporter support. It includes * **all** of Catch2 headers related to reporters, including all reporters. * * Generally the Catch2 users should use specific includes they need, * but this header can be used instead for ease-of-experimentation, or * just plain convenience, at the cost of (significantly) increased * compilation times. * * When a new header (reporter) is added to either the `reporter` folder, * or to the corresponding internal subfolder, it should be added here. */#ifndef CATCH_REPORTERS_ALL_HPP_INCLUDED#define CATCH_REPORTERS_ALL_HPP_INCLUDED#ifndef CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED#define CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED#ifndef CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED#define CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED#ifndef CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED#define CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED#include <map>#include <string>namespace Catch { class ColourImpl; /** * This is the base class for all reporters. * * If are writing a reporter, you must derive from this type, or one * of the helper reporter bases that are derived from this type. * * ReporterBase centralizes handling of various common tasks in reporters, * like storing the right stream for the reporters to write to, and * providing the default implementation of the different listing events. */ class ReporterBase : public IEventListener { protected: Detail::unique_ptr<IStream> m_wrapped_stream; std::ostream& m_stream; Detail::unique_ptr<ColourImpl> m_colour; std::map<std::string, std::string> m_customOptions; public: ReporterBase( ReporterConfig&& config ); ~ReporterBase() override; // = default; /** * Provides a simple default listing of reporters. * * Should look roughly like the reporter listing in v2 and earlier * versions of Catch2. */ void listReporters( std::vector<ReporterDescription> const& descriptions ) override; /** * Provides a simple default listing of listeners * * Looks similarly to listing of reporters, but with listener type * instead of reporter name. */ void listListeners( std::vector<ListenerDescription> const& descriptions ) override; /** * Provides a simple default listing of tests. * * Should look roughly like the test listing in v2 and earlier versions * of Catch2. Especially supports low-verbosity listing that mimics the * old `--list-test-names-only` output. */ void listTests( std::vector<TestCaseHandle> const& tests ) override; /** * Provides a simple default listing of tags. * * Should look roughly like the tag listing in v2 and earlier versions * of Catch2. */ void listTags( std::vector<TagInfo> const& tags ) override; };} // namespace Catch#endif // CATCH_REPORTER_COMMON_BASE_HPP_INCLUDED#include <vector>namespace Catch { class StreamingReporterBase : public ReporterBase { public: // GCC5 compat: we cannot use inherited constructor, because it // doesn't implement backport of P0136 StreamingReporterBase(ReporterConfig&& _config): ReporterBase(CATCH_MOVE(_config)) {} ~StreamingReporterBase() override; void benchmarkPreparing( StringRef ) override {} void benchmarkStarting( BenchmarkInfo const& ) override {} void benchmarkEnded( BenchmarkStats<> const& ) override {} void benchmarkFailed( StringRef ) override {} void fatalErrorEncountered( StringRef /*error*/ ) override {} void noMatchingTestCases( StringRef /*unmatchedSpec*/ ) override {} void reportInvalidTestSpec( StringRef /*invalidArgument*/ ) override {} void testRunStarting( TestRunInfo const& _testRunInfo ) override; void testCaseStarting(TestCaseInfo const& _testInfo) override { currentTestCaseInfo = &_testInfo; } void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {} void sectionStarting(SectionInfo const& _sectionInfo) override { m_sectionStack.push_back(_sectionInfo); } void assertionStarting( AssertionInfo const& ) override {} void assertionEnded( AssertionStats const& ) override {} void sectionEnded(SectionStats const& /* _sectionStats */) override { m_sectionStack.pop_back(); } void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {} void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { currentTestCaseInfo = nullptr; } void testRunEnded( TestRunStats const& /* _testRunStats */ ) override; void skipTest(TestCaseInfo const&) override { // Don't do anything with this by default. // It can optionally be overridden in the derived class. } protected: TestRunInfo currentTestRunInfo{ "test run has not started yet"_sr }; TestCaseInfo const* currentTestCaseInfo = nullptr; std::vector<SectionInfo> m_sectionStack; };} // end namespace Catch#endif // CATCH_REPORTER_STREAMING_BASE_HPP_INCLUDED#include <string>namespace Catch { class AutomakeReporter final : public StreamingReporterBase { public: // GCC5 compat: we cannot use inherited constructor, because it // doesn't implement backport of P0136 AutomakeReporter(ReporterConfig&& _config): StreamingReporterBase(CATCH_MOVE(_config)) {} ~AutomakeReporter() override; static std::string getDescription() { using namespace std::string_literals; return "Reports test results in the format of Automake .trs files"s; } void testCaseEnded(TestCaseStats const& _testCaseStats) override; void skipTest(TestCaseInfo const& testInfo) override; };} // end namespace Catch#endif // CATCH_REPORTER_AUTOMAKE_HPP_INCLUDED#ifndef CATCH_REPORTER_COMPACT_HPP_INCLUDED#define CATCH_REPORTER_COMPACT_HPP_INCLUDEDnamespace Catch { class CompactReporter final : public StreamingReporterBase { public: using StreamingReporterBase::StreamingReporterBase; ~CompactReporter() override; static std::string getDescription(); void noMatchingTestCases( StringRef unmatchedSpec ) override; void testRunStarting( TestRunInfo const& _testInfo ) override; void assertionEnded(AssertionStats const& _assertionStats) override; void sectionEnded(SectionStats const& _sectionStats) override; void testRunEnded(TestRunStats const& _testRunStats) override; };} // end namespace Catch#endif // CATCH_REPORTER_COMPACT_HPP_INCLUDED#ifndef CATCH_REPORTER_CONSOLE_HPP_INCLUDED#define CATCH_REPORTER_CONSOLE_HPP_INCLUDEDnamespace Catch { // Fwd decls class TablePrinter; class ConsoleReporter final : public StreamingReporterBase { Detail::unique_ptr<TablePrinter> m_tablePrinter; public: ConsoleReporter(ReporterConfig&& config); ~ConsoleReporter() override; static std::string getDescription(); void noMatchingTestCases( StringRef unmatchedSpec ) override; void reportInvalidTestSpec( StringRef arg ) override; void assertionStarting(AssertionInfo const&) override; void assertionEnded(AssertionStats const& _assertionStats) override; void sectionStarting(SectionInfo const& _sectionInfo) override; void sectionEnded(SectionStats const& _sectionStats) override; void benchmarkPreparing( StringRef name ) override; void benchmarkStarting(BenchmarkInfo const& info) override; void benchmarkEnded(BenchmarkStats<> const& stats) override; void benchmarkFailed( StringRef error ) override; void testCaseEnded(TestCaseStats const& _testCaseStats) override; void testRunEnded(TestRunStats const& _testRunStats) override; void testRunStarting(TestRunInfo const& _testRunInfo) override; private: void lazyPrint(); void lazyPrintWithoutClosingBenchmarkTable(); void lazyPrintRunInfo(); void printTestCaseAndSectionHeader(); void printClosedHeader(std::string const& _name); void printOpenHeader(std::string const& _name); // if string has a : in first line will set indent to follow it on // subsequent lines void printHeaderString(std::string const& _string, std::size_t indent = 0); void printTotalsDivider(Totals const& totals); bool m_headerPrinted = false; bool m_testRunInfoPrinted = false; };} // end namespace Catch#endif // CATCH_REPORTER_CONSOLE_HPP_INCLUDED#ifndef CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED#define CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED#include <string>#include <vector>namespace Catch { namespace Detail { class AssertionOrBenchmarkResult { // This should really be a variant, but this is much faster // to write and the data layout here is already terrible // enough that we do not have to care about the object size. Optional<AssertionStats> m_assertion; Optional<BenchmarkStats<>> m_benchmark; public: AssertionOrBenchmarkResult(AssertionStats const& assertion); AssertionOrBenchmarkResult(BenchmarkStats<> const& benchmark); bool isAssertion() const; bool isBenchmark() const; AssertionStats const& asAssertion() const; BenchmarkStats<> const& asBenchmark() const; }; } /** * Utility base for reporters that need to handle all results at once * * It stores tree of all test cases, sections and assertions, and after the * test run is finished, calls into `testRunEndedCumulative` to pass the * control to the deriving class. * * If you are deriving from this class and override any testing related * member functions, you should first call into the base's implementation to * avoid breaking the tree construction. * * Due to the way this base functions, it has to expand assertions up-front, * even if they are later unused (e.g. because the deriving reporter does * not report srtion expansion at all). Derived classes can use two * customization points, `m_shouldStoreSuccesfulAssertions` and * `m_shouldStoreFailedAssertions`, to disable the expansion and gain extra * performance. **Accessing the assertion expansions if it wasn't stored is * UB.** */ class CumulativeReporterBase : public ReporterBase { public: template<typename T, typename ChildNodeT> struct Node { explicit Node( T const& _value ) : value( _value ) {} using ChildNodes = std::vector<Detail::unique_ptr<ChildNodeT>>; T value; ChildNodes children; }; struct SectionNode { explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} bool operator == (SectionNode const& other) const { return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; } bool hasAnyAssertions() const; SectionStats stats; std::vector<Detail::unique_ptr<SectionNode>> childSections; std::vector<Detail::AssertionOrBenchmarkResult> assertionsAndBenchmarks; std::string stdOut; std::string stdErr; }; using TestCaseNode = Node<TestCaseStats, SectionNode>; using TestRunNode = Node<TestRunStats, TestCaseNode>; // GCC5 compat: we cannot use inherited constructor, because it // doesn't implement backport of P0136 CumulativeReporterBase(ReporterConfig&& _config): ReporterBase(CATCH_MOVE(_config)) {} ~CumulativeReporterBase() override; void benchmarkPreparing( StringRef ) override {} void benchmarkStarting( BenchmarkInfo const& ) override {} void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override; void benchmarkFailed( StringRef ) override {} void noMatchingTestCases( StringRef ) override {} void reportInvalidTestSpec( StringRef ) override {} void fatalErrorEncountered( StringRef /*error*/ ) override {} void testRunStarting( TestRunInfo const& ) override {} void testCaseStarting( TestCaseInfo const& ) override {} void testCasePartialStarting( TestCaseInfo const&, uint64_t ) override {} void sectionStarting( SectionInfo const& sectionInfo ) override; void assertionStarting( AssertionInfo const& ) override {} void assertionEnded( AssertionStats const& assertionStats ) override; void sectionEnded( SectionStats const& sectionStats ) override; void testCasePartialEnded( TestCaseStats const&, uint64_t ) override {} void testCaseEnded( TestCaseStats const& testCaseStats ) override; void testRunEnded( TestRunStats const& testRunStats ) override; virtual void testRunEndedCumulative() = 0; void skipTest(TestCaseInfo const&) override {} protected: bool m_shouldStoreSuccesfulAssertions = true; bool m_shouldStoreFailedAssertions = true; // We need lazy construction here. We should probably refactor it // later, after the events are redone. Detail::unique_ptr<TestRunNode> m_testRun; private: // Note: We rely on pointer identity being stable, which is why // we store pointers to the nodes rather than the values. std::vector<Detail::unique_ptr<TestCaseNode>> m_testCases; // Root section of the _current_ test case Detail::unique_ptr<SectionNode> m_rootSection; // Deepest section of the _current_ test case SectionNode* m_deepestSection = nullptr; // Stack of _active_ sections in the _current_ test case std::vector<SectionNode*> m_sectionStack; };} // end namespace Catch#endif // CATCH_REPORTER_CUMULATIVE_BASE_HPP_INCLUDED#ifndef CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED#define CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDEDnamespace Catch { /** * Base class to simplify implementing listeners. * * Provides empty default implementation for all IEventListener member * functions, so that a listener implementation can pick which * member functions it actually cares about. */ class EventListenerBase : public IEventListener { public: using IEventListener::IEventListener; void reportInvalidTestSpec( StringRef unmatchedSpec ) override; void fatalErrorEncountered( StringRef error ) override; void benchmarkPreparing( StringRef name ) override; void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override; void benchmarkFailed( StringRef error ) override; void assertionStarting( AssertionInfo const& assertionInfo ) override; void assertionEnded( AssertionStats const& assertionStats ) override; void listReporters( std::vector<ReporterDescription> const& descriptions ) override; void listListeners( std::vector<ListenerDescription> const& descriptions ) override; void listTests( std::vector<TestCaseHandle> const& tests ) override; void listTags( std::vector<TagInfo> const& tagInfos ) override; void noMatchingTestCases( StringRef unmatchedSpec ) override; void testRunStarting( TestRunInfo const& testRunInfo ) override; void testCaseStarting( TestCaseInfo const& testInfo ) override; void testCasePartialStarting( TestCaseInfo const& testInfo, uint64_t partNumber ) override; void sectionStarting( SectionInfo const& sectionInfo ) override; void sectionEnded( SectionStats const& sectionStats ) override; void testCasePartialEnded( TestCaseStats const& testCaseStats, uint64_t partNumber ) override; void testCaseEnded( TestCaseStats const& testCaseStats ) override; void testRunEnded( TestRunStats const& testRunStats ) override; void skipTest( TestCaseInfo const& testInfo ) override; };} // end namespace Catch#endif // CATCH_REPORTER_EVENT_LISTENER_HPP_INCLUDED#ifndef CATCH_REPORTER_HELPERS_HPP_INCLUDED#define CATCH_REPORTER_HELPERS_HPP_INCLUDED#include <iosfwd>#include <string>#include <vector>namespace Catch { class IConfig; class TestCaseHandle; class ColourImpl; // Returns double formatted as %.3f (format expected on output) std::string getFormattedDuration( double duration ); bool shouldShowDuration( IConfig const& config, double duration ); std::string serializeFilters( std::vector<std::string> const& filters ); struct lineOfChars { char c; constexpr lineOfChars( char c_ ): c( c_ ) {} friend std::ostream& operator<<( std::ostream& out, lineOfChars value ); }; /** * Lists reporter descriptions to the provided stream in user-friendly * format * * Used as the default listing implementation by the first party reporter * bases. The output should be backwards compatible with the output of * Catch2 v2 binaries. */ void defaultListReporters( std::ostream& out, std::vector<ReporterDescription> const& descriptions, Verbosity verbosity ); /** * Lists listeners descriptions to the provided stream in user-friendly * format */ void defaultListListeners( std::ostream& out, std::vector<ListenerDescription> const& descriptions ); /** * Lists tag information to the provided stream in user-friendly format * * Used as the default listing implementation by the first party reporter * bases. The output should be backwards compatible with the output of * Catch2 v2 binaries. */ void defaultListTags( std::ostream& out, std::vector<TagInfo> const& tags, bool isFiltered ); /** * Lists test case information to the provided stream in user-friendly * format * * Used as the default listing implementation by the first party reporter * bases. The output is backwards compatible with the output of Catch2 * v2 binaries, and also supports the format specific to the old * `--list-test-names-only` option, for people who used it in integrations. */ void defaultListTests( std::ostream& out, ColourImpl* streamColour, std::vector<TestCaseHandle> const& tests, bool isFiltered, Verbosity verbosity ); /** * Prints test run totals to the provided stream in user-friendly format * * Used by the console and compact reporters. */ void printTestRunTotals( std::ostream& stream, ColourImpl& streamColour, Totals const& totals );} // end namespace Catch#endif // CATCH_REPORTER_HELPERS_HPP_INCLUDED#ifndef CATCH_REPORTER_JSON_HPP_INCLUDED#define CATCH_REPORTER_JSON_HPP_INCLUDED#include <stack>namespace Catch { class JsonReporter : public StreamingReporterBase { public: JsonReporter( ReporterConfig&& config ); ~JsonReporter() override; static std::string getDescription(); public: // StreamingReporterBase void testRunStarting( TestRunInfo const& runInfo ) override; void testRunEnded( TestRunStats const& runStats ) override; void testCaseStarting( TestCaseInfo const& tcInfo ) override; void testCaseEnded( TestCaseStats const& tcStats ) override; void testCasePartialStarting( TestCaseInfo const& tcInfo, uint64_t index ) override; void testCasePartialEnded( TestCaseStats const& tcStats, uint64_t index ) override; void sectionStarting( SectionInfo const& sectionInfo ) override; void sectionEnded( SectionStats const& sectionStats ) override; void assertionStarting( AssertionInfo const& assertionInfo ) override; void assertionEnded( AssertionStats const& assertionStats ) override; //void testRunEndedCumulative() override; void benchmarkPreparing( StringRef name ) override; void benchmarkStarting( BenchmarkInfo const& ) override; void benchmarkEnded( BenchmarkStats<> const& ) override; void benchmarkFailed( StringRef error ) override; void listReporters( std::vector<ReporterDescription> const& descriptions ) override; void listListeners( std::vector<ListenerDescription> const& descriptions ) override; void listTests( std::vector<TestCaseHandle> const& tests ) override; void listTags( std::vector<TagInfo> const& tags ) override; private: Timer m_testCaseTimer; enum class Writer { Object, Array }; JsonArrayWriter& startArray(); JsonArrayWriter& startArray( StringRef key ); JsonObjectWriter& startObject(); JsonObjectWriter& startObject( StringRef key ); void endObject(); void endArray(); bool isInside( Writer writer ); void startListing(); void endListing(); // Invariant: // When m_writers is not empty and its top element is // - Writer::Object, then m_objectWriters is not be empty // - Writer::Array, then m_arrayWriters shall not be empty std::stack<JsonObjectWriter> m_objectWriters{}; std::stack<JsonArrayWriter> m_arrayWriters{}; std::stack<Writer> m_writers{}; bool m_startedListing = false; // std::size_t m_sectionDepth = 0; // std::size_t m_sectionStarted = 0; };} // namespace Catch#endif // CATCH_REPORTER_JSON_HPP_INCLUDED#ifndef CATCH_REPORTER_JUNIT_HPP_INCLUDED#define CATCH_REPORTER_JUNIT_HPP_INCLUDEDnamespace Catch { class JunitReporter final : public CumulativeReporterBase { public: JunitReporter(ReporterConfig&& _config); static std::string getDescription(); void testRunStarting(TestRunInfo const& runInfo) override; void testCaseStarting(TestCaseInfo const& testCaseInfo) override; void assertionEnded(AssertionStats const& assertionStats) override; void testCaseEnded(TestCaseStats const& testCaseStats) override; void testRunEndedCumulative() override; private: void writeRun(TestRunNode const& testRunNode, double suiteTime); void writeTestCase(TestCaseNode const& testCaseNode); void writeSection( std::string const& className, std::string const& rootName, SectionNode const& sectionNode, bool testOkToFail ); void writeAssertions(SectionNode const& sectionNode); void writeAssertion(AssertionStats const& stats); XmlWriter xml; Timer suiteTimer; std::string stdOutForSuite; std::string stdErrForSuite; unsigned int unexpectedExceptions = 0; bool m_okToFail = false; };} // end namespace Catch#endif // CATCH_REPORTER_JUNIT_HPP_INCLUDED#ifndef CATCH_REPORTER_MULTI_HPP_INCLUDED#define CATCH_REPORTER_MULTI_HPP_INCLUDEDnamespace Catch { class MultiReporter final : public IEventListener { /* * Stores all added reporters and listeners * * All Listeners are stored before all reporters, and individual * listeners/reporters are stored in order of insertion. */ std::vector<IEventListenerPtr> m_reporterLikes; bool m_haveNoncapturingReporters = false; // Keep track of how many listeners we have already inserted, // so that we can insert them into the main vector at the right place size_t m_insertedListeners = 0; void updatePreferences(IEventListener const& reporterish); public: using IEventListener::IEventListener; void addListener( IEventListenerPtr&& listener ); void addReporter( IEventListenerPtr&& reporter ); public: // IEventListener void noMatchingTestCases( StringRef unmatchedSpec ) override; void fatalErrorEncountered( StringRef error ) override; void reportInvalidTestSpec( StringRef arg ) override; void benchmarkPreparing( StringRef name ) override; void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override; void benchmarkFailed( StringRef error ) override; void testRunStarting( TestRunInfo const& testRunInfo ) override; void testCaseStarting( TestCaseInfo const& testInfo ) override; void testCasePartialStarting(TestCaseInfo const& testInfo, uint64_t partNumber) override; void sectionStarting( SectionInfo const& sectionInfo ) override; void assertionStarting( AssertionInfo const& assertionInfo ) override; void assertionEnded( AssertionStats const& assertionStats ) override; void sectionEnded( SectionStats const& sectionStats ) override; void testCasePartialEnded(TestCaseStats const& testStats, uint64_t partNumber) override; void testCaseEnded( TestCaseStats const& testCaseStats ) override; void testRunEnded( TestRunStats const& testRunStats ) override; void skipTest( TestCaseInfo const& testInfo ) override; void listReporters(std::vector<ReporterDescription> const& descriptions) override; void listListeners(std::vector<ListenerDescription> const& descriptions) override; void listTests(std::vector<TestCaseHandle> const& tests) override; void listTags(std::vector<TagInfo> const& tags) override; };} // end namespace Catch#endif // CATCH_REPORTER_MULTI_HPP_INCLUDED#ifndef CATCH_REPORTER_REGISTRARS_HPP_INCLUDED#define CATCH_REPORTER_REGISTRARS_HPP_INCLUDED#include <type_traits>namespace Catch { namespace Detail { template <typename T, typename = void> struct has_description : std::false_type {}; template <typename T> struct has_description< T, void_t<decltype( T::getDescription() )>> : std::true_type {}; void registerReporterImpl( std::string const& name, IReporterFactoryPtr reporterPtr ); void registerListenerImpl( Detail::unique_ptr<EventListenerFactory> listenerFactory ); } // namespace Detail class IEventListener; using IEventListenerPtr = Detail::unique_ptr<IEventListener>; template <typename T> class ReporterFactory : public IReporterFactory { IEventListenerPtr create( ReporterConfig&& config ) const override { return Detail::make_unique<T>( CATCH_MOVE(config) ); } std::string getDescription() const override { return T::getDescription(); } }; template<typename T> class ReporterRegistrar { public: explicit ReporterRegistrar( std::string const& name ) { registerReporterImpl( name, Detail::make_unique<ReporterFactory<T>>() ); } }; template<typename T> class ListenerRegistrar { class TypedListenerFactory : public EventListenerFactory { StringRef m_listenerName; std::string getDescriptionImpl( std::true_type ) const { return T::getDescription(); } std::string getDescriptionImpl( std::false_type ) const { return "(No description provided)"; } public: TypedListenerFactory( StringRef listenerName ): m_listenerName( listenerName ) {} IEventListenerPtr create( IConfig const* config ) const override { return Detail::make_unique<T>( config ); } StringRef getName() const override { return m_listenerName; } std::string getDescription() const override { return getDescriptionImpl( Detail::has_description<T>{} ); } }; public: ListenerRegistrar(StringRef listenerName) { registerListenerImpl( Detail::make_unique<TypedListenerFactory>(listenerName) ); } };}#if !defined(CATCH_CONFIG_DISABLE)# define CATCH_REGISTER_REPORTER( name, reporterType ) \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace { \ Catch::ReporterRegistrar<reporterType> INTERNAL_CATCH_UNIQUE_NAME( \ catch_internal_RegistrarFor )( name ); \ } \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION# define CATCH_REGISTER_LISTENER( listenerType ) \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ namespace { \ Catch::ListenerRegistrar<listenerType> INTERNAL_CATCH_UNIQUE_NAME( \ catch_internal_RegistrarFor )( #listenerType##_catch_sr ); \ } \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION#else // CATCH_CONFIG_DISABLE#define CATCH_REGISTER_REPORTER(name, reporterType)#define CATCH_REGISTER_LISTENER(listenerType)#endif // CATCH_CONFIG_DISABLE#endif // CATCH_REPORTER_REGISTRARS_HPP_INCLUDED#ifndef CATCH_REPORTER_SONARQUBE_HPP_INCLUDED#define CATCH_REPORTER_SONARQUBE_HPP_INCLUDEDnamespace Catch { class SonarQubeReporter final : public CumulativeReporterBase { public: SonarQubeReporter(ReporterConfig&& config) : CumulativeReporterBase(CATCH_MOVE(config)) , xml(m_stream) { m_preferences.shouldRedirectStdOut = true; m_preferences.shouldReportAllAssertions = false; m_shouldStoreSuccesfulAssertions = false; } static std::string getDescription() { using namespace std::string_literals; return "Reports test results in the Generic Test Data SonarQube XML format"s; } void testRunStarting( TestRunInfo const& testRunInfo ) override; void testRunEndedCumulative() override { writeRun( *m_testRun ); xml.endElement(); } void writeRun( TestRunNode const& runNode ); void writeTestFile(StringRef filename, std::vector<TestCaseNode const*> const& testCaseNodes); void writeTestCase(TestCaseNode const& testCaseNode); void writeSection(std::string const& rootName, SectionNode const& sectionNode, bool okToFail); void writeAssertions(SectionNode const& sectionNode, bool okToFail); void writeAssertion(AssertionStats const& stats, bool okToFail); private: XmlWriter xml; };} // end namespace Catch#endif // CATCH_REPORTER_SONARQUBE_HPP_INCLUDED#ifndef CATCH_REPORTER_TAP_HPP_INCLUDED#define CATCH_REPORTER_TAP_HPP_INCLUDEDnamespace Catch { class TAPReporter final : public StreamingReporterBase { public: TAPReporter( ReporterConfig&& config ): StreamingReporterBase( CATCH_MOVE(config) ) { m_preferences.shouldReportAllAssertions = true; } static std::string getDescription() { using namespace std::string_literals; return "Reports test results in TAP format, suitable for test harnesses"s; } void testRunStarting( TestRunInfo const& testInfo ) override; void noMatchingTestCases( StringRef unmatchedSpec ) override; void assertionEnded(AssertionStats const& _assertionStats) override; void testRunEnded(TestRunStats const& _testRunStats) override; private: std::size_t counter = 0; };} // end namespace Catch#endif // CATCH_REPORTER_TAP_HPP_INCLUDED#ifndef CATCH_REPORTER_TEAMCITY_HPP_INCLUDED#define CATCH_REPORTER_TEAMCITY_HPP_INCLUDED#include <cstring>#ifdef __clang__# pragma clang diagnostic push# pragma clang diagnostic ignored "-Wpadded"#endifnamespace Catch { class TeamCityReporter final : public StreamingReporterBase { public: TeamCityReporter( ReporterConfig&& _config ) : StreamingReporterBase( CATCH_MOVE(_config) ) { m_preferences.shouldRedirectStdOut = true; } ~TeamCityReporter() override; static std::string getDescription() { using namespace std::string_literals; return "Reports test results as TeamCity service messages"s; } void testRunStarting( TestRunInfo const& runInfo ) override; void testRunEnded( TestRunStats const& runStats ) override; void assertionEnded(AssertionStats const& assertionStats) override; void sectionStarting(SectionInfo const& sectionInfo) override { m_headerPrintedForThisSection = false; StreamingReporterBase::sectionStarting( sectionInfo ); } void testCaseStarting(TestCaseInfo const& testInfo) override; void testCaseEnded(TestCaseStats const& testCaseStats) override; private: void printSectionHeader(std::ostream& os); bool m_headerPrintedForThisSection = false; Timer m_testTimer; };} // end namespace Catch#ifdef __clang__# pragma clang diagnostic pop#endif#endif // CATCH_REPORTER_TEAMCITY_HPP_INCLUDED#ifndef CATCH_REPORTER_XML_HPP_INCLUDED#define CATCH_REPORTER_XML_HPP_INCLUDEDnamespace Catch { class XmlReporter : public StreamingReporterBase { public: XmlReporter(ReporterConfig&& _config); ~XmlReporter() override; static std::string getDescription(); virtual std::string getStylesheetRef() const; void writeSourceInfo(SourceLineInfo const& sourceInfo); public: // StreamingReporterBase void testRunStarting(TestRunInfo const& testInfo) override; void testCaseStarting(TestCaseInfo const& testInfo) override; void sectionStarting(SectionInfo const& sectionInfo) override; void assertionStarting(AssertionInfo const&) override; void assertionEnded(AssertionStats const& assertionStats) override; void sectionEnded(SectionStats const& sectionStats) override; void testCaseEnded(TestCaseStats const& testCaseStats) override; void testRunEnded(TestRunStats const& testRunStats) override; void benchmarkPreparing( StringRef name ) override; void benchmarkStarting(BenchmarkInfo const&) override; void benchmarkEnded(BenchmarkStats<> const&) override; void benchmarkFailed( StringRef error ) override; void listReporters(std::vector<ReporterDescription> const& descriptions) override; void listListeners(std::vector<ListenerDescription> const& descriptions) override; void listTests(std::vector<TestCaseHandle> const& tests) override; void listTags(std::vector<TagInfo> const& tags) override; private: Timer m_testCaseTimer; XmlWriter m_xml; int m_sectionDepth = 0; };} // end namespace Catch#endif // CATCH_REPORTER_XML_HPP_INCLUDED#endif // CATCH_REPORTERS_ALL_HPP_INCLUDED#endif // CATCH_ALL_HPP_INCLUDED#endif // CATCH_AMALGAMATED_HPP_INCLUDEDuccessful assertions, or because the deriving reporter does not use asse#ifndef CATCH_WINDOWS_H_PROXY_HPP_INCLUDED#define CATCH_WINDOWS_H_PROXY_HPP_INCLUDED#if defined(CATCH_PLATFORM_WINDOWS)// We might end up with the define made globally through the compiler,// and we don't want to trigger warnings for this#if !defined(NOMINMAX)# define NOMINMAX#endif#if !defined(WIN32_LEAN_AND_MEAN)# define WIN32_LEAN_AND_MEAN#endif#include <windows.h>#endif // defined(CATCH_PLATFORM_WINDOWS)#endif // CATCH_WINDOWS_H_PROXY_HPP_INCLUDEDnamespace Catch { namespace Benchmark { namespace Detail { ChronometerConcept::~ChronometerConcept() = default; } // namespace Detail } // namespace Benchmark} // namespace Catch// Adapted from donated nonius code.#include <vector>namespace Catch { namespace Benchmark { namespace Detail { SampleAnalysis analyse(const IConfig &cfg, FDuration* first, FDuration* last) { if (!cfg.benchmarkNoAnalysis()) { std::vector<double> samples; samples.reserve(static_cast<size_t>(last - first)); for (auto current = first; current != last; ++current) { samples.push_back( current->count() ); } auto analysis = Catch::Benchmark::Detail::analyse_samples( cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.data(), samples.data() + samples.size() ); auto outliers = Catch::Benchmark::Detail::classify_outliers( samples.data(), samples.data() + samples.size() ); auto wrap_estimate = [](Estimate<double> e) { return Estimate<FDuration> { FDuration(e.point), FDuration(e.lower_bound), FDuration(e.upper_bound), e.confidence_interval, }; }; std::vector<FDuration> samples2; samples2.reserve(samples.size()); for (auto s : samples) { samples2.push_back( FDuration( s ) ); } return { CATCH_MOVE(samples2), wrap_estimate(analysis.mean), wrap_estimate(analysis.standard_deviation), outliers, analysis.outlier_variance, }; } else { std::vector<FDuration> samples; samples.reserve(static_cast<size_t>(last - first)); FDuration mean = FDuration(0); int i = 0; for (auto it = first; it < last; ++it, ++i) { samples.push_back(*it); mean += *it; } mean /= i; return SampleAnalysis{ CATCH_MOVE(samples), Estimate<FDuration>{ mean, mean, mean, 0.0 }, Estimate<FDuration>{ FDuration( 0 ), FDuration( 0 ), FDuration( 0 ), 0.0 }, OutlierClassification{}, 0.0 }; } } } // namespace Detail } // namespace Benchmark} // namespace Catchnamespace Catch { namespace Benchmark { namespace Detail { struct do_nothing { void operator()() const {} }; BenchmarkFunction::callable::~callable() = default; BenchmarkFunction::BenchmarkFunction(): f( new model<do_nothing>{ {} } ){} } // namespace Detail } // namespace Benchmark} // namespace Catch#include <exception>namespace Catch { namespace Benchmark { namespace Detail { struct optimized_away_error : std::exception { const char* what() const noexcept override; }; const char* optimized_away_error::what() const noexcept { return "could not measure benchmark, maybe it was optimized away"; } void throw_optimized_away_error() { Catch::throw_exception(optimized_away_error{}); } } // namespace Detail } // namespace Benchmark} // namespace Catch// Adapted from donated nonius code.#include <algorithm>#include <cassert>#include <cmath>#include <cstddef>#include <numeric>#include <random>#if defined(CATCH_CONFIG_USE_ASYNC)#include <future>#endifnamespace Catch { namespace Benchmark { namespace Detail { namespace { template <typename URng, typename Estimator> static sample resample( URng& rng, unsigned int resamples, double const* first, double const* last, Estimator& estimator ) { auto n = static_cast<size_t>( last - first ); Catch::uniform_integer_distribution<size_t> dist( 0, n - 1 ); sample out; out.reserve( resamples ); std::vector<double> resampled; resampled.reserve( n ); for ( size_t i = 0; i < resamples; ++i ) { resampled.clear(); for ( size_t s = 0; s < n; ++s ) { resampled.push_back( first[dist( rng )] ); } const auto estimate = estimator( resampled.data(), resampled.data() + resampled.size() ); out.push_back( estimate ); } std::sort( out.begin(), out.end() ); return out; } static double outlier_variance( Estimate<double> mean, Estimate<double> stddev, int n ) { double sb = stddev.point; double mn = mean.point / n; double mg_min = mn / 2.; double sg = (std::min)( mg_min / 4., sb / std::sqrt( n ) ); double sg2 = sg * sg; double sb2 = sb * sb; auto c_max = [n, mn, sb2, sg2]( double x ) -> double { double k = mn - x; double d = k * k; double nd = n * d; double k0 = -n * nd; double k1 = sb2 - n * sg2 + nd; double det = k1 * k1 - 4 * sg2 * k0; return static_cast<int>( -2. * k0 / ( k1 + std::sqrt( det ) ) ); }; auto var_out = [n, sb2, sg2]( double c ) { double nc = n - c; return ( nc / n ) * ( sb2 - nc * sg2 ); }; return (std::min)( var_out( 1 ), var_out( (std::min)( c_max( 0. ), c_max( mg_min ) ) ) ) / sb2; } static double erf_inv( double x ) { // Code accompanying the article "Approximating the erfinv