Merge pull request #459 from lioncash/catch

externals: Update catch to 2.7.0
This commit is contained in:
Merry 2019-03-28 14:42:02 +00:00 committed by MerryMage
commit 3a0b9e8883

View file

@ -1,6 +1,6 @@
/* /*
* Catch v2.6.1 * Catch v2.7.0
* Generated: 2019-02-12 19:52:52.262497 * Generated: 2019-03-07 21:34:30.252164
* ---------------------------------------------------------- * ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly * This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved.
@ -14,8 +14,8 @@
#define CATCH_VERSION_MAJOR 2 #define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 6 #define CATCH_VERSION_MINOR 7
#define CATCH_VERSION_PATCH 1 #define CATCH_VERSION_PATCH 0
#ifdef __clang__ #ifdef __clang__
# pragma clang system_header # 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_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF #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__) #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__))) #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
#endif #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)\ #define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(types)\
CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,INTERNAL_CATCH_REMOVE_PARENS(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> #include <type_traits>
namespace Catch {
template< typename... > template< typename... >
struct TypeList{}; struct TypeList {};
template< typename... > template< typename... >
struct append; struct append;
template< template<typename...> class L1 template< template<typename...> class L1
, typename...E1 , typename...E1
, template<typename...> class L2 , template<typename...> class L2
, typename...E2 , typename...E2
> >
struct append< L1<E1...>, L2<E2...> > struct append< L1<E1...>, L2<E2...> > {
{ using type = L1<E1..., E2...>;
using type = L1<E1..., E2...>;
}; };
template< template<typename...> class L1 template< template<typename...> class L1
, typename...E1 , typename...E1
, template<typename...> class L2 , template<typename...> class L2
, typename...E2 , typename...E2
, typename...Rest , typename...Rest
> >
struct append< L1<E1...>, L2<E2...>, Rest...> struct append< L1<E1...>, L2<E2...>, Rest...> {
{ using type = typename append< L1<E1..., E2...>, Rest... >::type;
using type = typename append< L1<E1..., E2...>, Rest... >::type;
}; };
template< template<typename...> class template< template<typename...> class
, typename... , typename...
> >
struct rewrap; struct rewrap;
template< template<typename...> class Container template< template<typename...> class Container
, template<typename...> class List , template<typename...> class List
, typename...elems , typename...elems
> >
struct rewrap<Container, List<elems...>> struct rewrap<Container, List<elems...>> {
{
using type = TypeList< Container< elems... > >; using type = TypeList< Container< elems... > >;
}; };
template< template<typename...> class Container template< template<typename...> class Container
, template<typename...> class List , template<typename...> class List
, class...Elems , class...Elems
, typename...Elements> , typename...Elements>
struct rewrap<Container, List<Elems...>, Elements...> struct rewrap<Container, List<Elems...>, Elements...> {
{
using type = typename append<TypeList<Container<Elems...>>, typename rewrap<Container, Elements...>::type>::type; using type = typename append<TypeList<Container<Elems...>>, typename rewrap<Container, Elements...>::type>::type;
}; };
template< template<typename...> class...Containers > template< template<typename...> class...Containers >
struct combine struct combine {
{
template< typename...Types > template< typename...Types >
struct with_types struct with_types {
{
template< template <typename...> class Final > template< template <typename...> class Final >
struct into struct into {
{
using type = typename append<Final<>, typename rewrap<Containers, Types...>::type...>::type; using type = typename append<Final<>, typename rewrap<Containers, Types...>::type...>::type;
}; };
}; };
@ -803,6 +807,8 @@ struct combine
template<typename T> template<typename T>
struct always_false : std::false_type {}; struct always_false : std::false_type {};
} // namespace Catch
// end catch_meta.hpp // end catch_meta.hpp
namespace Catch { namespace Catch {
@ -949,11 +955,14 @@ struct AutoReg : NonCopyable {
CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...) \ CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...) \
int index = 0; \ int index = 0; \
using expander = int[]; \ 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 ) = [](){ \ 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; \ ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestName>::type; \
TestInit(); \ TestInit(); \
return 0; \ return 0; \
@ -1014,11 +1023,14 @@ struct AutoReg : NonCopyable {
CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\ CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\
int index = 0;\ int index = 0;\
using expander = int[];\ 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 ) = [](){\ 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;\ ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestNameClass>::type;\
TestInit();\ TestInit();\
return 0;\ return 0;\
@ -2062,6 +2074,7 @@ namespace Catch {
struct SectionInfo; struct SectionInfo;
struct SectionEndInfo; struct SectionEndInfo;
struct MessageInfo; struct MessageInfo;
struct MessageBuilder;
struct Counts; struct Counts;
struct BenchmarkInfo; struct BenchmarkInfo;
struct BenchmarkStats; struct BenchmarkStats;
@ -2088,6 +2101,8 @@ namespace Catch {
virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void pushScopedMessage( MessageInfo const& message ) = 0;
virtual void popScopedMessage( 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 handleFatalErrorCondition( StringRef message ) = 0;
virtual void handleExpr virtual void handleExpr
@ -2251,9 +2266,12 @@ namespace Catch {
class ScopedMessage { class ScopedMessage {
public: public:
explicit ScopedMessage( MessageBuilder const& builder ); explicit ScopedMessage( MessageBuilder const& builder );
ScopedMessage( ScopedMessage& duplicate ) = delete;
ScopedMessage( ScopedMessage&& old );
~ScopedMessage(); ~ScopedMessage();
MessageInfo m_info; MessageInfo m_info;
bool m_moved;
}; };
class Capturer { class Capturer {
@ -2316,7 +2334,7 @@ namespace Catch {
CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
} INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
INTERNAL_CATCH_REACT( 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 &&. // 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 ) \ #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 ); 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 // Although this is matcher-based, it can be used with just a string
#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ #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 )... ); 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> template <typename T>
class TakeGenerator : public IGenerator<T> { class TakeGenerator : public IGenerator<T> {
GeneratorWrapper<T> m_generator; GeneratorWrapper<T> m_generator;
@ -3810,31 +3862,297 @@ namespace Generators {
); );
} }
auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&; template <typename T>
class ChunkGenerator final : public IGenerator<std::vector<T>> {
template<typename L> std::vector<T> m_chunk;
// Note: The type after -> is weird, because VS2015 cannot parse size_t m_chunk_size;
// the expression used in the typedef inside, when it is in GeneratorWrapper<T> m_generator;
// return type. Yeah, ¯\_(ツ)_/¯ bool m_used_up = false;
auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) { public:
using UnderlyingType = typename decltype(generatorExpression())::type; ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :
m_chunk_size(size), m_generator(std::move(generator))
IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo ); {
if (!tracker.hasGenerator()) { m_chunk.reserve(m_chunk_size);
tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression())); 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() ); template <typename T>
return generator.get(); 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 Generators
} // namespace Catch } // namespace Catch
#define GENERATE( ... ) \ // end catch_generators_generic.hpp
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) // 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 // These files are included here so the single_include script doesn't put them
// in the conditionally compiled sections // in the conditionally compiled sections
@ -4321,79 +4639,6 @@ namespace Catch {
#endif #endif
// end catch_test_spec_parser.h // 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 // Libstdc++ doesn't like incomplete classes for unique_ptr
#include <memory> #include <memory>
@ -4673,8 +4918,8 @@ namespace Catch {
AssertionStats( AssertionStats const& ) = default; AssertionStats( AssertionStats const& ) = default;
AssertionStats( AssertionStats && ) = default; AssertionStats( AssertionStats && ) = default;
AssertionStats& operator = ( AssertionStats const& ) = default; AssertionStats& operator = ( AssertionStats const& ) = delete;
AssertionStats& operator = ( AssertionStats && ) = default; AssertionStats& operator = ( AssertionStats && ) = delete;
virtual ~AssertionStats(); virtual ~AssertionStats();
AssertionResult assertionResult; AssertionResult assertionResult;
@ -5758,58 +6003,6 @@ std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx co
// end catch_approx.cpp // end catch_approx.cpp
// start catch_assertionhandler.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 // start catch_debugger.h
namespace Catch { namespace Catch {
@ -5996,6 +6189,8 @@ namespace Catch {
void pushScopedMessage( MessageInfo const& message ) override; void pushScopedMessage( MessageInfo const& message ) override;
void popScopedMessage( MessageInfo const& message ) override; void popScopedMessage( MessageInfo const& message ) override;
void emplaceUnscopedMessage( MessageBuilder const& builder ) override;
std::string getCurrentTestName() const override; std::string getCurrentTestName() const override;
const AssertionResult* getLastResult() const override; const AssertionResult* getLastResult() const override;
@ -6043,6 +6238,7 @@ namespace Catch {
Totals m_totals; Totals m_totals;
IStreamingReporterPtr m_reporter; IStreamingReporterPtr m_reporter;
std::vector<MessageInfo> m_messages; std::vector<MessageInfo> m_messages;
std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
AssertionInfo m_lastAssertionInfo; AssertionInfo m_lastAssertionInfo;
std::vector<SectionEndInfo> m_unfinishedSections; std::vector<SectionEndInfo> m_unfinishedSections;
std::vector<ITracker*> m_activeSections; std::vector<ITracker*> m_activeSections;
@ -6679,6 +6875,7 @@ inline auto Column::operator + (Column const& other) -> Columns {
// ----------- end of #include from clara_textflow.hpp ----------- // ----------- end of #include from clara_textflow.hpp -----------
// ........... back in clara.hpp // ........... back in clara.hpp
#include <cctype>
#include <string> #include <string>
#include <memory> #include <memory>
#include <set> #include <set>
@ -6971,7 +7168,7 @@ namespace detail {
} }
inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
std::string srcLC = source; 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") if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
target = true; target = true;
else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
@ -9374,14 +9571,20 @@ namespace Catch {
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
ScopedMessage::ScopedMessage( MessageBuilder const& builder ) ScopedMessage::ScopedMessage( MessageBuilder const& builder )
: m_info( builder.m_info ) : m_info( builder.m_info ), m_moved()
{ {
m_info.message = builder.m_stream.str(); m_info.message = builder.m_stream.str();
getResultCapture().pushScopedMessage( m_info ); getResultCapture().pushScopedMessage( m_info );
} }
ScopedMessage::ScopedMessage( ScopedMessage&& old )
: m_info( old.m_info ), m_moved()
{
old.m_moved = true;
}
ScopedMessage::~ScopedMessage() { ScopedMessage::~ScopedMessage() {
if ( !uncaught_exceptions() ){ if ( !uncaught_exceptions() && !m_moved ){
getResultCapture().popScopedMessage(m_info); getResultCapture().popScopedMessage(m_info);
} }
} }
@ -9489,6 +9692,22 @@ namespace Catch {
auto str() const -> std::string; 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) #if defined(CATCH_CONFIG_NEW_CAPTURE)
// Windows's implementation of std::tmpfile is terrible (it tries // 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(); } 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(CATCH_CONFIG_NEW_CAPTURE)
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -10161,6 +10390,9 @@ namespace Catch {
// and should be let to clear themselves out. // and should be let to clear themselves out.
static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
if (result.getResultType() != ResultWas::Warning)
m_messageScopes.clear();
// Reset working state // Reset working state
resetAssertionInfo(); resetAssertionInfo();
m_lastResult = result; m_lastResult = result;
@ -10215,6 +10447,7 @@ namespace Catch {
m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
m_messages.clear(); m_messages.clear();
m_messageScopes.clear();
} }
void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { 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()); 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 { std::string RunContext::getCurrentTestName() const {
return m_activeTestCase return m_activeTestCase
? m_activeTestCase->getTestCaseInfo().name ? m_activeTestCase->getTestCaseInfo().name
@ -10301,6 +10538,7 @@ namespace Catch {
m_lastAssertionPassed = true; m_lastAssertionPassed = true;
++m_totals.assertions.passed; ++m_totals.assertions.passed;
resetAssertionInfo(); resetAssertionInfo();
m_messageScopes.clear();
} }
bool RunContext::aborting() const { bool RunContext::aborting() const {
@ -10322,13 +10560,10 @@ namespace Catch {
CATCH_TRY { CATCH_TRY {
if (m_reporter->getPreferences().shouldRedirectStdOut) { if (m_reporter->getPreferences().shouldRedirectStdOut) {
#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
RedirectedStdOut redirectedStdOut; RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
RedirectedStdErr redirectedStdErr;
timer.start(); timer.start();
invokeActiveTestCase(); invokeActiveTestCase();
redirectedCout += redirectedStdOut.str();
redirectedCerr += redirectedStdErr.str();
#else #else
OutputRedirect r(redirectedCout, redirectedCerr); OutputRedirect r(redirectedCout, redirectedCerr);
timer.start(); timer.start();
@ -10355,6 +10590,7 @@ namespace Catch {
m_testCaseTracker->close(); m_testCaseTracker->close();
handleUnfinishedSections(); handleUnfinishedSections();
m_messages.clear(); m_messages.clear();
m_messageScopes.clear();
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
m_reporter->sectionEnded(testCaseSectionStats); m_reporter->sectionEnded(testCaseSectionStats);
@ -10762,9 +10998,9 @@ namespace Catch {
return 1; return 1;
auto result = m_cli.parse( clara::Args( argc, argv ) ); auto result = m_cli.parse( clara::Args( argc, argv ) );
config();
getCurrentMutableContext().setConfig( m_config );
if( !result ) { if( !result ) {
config();
getCurrentMutableContext().setConfig(m_config);
Catch::cerr() Catch::cerr()
<< Colour( Colour::Red ) << Colour( Colour::Red )
<< "\nError(s) in input:\n" << "\nError(s) in input:\n"
@ -12429,7 +12665,7 @@ namespace Catch {
} }
Version const& libraryVersion() { Version const& libraryVersion() {
static Version version( 2, 6, 1, "", 0 ); static Version version( 2, 7, 0, "", 0 );
return version; return version;
} }
@ -12781,7 +13017,7 @@ namespace Catch {
#ifdef _MSC_VER #ifdef _MSC_VER
sprintf_s(buffer, "%.3f", duration); sprintf_s(buffer, "%.3f", duration);
#else #else
sprintf(buffer, "%.3f", duration); std::sprintf(buffer, "%.3f", duration);
#endif #endif
return std::string(buffer); return std::string(buffer);
} }
@ -13315,7 +13551,7 @@ public:
case Unit::Nanoseconds: case Unit::Nanoseconds:
return "ns"; return "ns";
case Unit::Microseconds: case Unit::Microseconds:
return "µs"; return "us";
case Unit::Milliseconds: case Unit::Milliseconds:
return "ms"; return "ms";
case Unit::Seconds: case Unit::Seconds:
@ -14464,6 +14700,7 @@ int main (int argc, char * const argv[]) {
#endif // CATCH_CONFIG_DISABLE_MATCHERS #endif // CATCH_CONFIG_DISABLE_MATCHERS
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #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 WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )