| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Catch v2.6.1 | |||
| * Generated: 2019-02-12 19:52:52.262497 | |||
| * Catch v2.7.0 | |||
| * Generated: 2019-03-07 21:34:30.252164 | |||
| * ---------------------------------------------------------- | |||
| * This file has been merged from multiple headers. Please don't edit it directly | |||
| * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. | |||
| @@ -14,8 +14,8 @@ | |||
| #define CATCH_VERSION_MAJOR 2 | |||
| #define CATCH_VERSION_MINOR 6 | |||
| #define CATCH_VERSION_PATCH 1 | |||
| #define CATCH_VERSION_MINOR 7 | |||
| #define CATCH_VERSION_PATCH 0 | |||
| #ifdef __clang__ | |||
| # pragma clang system_header | |||
| @@ -711,6 +711,16 @@ struct is_unique<T0, T1, Rest...> : std::integral_constant | |||
| #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ | |||
| #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ | |||
| #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF | |||
| #define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) | |||
| #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR | |||
| #define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ | |||
| #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) | |||
| #else | |||
| // MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF | |||
| #define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) | |||
| #define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ | |||
| #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) | |||
| #endif | |||
| #define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) | |||
| @@ -725,7 +735,7 @@ struct is_unique<T0, T1, Rest...> : std::integral_constant | |||
| #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) | |||
| #endif | |||
| #define INTERNAL_CATCH_MAKE_TYPE_LIST(types) TypeList<INTERNAL_CATCH_REMOVE_PARENS(types)> | |||
| #define INTERNAL_CATCH_MAKE_TYPE_LIST(types) Catch::TypeList<INTERNAL_CATCH_REMOVE_PARENS(types)> | |||
| #define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(types)\ | |||
| CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,INTERNAL_CATCH_REMOVE_PARENS(types)) | |||
| @@ -736,65 +746,59 @@ struct is_unique<T0, T1, Rest...> : std::integral_constant | |||
| #include <type_traits> | |||
| namespace Catch { | |||
| template< typename... > | |||
| struct TypeList{}; | |||
| struct TypeList {}; | |||
| template< typename... > | |||
| struct append; | |||
| template< template<typename...> class L1 | |||
| , typename...E1 | |||
| , template<typename...> class L2 | |||
| , typename...E2 | |||
| > | |||
| struct append< L1<E1...>, L2<E2...> > | |||
| { | |||
| using type = L1<E1..., E2...>; | |||
| , typename...E1 | |||
| , template<typename...> class L2 | |||
| , typename...E2 | |||
| > | |||
| struct append< L1<E1...>, L2<E2...> > { | |||
| using type = L1<E1..., E2...>; | |||
| }; | |||
| template< template<typename...> class L1 | |||
| , typename...E1 | |||
| , template<typename...> class L2 | |||
| , typename...E2 | |||
| , typename...Rest | |||
| > | |||
| struct append< L1<E1...>, L2<E2...>, Rest...> | |||
| { | |||
| using type = typename append< L1<E1..., E2...>, Rest... >::type; | |||
| , typename...E1 | |||
| , template<typename...> class L2 | |||
| , typename...E2 | |||
| , typename...Rest | |||
| > | |||
| struct append< L1<E1...>, L2<E2...>, Rest...> { | |||
| using type = typename append< L1<E1..., E2...>, Rest... >::type; | |||
| }; | |||
| template< template<typename...> class | |||
| , typename... | |||
| > | |||
| , typename... | |||
| > | |||
| struct rewrap; | |||
| template< template<typename...> class Container | |||
| , template<typename...> class List | |||
| , typename...elems | |||
| > | |||
| struct rewrap<Container, List<elems...>> | |||
| { | |||
| , template<typename...> class List | |||
| , typename...elems | |||
| > | |||
| struct rewrap<Container, List<elems...>> { | |||
| using type = TypeList< Container< elems... > >; | |||
| }; | |||
| template< template<typename...> class Container | |||
| , template<typename...> class List | |||
| , class...Elems | |||
| , typename...Elements> | |||
| struct rewrap<Container, List<Elems...>, Elements...> | |||
| { | |||
| , template<typename...> class List | |||
| , class...Elems | |||
| , typename...Elements> | |||
| struct rewrap<Container, List<Elems...>, Elements...> { | |||
| using type = typename append<TypeList<Container<Elems...>>, typename rewrap<Container, Elements...>::type>::type; | |||
| }; | |||
| template< template<typename...> class...Containers > | |||
| struct combine | |||
| { | |||
| struct combine { | |||
| template< typename...Types > | |||
| struct with_types | |||
| { | |||
| struct with_types { | |||
| template< template <typename...> class Final > | |||
| struct into | |||
| { | |||
| struct into { | |||
| using type = typename append<Final<>, typename rewrap<Containers, Types...>::type...>::type; | |||
| }; | |||
| }; | |||
| @@ -803,6 +807,8 @@ struct combine | |||
| template<typename T> | |||
| struct always_false : std::false_type {}; | |||
| } // namespace Catch | |||
| // end catch_meta.hpp | |||
| namespace Catch { | |||
| @@ -949,11 +955,14 @@ struct AutoReg : NonCopyable { | |||
| CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...) \ | |||
| int index = 0; \ | |||
| using expander = int[]; \ | |||
| (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + Catch::StringMaker<int>::convert(index++), Tags } ), 0)... };/* NOLINT */ \ | |||
| constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ | |||
| constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ | |||
| constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ | |||
| (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */\ | |||
| } \ | |||
| }; \ | |||
| static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ | |||
| using TestInit = combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)> \ | |||
| using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)> \ | |||
| ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestName>::type; \ | |||
| TestInit(); \ | |||
| return 0; \ | |||
| @@ -1014,11 +1023,14 @@ struct AutoReg : NonCopyable { | |||
| CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\ | |||
| int index = 0;\ | |||
| using expander = int[];\ | |||
| (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + Catch::StringMaker<int>::convert(index++), Tags } ), 0)... };/* NOLINT */ \ | |||
| constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ | |||
| constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ | |||
| constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ | |||
| (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */ \ | |||
| }\ | |||
| };\ | |||
| static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ | |||
| using TestInit = combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>\ | |||
| using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>\ | |||
| ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestNameClass>::type;\ | |||
| TestInit();\ | |||
| return 0;\ | |||
| @@ -2062,6 +2074,7 @@ namespace Catch { | |||
| struct SectionInfo; | |||
| struct SectionEndInfo; | |||
| struct MessageInfo; | |||
| struct MessageBuilder; | |||
| struct Counts; | |||
| struct BenchmarkInfo; | |||
| struct BenchmarkStats; | |||
| @@ -2088,6 +2101,8 @@ namespace Catch { | |||
| virtual void pushScopedMessage( MessageInfo const& message ) = 0; | |||
| virtual void popScopedMessage( MessageInfo const& message ) = 0; | |||
| virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0; | |||
| virtual void handleFatalErrorCondition( StringRef message ) = 0; | |||
| virtual void handleExpr | |||
| @@ -2251,9 +2266,12 @@ namespace Catch { | |||
| class ScopedMessage { | |||
| public: | |||
| explicit ScopedMessage( MessageBuilder const& builder ); | |||
| ScopedMessage( ScopedMessage& duplicate ) = delete; | |||
| ScopedMessage( ScopedMessage&& old ); | |||
| ~ScopedMessage(); | |||
| MessageInfo m_info; | |||
| bool m_moved; | |||
| }; | |||
| class Capturer { | |||
| @@ -2316,7 +2334,7 @@ namespace Catch { | |||
| CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ | |||
| } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ | |||
| INTERNAL_CATCH_REACT( catchAssertionHandler ) \ | |||
| } while( (void)0, false && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look | |||
| } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look | |||
| // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. | |||
| /////////////////////////////////////////////////////////////////////////////// | |||
| @@ -2397,6 +2415,10 @@ namespace Catch { | |||
| #define INTERNAL_CATCH_INFO( macroName, log ) \ | |||
| Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); | |||
| /////////////////////////////////////////////////////////////////////////////// | |||
| #define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \ | |||
| Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) | |||
| /////////////////////////////////////////////////////////////////////////////// | |||
| // Although this is matcher-based, it can be used with just a string | |||
| #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ | |||
| @@ -3642,6 +3664,36 @@ namespace Generators { | |||
| return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... ); | |||
| } | |||
| auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; | |||
| template<typename L> | |||
| // Note: The type after -> is weird, because VS2015 cannot parse | |||
| // the expression used in the typedef inside, when it is in | |||
| // return type. Yeah. | |||
| auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) { | |||
| using UnderlyingType = typename decltype(generatorExpression())::type; | |||
| IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo ); | |||
| if (!tracker.hasGenerator()) { | |||
| tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression())); | |||
| } | |||
| auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() ); | |||
| return generator.get(); | |||
| } | |||
| } // namespace Generators | |||
| } // namespace Catch | |||
| #define GENERATE( ... ) \ | |||
| Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) | |||
| // end catch_generators.hpp | |||
| // start catch_generators_generic.hpp | |||
| namespace Catch { | |||
| namespace Generators { | |||
| template <typename T> | |||
| class TakeGenerator : public IGenerator<T> { | |||
| GeneratorWrapper<T> m_generator; | |||
| @@ -3810,31 +3862,297 @@ namespace Generators { | |||
| ); | |||
| } | |||
| auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; | |||
| template<typename L> | |||
| // Note: The type after -> is weird, because VS2015 cannot parse | |||
| // the expression used in the typedef inside, when it is in | |||
| // return type. Yeah, ¯\_(ツ)_/¯ | |||
| auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) { | |||
| using UnderlyingType = typename decltype(generatorExpression())::type; | |||
| IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo ); | |||
| if (!tracker.hasGenerator()) { | |||
| tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression())); | |||
| template <typename T> | |||
| class ChunkGenerator final : public IGenerator<std::vector<T>> { | |||
| std::vector<T> m_chunk; | |||
| size_t m_chunk_size; | |||
| GeneratorWrapper<T> m_generator; | |||
| bool m_used_up = false; | |||
| public: | |||
| ChunkGenerator(size_t size, GeneratorWrapper<T> generator) : | |||
| m_chunk_size(size), m_generator(std::move(generator)) | |||
| { | |||
| m_chunk.reserve(m_chunk_size); | |||
| m_chunk.push_back(m_generator.get()); | |||
| for (size_t i = 1; i < m_chunk_size; ++i) { | |||
| if (!m_generator.next()) { | |||
| Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk")); | |||
| } | |||
| m_chunk.push_back(m_generator.get()); | |||
| } | |||
| } | |||
| std::vector<T> const& get() const override { | |||
| return m_chunk; | |||
| } | |||
| bool next() override { | |||
| m_chunk.clear(); | |||
| for (size_t idx = 0; idx < m_chunk_size; ++idx) { | |||
| if (!m_generator.next()) { | |||
| return false; | |||
| } | |||
| m_chunk.push_back(m_generator.get()); | |||
| } | |||
| return true; | |||
| } | |||
| }; | |||
| auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() ); | |||
| return generator.get(); | |||
| template <typename T> | |||
| GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) { | |||
| return GeneratorWrapper<std::vector<T>>( | |||
| pf::make_unique<ChunkGenerator<T>>(size, std::move(generator)) | |||
| ); | |||
| } | |||
| } // namespace Generators | |||
| } // namespace Catch | |||
| #define GENERATE( ... ) \ | |||
| Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) | |||
| // end catch_generators_generic.hpp | |||
| // start catch_generators_specific.hpp | |||
| // end catch_generators.hpp | |||
| // start catch_context.h | |||
| #include <memory> | |||
| namespace Catch { | |||
| struct IResultCapture; | |||
| struct IRunner; | |||
| struct IConfig; | |||
| struct IMutableContext; | |||
| using IConfigPtr = std::shared_ptr<IConfig const>; | |||
| struct IContext | |||
| { | |||
| virtual ~IContext(); | |||
| virtual IResultCapture* getResultCapture() = 0; | |||
| virtual IRunner* getRunner() = 0; | |||
| virtual IConfigPtr const& getConfig() const = 0; | |||
| }; | |||
| struct IMutableContext : IContext | |||
| { | |||
| virtual ~IMutableContext(); | |||
| virtual void setResultCapture( IResultCapture* resultCapture ) = 0; | |||
| virtual void setRunner( IRunner* runner ) = 0; | |||
| virtual void setConfig( IConfigPtr const& config ) = 0; | |||
| private: | |||
| static IMutableContext *currentContext; | |||
| friend IMutableContext& getCurrentMutableContext(); | |||
| friend void cleanUpContext(); | |||
| static void createContext(); | |||
| }; | |||
| inline IMutableContext& getCurrentMutableContext() | |||
| { | |||
| if( !IMutableContext::currentContext ) | |||
| IMutableContext::createContext(); | |||
| return *IMutableContext::currentContext; | |||
| } | |||
| inline IContext& getCurrentContext() | |||
| { | |||
| return getCurrentMutableContext(); | |||
| } | |||
| void cleanUpContext(); | |||
| } | |||
| // end catch_context.h | |||
| // start catch_interfaces_config.h | |||
| #include <iosfwd> | |||
| #include <string> | |||
| #include <vector> | |||
| #include <memory> | |||
| namespace Catch { | |||
| enum class Verbosity { | |||
| Quiet = 0, | |||
| Normal, | |||
| High | |||
| }; | |||
| struct WarnAbout { enum What { | |||
| Nothing = 0x00, | |||
| NoAssertions = 0x01, | |||
| NoTests = 0x02 | |||
| }; }; | |||
| struct ShowDurations { enum OrNot { | |||
| DefaultForReporter, | |||
| Always, | |||
| Never | |||
| }; }; | |||
| struct RunTests { enum InWhatOrder { | |||
| InDeclarationOrder, | |||
| InLexicographicalOrder, | |||
| InRandomOrder | |||
| }; }; | |||
| struct UseColour { enum YesOrNo { | |||
| Auto, | |||
| Yes, | |||
| No | |||
| }; }; | |||
| struct WaitForKeypress { enum When { | |||
| Never, | |||
| BeforeStart = 1, | |||
| BeforeExit = 2, | |||
| BeforeStartAndExit = BeforeStart | BeforeExit | |||
| }; }; | |||
| class TestSpec; | |||
| struct IConfig : NonCopyable { | |||
| virtual ~IConfig(); | |||
| virtual bool allowThrows() const = 0; | |||
| virtual std::ostream& stream() const = 0; | |||
| virtual std::string name() const = 0; | |||
| virtual bool includeSuccessfulResults() const = 0; | |||
| virtual bool shouldDebugBreak() const = 0; | |||
| virtual bool warnAboutMissingAssertions() const = 0; | |||
| virtual bool warnAboutNoTests() const = 0; | |||
| virtual int abortAfter() const = 0; | |||
| virtual bool showInvisibles() const = 0; | |||
| virtual ShowDurations::OrNot showDurations() const = 0; | |||
| virtual TestSpec const& testSpec() const = 0; | |||
| virtual bool hasTestFilters() const = 0; | |||
| virtual RunTests::InWhatOrder runOrder() const = 0; | |||
| virtual unsigned int rngSeed() const = 0; | |||
| virtual int benchmarkResolutionMultiple() const = 0; | |||
| virtual UseColour::YesOrNo useColour() const = 0; | |||
| virtual std::vector<std::string> const& getSectionsToRun() const = 0; | |||
| virtual Verbosity verbosity() const = 0; | |||
| }; | |||
| using IConfigPtr = std::shared_ptr<IConfig const>; | |||
| } | |||
| // end catch_interfaces_config.h | |||
| #include <random> | |||
| namespace Catch { | |||
| namespace Generators { | |||
| template <typename Float> | |||
| class RandomFloatingGenerator final : public IGenerator<Float> { | |||
| // FIXME: What is the right seed? | |||
| std::minstd_rand m_rand; | |||
| std::uniform_real_distribution<Float> m_dist; | |||
| Float m_current_number; | |||
| public: | |||
| RandomFloatingGenerator(Float a, Float b): | |||
| m_rand(getCurrentContext().getConfig()->rngSeed()), | |||
| 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_rand); | |||
| return true; | |||
| } | |||
| }; | |||
| template <typename Integer> | |||
| class RandomIntegerGenerator final : public IGenerator<Integer> { | |||
| std::minstd_rand m_rand; | |||
| std::uniform_int_distribution<Integer> m_dist; | |||
| Integer m_current_number; | |||
| public: | |||
| RandomIntegerGenerator(Integer a, Integer b): | |||
| m_rand(getCurrentContext().getConfig()->rngSeed()), | |||
| 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_rand); | |||
| return true; | |||
| } | |||
| }; | |||
| // TODO: Ideally this would be also constrained against the various char types, | |||
| // but I don't expect users to run into that in practice. | |||
| template <typename T> | |||
| typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value, | |||
| GeneratorWrapper<T>>::type | |||
| random(T a, T b) { | |||
| return GeneratorWrapper<T>( | |||
| pf::make_unique<RandomIntegerGenerator<T>>(a, b) | |||
| ); | |||
| } | |||
| template <typename T> | |||
| typename std::enable_if<std::is_floating_point<T>::value, | |||
| GeneratorWrapper<T>>::type | |||
| random(T a, T b) { | |||
| return GeneratorWrapper<T>( | |||
| pf::make_unique<RandomFloatingGenerator<T>>(a, b) | |||
| ); | |||
| } | |||
| 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_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer"); | |||
| return GeneratorWrapper<T>(pf::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>(pf::make_unique<RangeGenerator<T>>(start, end)); | |||
| } | |||
| } // namespace Generators | |||
| } // namespace Catch | |||
| // end catch_generators_specific.hpp | |||
| // These files are included here so the single_include script doesn't put them | |||
| // in the conditionally compiled sections | |||
| @@ -4321,79 +4639,6 @@ namespace Catch { | |||
| #endif | |||
| // end catch_test_spec_parser.h | |||
| // start catch_interfaces_config.h | |||
| #include <iosfwd> | |||
| #include <string> | |||
| #include <vector> | |||
| #include <memory> | |||
| namespace Catch { | |||
| enum class Verbosity { | |||
| Quiet = 0, | |||
| Normal, | |||
| High | |||
| }; | |||
| struct WarnAbout { enum What { | |||
| Nothing = 0x00, | |||
| NoAssertions = 0x01, | |||
| NoTests = 0x02 | |||
| }; }; | |||
| struct ShowDurations { enum OrNot { | |||
| DefaultForReporter, | |||
| Always, | |||
| Never | |||
| }; }; | |||
| struct RunTests { enum InWhatOrder { | |||
| InDeclarationOrder, | |||
| InLexicographicalOrder, | |||
| InRandomOrder | |||
| }; }; | |||
| struct UseColour { enum YesOrNo { | |||
| Auto, | |||
| Yes, | |||
| No | |||
| }; }; | |||
| struct WaitForKeypress { enum When { | |||
| Never, | |||
| BeforeStart = 1, | |||
| BeforeExit = 2, | |||
| BeforeStartAndExit = BeforeStart | BeforeExit | |||
| }; }; | |||
| class TestSpec; | |||
| struct IConfig : NonCopyable { | |||
| virtual ~IConfig(); | |||
| virtual bool allowThrows() const = 0; | |||
| virtual std::ostream& stream() const = 0; | |||
| virtual std::string name() const = 0; | |||
| virtual bool includeSuccessfulResults() const = 0; | |||
| virtual bool shouldDebugBreak() const = 0; | |||
| virtual bool warnAboutMissingAssertions() const = 0; | |||
| virtual bool warnAboutNoTests() const = 0; | |||
| virtual int abortAfter() const = 0; | |||
| virtual bool showInvisibles() const = 0; | |||
| virtual ShowDurations::OrNot showDurations() const = 0; | |||
| virtual TestSpec const& testSpec() const = 0; | |||
| virtual bool hasTestFilters() const = 0; | |||
| virtual RunTests::InWhatOrder runOrder() const = 0; | |||
| virtual unsigned int rngSeed() const = 0; | |||
| virtual int benchmarkResolutionMultiple() const = 0; | |||
| virtual UseColour::YesOrNo useColour() const = 0; | |||
| virtual std::vector<std::string> const& getSectionsToRun() const = 0; | |||
| virtual Verbosity verbosity() const = 0; | |||
| }; | |||
| using IConfigPtr = std::shared_ptr<IConfig const>; | |||
| } | |||
| // end catch_interfaces_config.h | |||
| // Libstdc++ doesn't like incomplete classes for unique_ptr | |||
| #include <memory> | |||
| @@ -4673,8 +4918,8 @@ namespace Catch { | |||
| AssertionStats( AssertionStats const& ) = default; | |||
| AssertionStats( AssertionStats && ) = default; | |||
| AssertionStats& operator = ( AssertionStats const& ) = default; | |||
| AssertionStats& operator = ( AssertionStats && ) = default; | |||
| AssertionStats& operator = ( AssertionStats const& ) = delete; | |||
| AssertionStats& operator = ( AssertionStats && ) = delete; | |||
| virtual ~AssertionStats(); | |||
| AssertionResult assertionResult; | |||
| @@ -5758,58 +6003,6 @@ std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx co | |||
| // end catch_approx.cpp | |||
| // start catch_assertionhandler.cpp | |||
| // start catch_context.h | |||
| #include <memory> | |||
| namespace Catch { | |||
| struct IResultCapture; | |||
| struct IRunner; | |||
| struct IConfig; | |||
| struct IMutableContext; | |||
| using IConfigPtr = std::shared_ptr<IConfig const>; | |||
| struct IContext | |||
| { | |||
| virtual ~IContext(); | |||
| virtual IResultCapture* getResultCapture() = 0; | |||
| virtual IRunner* getRunner() = 0; | |||
| virtual IConfigPtr const& getConfig() const = 0; | |||
| }; | |||
| struct IMutableContext : IContext | |||
| { | |||
| virtual ~IMutableContext(); | |||
| virtual void setResultCapture( IResultCapture* resultCapture ) = 0; | |||
| virtual void setRunner( IRunner* runner ) = 0; | |||
| virtual void setConfig( IConfigPtr const& config ) = 0; | |||
| private: | |||
| static IMutableContext *currentContext; | |||
| friend IMutableContext& getCurrentMutableContext(); | |||
| friend void cleanUpContext(); | |||
| static void createContext(); | |||
| }; | |||
| inline IMutableContext& getCurrentMutableContext() | |||
| { | |||
| if( !IMutableContext::currentContext ) | |||
| IMutableContext::createContext(); | |||
| return *IMutableContext::currentContext; | |||
| } | |||
| inline IContext& getCurrentContext() | |||
| { | |||
| return getCurrentMutableContext(); | |||
| } | |||
| void cleanUpContext(); | |||
| } | |||
| // end catch_context.h | |||
| // start catch_debugger.h | |||
| namespace Catch { | |||
| @@ -5996,6 +6189,8 @@ namespace Catch { | |||
| void pushScopedMessage( MessageInfo const& message ) override; | |||
| void popScopedMessage( MessageInfo const& message ) override; | |||
| void emplaceUnscopedMessage( MessageBuilder const& builder ) override; | |||
| std::string getCurrentTestName() const override; | |||
| const AssertionResult* getLastResult() const override; | |||
| @@ -6043,6 +6238,7 @@ namespace Catch { | |||
| Totals m_totals; | |||
| IStreamingReporterPtr m_reporter; | |||
| std::vector<MessageInfo> m_messages; | |||
| std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */ | |||
| AssertionInfo m_lastAssertionInfo; | |||
| std::vector<SectionEndInfo> m_unfinishedSections; | |||
| std::vector<ITracker*> m_activeSections; | |||
| @@ -6679,6 +6875,7 @@ inline auto Column::operator + (Column const& other) -> Columns { | |||
| // ----------- end of #include from clara_textflow.hpp ----------- | |||
| // ........... back in clara.hpp | |||
| #include <cctype> | |||
| #include <string> | |||
| #include <memory> | |||
| #include <set> | |||
| @@ -6971,7 +7168,7 @@ namespace detail { | |||
| } | |||
| inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { | |||
| std::string srcLC = source; | |||
| std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( ::tolower(c) ); } ); | |||
| std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( std::tolower(c) ); } ); | |||
| if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") | |||
| target = true; | |||
| else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") | |||
| @@ -9374,14 +9571,20 @@ namespace Catch { | |||
| //////////////////////////////////////////////////////////////////////////// | |||
| ScopedMessage::ScopedMessage( MessageBuilder const& builder ) | |||
| : m_info( builder.m_info ) | |||
| : m_info( builder.m_info ), m_moved() | |||
| { | |||
| m_info.message = builder.m_stream.str(); | |||
| getResultCapture().pushScopedMessage( m_info ); | |||
| } | |||
| ScopedMessage::ScopedMessage( ScopedMessage&& old ) | |||
| : m_info( old.m_info ), m_moved() | |||
| { | |||
| old.m_moved = true; | |||
| } | |||
| ScopedMessage::~ScopedMessage() { | |||
| if ( !uncaught_exceptions() ){ | |||
| if ( !uncaught_exceptions() && !m_moved ){ | |||
| getResultCapture().popScopedMessage(m_info); | |||
| } | |||
| } | |||
| @@ -9489,6 +9692,22 @@ namespace Catch { | |||
| auto str() const -> std::string; | |||
| }; | |||
| class RedirectedStreams { | |||
| public: | |||
| RedirectedStreams(RedirectedStreams const&) = delete; | |||
| RedirectedStreams& operator=(RedirectedStreams const&) = delete; | |||
| RedirectedStreams(RedirectedStreams&&) = delete; | |||
| RedirectedStreams& operator=(RedirectedStreams&&) = delete; | |||
| RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr); | |||
| ~RedirectedStreams(); | |||
| private: | |||
| std::string& m_redirectedCout; | |||
| std::string& m_redirectedCerr; | |||
| RedirectedStdOut m_redirectedStdOut; | |||
| RedirectedStdErr m_redirectedStdErr; | |||
| }; | |||
| #if defined(CATCH_CONFIG_NEW_CAPTURE) | |||
| // Windows's implementation of std::tmpfile is terrible (it tries | |||
| @@ -9580,6 +9799,16 @@ namespace Catch { | |||
| {} | |||
| auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); } | |||
| RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr) | |||
| : m_redirectedCout(redirectedCout), | |||
| m_redirectedCerr(redirectedCerr) | |||
| {} | |||
| RedirectedStreams::~RedirectedStreams() { | |||
| m_redirectedCout += m_redirectedStdOut.str(); | |||
| m_redirectedCerr += m_redirectedStdErr.str(); | |||
| } | |||
| #if defined(CATCH_CONFIG_NEW_CAPTURE) | |||
| #if defined(_MSC_VER) | |||
| @@ -10161,6 +10390,9 @@ namespace Catch { | |||
| // and should be let to clear themselves out. | |||
| static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); | |||
| if (result.getResultType() != ResultWas::Warning) | |||
| m_messageScopes.clear(); | |||
| // Reset working state | |||
| resetAssertionInfo(); | |||
| m_lastResult = result; | |||
| @@ -10215,6 +10447,7 @@ namespace Catch { | |||
| m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); | |||
| m_messages.clear(); | |||
| m_messageScopes.clear(); | |||
| } | |||
| void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { | |||
| @@ -10241,6 +10474,10 @@ namespace Catch { | |||
| m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); | |||
| } | |||
| void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) { | |||
| m_messageScopes.emplace_back( builder ); | |||
| } | |||
| std::string RunContext::getCurrentTestName() const { | |||
| return m_activeTestCase | |||
| ? m_activeTestCase->getTestCaseInfo().name | |||
| @@ -10301,6 +10538,7 @@ namespace Catch { | |||
| m_lastAssertionPassed = true; | |||
| ++m_totals.assertions.passed; | |||
| resetAssertionInfo(); | |||
| m_messageScopes.clear(); | |||
| } | |||
| bool RunContext::aborting() const { | |||
| @@ -10322,13 +10560,10 @@ namespace Catch { | |||
| CATCH_TRY { | |||
| if (m_reporter->getPreferences().shouldRedirectStdOut) { | |||
| #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) | |||
| RedirectedStdOut redirectedStdOut; | |||
| RedirectedStdErr redirectedStdErr; | |||
| RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr); | |||
| timer.start(); | |||
| invokeActiveTestCase(); | |||
| redirectedCout += redirectedStdOut.str(); | |||
| redirectedCerr += redirectedStdErr.str(); | |||
| #else | |||
| OutputRedirect r(redirectedCout, redirectedCerr); | |||
| timer.start(); | |||
| @@ -10355,6 +10590,7 @@ namespace Catch { | |||
| m_testCaseTracker->close(); | |||
| handleUnfinishedSections(); | |||
| m_messages.clear(); | |||
| m_messageScopes.clear(); | |||
| SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); | |||
| m_reporter->sectionEnded(testCaseSectionStats); | |||
| @@ -10762,9 +10998,9 @@ namespace Catch { | |||
| return 1; | |||
| auto result = m_cli.parse( clara::Args( argc, argv ) ); | |||
| config(); | |||
| getCurrentMutableContext().setConfig( m_config ); | |||
| if( !result ) { | |||
| config(); | |||
| getCurrentMutableContext().setConfig(m_config); | |||
| Catch::cerr() | |||
| << Colour( Colour::Red ) | |||
| << "\nError(s) in input:\n" | |||
| @@ -12429,7 +12665,7 @@ namespace Catch { | |||
| } | |||
| Version const& libraryVersion() { | |||
| static Version version( 2, 6, 1, "", 0 ); | |||
| static Version version( 2, 7, 0, "", 0 ); | |||
| return version; | |||
| } | |||
| @@ -12781,7 +13017,7 @@ namespace Catch { | |||
| #ifdef _MSC_VER | |||
| sprintf_s(buffer, "%.3f", duration); | |||
| #else | |||
| sprintf(buffer, "%.3f", duration); | |||
| std::sprintf(buffer, "%.3f", duration); | |||
| #endif | |||
| return std::string(buffer); | |||
| } | |||
| @@ -13315,7 +13551,7 @@ public: | |||
| case Unit::Nanoseconds: | |||
| return "ns"; | |||
| case Unit::Microseconds: | |||
| return "µs"; | |||
| return "us"; | |||
| case Unit::Milliseconds: | |||
| return "ms"; | |||
| case Unit::Seconds: | |||
| @@ -14464,6 +14700,7 @@ int main (int argc, char * const argv[]) { | |||
| #endif // CATCH_CONFIG_DISABLE_MATCHERS | |||
| #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) | |||
| #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) | |||
| #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) | |||
| #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) | |||