diff --git a/conanfile.py b/conanfile.py index d1dfa81d..5c7d9931 100644 --- a/conanfile.py +++ b/conanfile.py @@ -4,7 +4,7 @@ from conans import ConanFile class CatchConan(ConanFile): name = "Catch" - version = "2.0.0-develop.4" + version = "2.0.0-develop.5" description = "A modern, C++-native, header-only, framework for unit-tests, TDD and BDD" author = "philsquared" generators = "cmake" diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp index b635800b..e684f3f9 100644 --- a/include/internal/catch_version.cpp +++ b/include/internal/catch_version.cpp @@ -37,7 +37,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 4 ); + static Version version( 2, 0, 0, "develop", 5 ); return version; } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index e5ae6198..f9568b0c 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v2.0.0-develop.4 - * Generated: 2017-09-19 17:37:34.480115 + * Catch v2.0.0-develop.5 + * Generated: 2017-10-12 13:05:08.135067 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2017 Two Blue Cubes Ltd. All rights reserved. @@ -480,7 +480,6 @@ struct AutoReg : NonCopyable { #include #include #include -#include #include #include @@ -749,7 +748,53 @@ namespace Catch { } }; - // === Pair === + template + struct EnumStringMaker { + static std::string convert(const T& t) { + return ::Catch::Detail::stringify(static_cast::type>(t)); + } + }; + +#ifdef __OBJC__ + template<> + struct StringMaker { + static std::string convert(NSString * nsstring) { + if (!nsstring) + return "nil"; + return std::string("@") + [nsstring UTF8String]; + } + }; + template<> + struct StringMaker { + static std::string convert(NSObject* nsObject) { + return ::Catch::Detail::stringify([nsObject description]); + } + + }; + namespace Detail { + inline std::string stringify( NSString* nsstring ) { + return StringMaker::convert( nsstring ); + } + + } // namespace Detail +#endif // __OBJC__ + +} // namespace Catch + +////////////////////////////////////////////////////// +// Separate std-lib types stringification, so it can be selectively enabled +// This means that we do not bring in + +#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) +# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER +# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +#endif + +// Separate std::pair specialization +#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) +#include +namespace Catch { template struct StringMaker > { static std::string convert(const std::pair& pair) { @@ -762,7 +807,13 @@ namespace Catch { return oss.str(); } }; +} +#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER +// Separate std::tuple specialization +#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) +#include +namespace Catch { namespace Detail { template< typename Tuple, @@ -797,39 +848,124 @@ namespace Catch { return os.str(); } }; +} +#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER - template - struct EnumStringMaker { - static std::string convert(const T& t) { - return ::Catch::Detail::stringify(static_cast::type>(t)); +// Separate std::chrono::duration specialization +#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +#include +#include +#include + +template +struct ratio_string { + static std::string symbol(); +}; + +template +std::string ratio_string::symbol() { + std::ostringstream oss; + oss << '[' << Ratio::num << '/' + << Ratio::den << ']'; + return oss.str(); +} +template <> +struct ratio_string { + static std::string symbol() { return "a"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "f"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "p"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "n"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "u"; } +}; +template <> +struct ratio_string { + static std::string symbol() { return "m"; } +}; + +namespace Catch { + //////////// + // std::chrono::duration specializations + template + struct StringMaker> { + static std::string convert(std::chrono::duration const& duration) { + std::ostringstream oss; + oss << duration.count() << ' ' << ratio_string::symbol() << 's'; + return oss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + std::ostringstream oss; + oss << duration.count() << " s"; + return oss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + std::ostringstream oss; + oss << duration.count() << " m"; + return oss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + std::ostringstream oss; + oss << duration.count() << " h"; + return oss.str(); } }; -#ifdef __OBJC__ - template<> - struct StringMaker { - static std::string convert(NSString * nsstring) { - if (!nsstring) - return "nil"; - return std::string("@") + [nsstring UTF8String]; + //////////// + // std::chrono::time_point specialization + // Generic time_point cannot be specialized, only std::chrono::time_point + template + struct StringMaker> { + static std::string convert(std::chrono::time_point const& time_point) { + return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; } }; - template<> - struct StringMaker { - static std::string convert(NSObject* nsObject) { - return ::Catch::Detail::stringify([nsObject description]); - } + // std::chrono::time_point specialization + template + struct StringMaker> { + static std::string convert(std::chrono::time_point const& time_point) { + auto converted = std::chrono::system_clock::to_time_t(time_point); +#ifdef _MSC_VER + std::tm timeInfo = {}; + gmtime_s(&timeInfo, &converted); +#else + std::tm* timeInfo = std::gmtime(&converted); +#endif + + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + char timeStamp[timeStampSize]; + const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; + +#ifdef _MSC_VER + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); +#else + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); +#endif + return std::string(timeStamp); + } }; - namespace Detail { - inline std::string stringify( NSString* nsstring ) { - return StringMaker::convert( nsstring ); - } - - } // namespace Detail -#endif // __OBJC__ - -} // namespace Catch +} +#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER #ifdef _MSC_VER #pragma warning(pop) @@ -1614,6 +1750,7 @@ namespace Catch { static std::string translatorName( signature ) #endif +#include #include #include @@ -1646,7 +1783,7 @@ namespace Catch { std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { try { if( it == itEnd ) - throw; + std::rethrow_exception(std::current_exception()); else return (*it)->translate( it+1, itEnd ); } @@ -4205,6 +4342,10 @@ namespace Catch { #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 #endif +#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH +#endif + // ----------- #included from clara_textflow.hpp ----------- // TextFlowCpp @@ -4538,9 +4679,8 @@ namespace Catch { namespace clara { namespace TextFlow { #include #include -#if !defined(CLARA_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) -#define CLARA_PLATFORM_WINDOWS - +#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) +#define CATCH_PLATFORM_WINDOWS #endif namespace Catch { namespace clara { @@ -4548,15 +4688,15 @@ namespace detail { // Traits for extracting arg and return type of lambdas (for single argument lambdas) template - struct UnaryLambdaTraits : UnaryLambdaTraits {}; + struct UnaryLambdaTraits : UnaryLambdaTraits {}; template - struct UnaryLambdaTraits { + struct UnaryLambdaTraits { static const bool isValid = false; }; template - struct UnaryLambdaTraits { + struct UnaryLambdaTraits { static const bool isValid = true; using ArgType = typename std::remove_const::type>::type;; using ReturnType = ReturnT; @@ -4571,13 +4711,13 @@ namespace detail { std::vector m_args; public: - Args(int argc, char *argv[]) { + Args( int argc, char *argv[] ) { m_exeName = argv[0]; - for (int i = 1; i < argc; ++i) - m_args.push_back(argv[i]); + for( int i = 1; i < argc; ++i ) + m_args.push_back( argv[i] ); } - Args(std::initializer_list args) + Args( std::initializer_list args ) : m_exeName( *args.begin() ), m_args( args.begin()+1, args.end() ) {} @@ -4605,40 +4745,40 @@ namespace detail { std::vector m_tokenBuffer; void loadBuffer() { - m_tokenBuffer.resize(0); + m_tokenBuffer.resize( 0 ); // Skip any empty strings - while (it != itEnd && it->empty()) + while( it != itEnd && it->empty() ) ++it; - if (it != itEnd) { + if( it != itEnd ) { auto const &next = *it; - if (next[0] == '-' || next[0] == '/') { - auto delimiterPos = next.find_first_of(" :="); - if (delimiterPos != std::string::npos) { - m_tokenBuffer.push_back({TokenType::Option, next.substr(0, delimiterPos)}); - m_tokenBuffer.push_back({TokenType::Argument, next.substr(delimiterPos + 1)}); + if( next[0] == '-' || next[0] == '/' ) { + auto delimiterPos = next.find_first_of( " :=" ); + if( delimiterPos != std::string::npos ) { + m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); + m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } ); } else { - if (next[1] != '-' && next.size() > 2) { + if( next[1] != '-' && next.size() > 2 ) { std::string opt = "- "; - for (size_t i = 1; i < next.size(); ++i) { + for( size_t i = 1; i < next.size(); ++i ) { opt[1] = next[i]; - m_tokenBuffer.push_back({TokenType::Option, opt}); + m_tokenBuffer.push_back( { TokenType::Option, opt } ); } } else { - m_tokenBuffer.push_back({TokenType::Option, next}); + m_tokenBuffer.push_back( { TokenType::Option, next } ); } } } else { - m_tokenBuffer.push_back({TokenType::Argument, next}); + m_tokenBuffer.push_back( { TokenType::Argument, next } ); } } } public: - explicit TokenStream(Args const &args) : TokenStream(args.m_args.begin(), args.m_args.end()) {} + explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {} - TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { + TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) { loadBuffer(); } @@ -4649,20 +4789,20 @@ namespace detail { auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } auto operator*() const -> Token { - assert(!m_tokenBuffer.empty()); + assert( !m_tokenBuffer.empty() ); return m_tokenBuffer.front(); } auto operator->() const -> Token const * { - assert(!m_tokenBuffer.empty()); + assert( !m_tokenBuffer.empty() ); return &m_tokenBuffer.front(); } auto operator++() -> TokenStream & { - if (m_tokenBuffer.size() >= 2) { - m_tokenBuffer.erase(m_tokenBuffer.begin()); + if( m_tokenBuffer.size() >= 2 ) { + m_tokenBuffer.erase( m_tokenBuffer.begin() ); } else { - if (it != itEnd) + if( it != itEnd ) ++it; loadBuffer(); } @@ -4677,7 +4817,7 @@ namespace detail { }; protected: - ResultBase(Type type) : m_type(type) {} + ResultBase( Type type ) : m_type( type ) {} virtual ~ResultBase() = default; virtual void enforceOk() const = 0; @@ -4694,28 +4834,28 @@ namespace detail { } protected: - ResultValueBase(Type type) : ResultBase(type) {} + ResultValueBase( Type type ) : ResultBase( type ) {} - ResultValueBase(ResultValueBase const &other) : ResultBase(other) { - if (m_type == ResultBase::Ok) - new(&m_value) T(other.m_value); + ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) { + if( m_type == ResultBase::Ok ) + new( &m_value ) T( other.m_value ); } - ResultValueBase(Type, T const &value) : ResultBase(Ok) { - new(&m_value) T(value); + ResultValueBase( Type, T const &value ) : ResultBase( Ok ) { + new( &m_value ) T( value ); } - auto operator=(ResultValueBase const &other) -> ResultValueBase & { - if (m_type == ResultBase::Ok) + auto operator=( ResultValueBase const &other ) -> ResultValueBase & { + if( m_type == ResultBase::Ok ) m_value.~T(); ResultBase::operator=(other); - if (m_type == ResultBase::Ok) - new(&m_value) T(other.m_value); + if( m_type == ResultBase::Ok ) + new( &m_value ) T( other.m_value ); return *this; } ~ResultValueBase() { - if (m_type == Ok) + if( m_type == Ok ) m_value.~T(); } @@ -4734,37 +4874,31 @@ namespace detail { class BasicResult : public ResultValueBase { public: template - explicit BasicResult(BasicResult const &other) - : ResultValueBase(other.type()), - m_errorMessage(other.errorMessage()) { - assert(type() != ResultBase::Ok); + explicit BasicResult( BasicResult const &other ) + : ResultValueBase( other.type() ), + m_errorMessage( other.errorMessage() ) + { + assert( type() != ResultBase::Ok ); } - static auto ok() -> BasicResult { return {ResultBase::Ok}; } - template - static auto ok(U const &value) -> BasicResult { return {ResultBase::Ok, value}; } - - static auto logicError(std::string const &message) -> BasicResult { return {ResultBase::LogicError, message}; } - - static auto runtimeError(std::string const &message) -> BasicResult { - return {ResultBase::RuntimeError, message}; - } + static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; } + static auto ok() -> BasicResult { return { ResultBase::Ok }; } + static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; } + static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; } explicit operator bool() const { return m_type == ResultBase::Ok; } - auto type() const -> ResultBase::Type { return m_type; } - auto errorMessage() const -> std::string { return m_errorMessage; } protected: virtual void enforceOk() const { // !TBD: If no exceptions, std::terminate here or something - switch (m_type) { + switch( m_type ) { case ResultBase::LogicError: - throw std::logic_error(m_errorMessage); + throw std::logic_error( m_errorMessage ); case ResultBase::RuntimeError: - throw std::runtime_error(m_errorMessage); + throw std::runtime_error( m_errorMessage ); case ResultBase::Ok: break; } @@ -4772,10 +4906,11 @@ namespace detail { std::string m_errorMessage; // Only populated if resultType is an error - BasicResult(ResultBase::Type type, std::string const &message) - : ResultValueBase(type), - m_errorMessage(message) { - assert(m_type != ResultBase::Ok); + BasicResult( ResultBase::Type type, std::string const &message ) + : ResultValueBase(type), + m_errorMessage(message) + { + assert( m_type != ResultBase::Ok ); } using ResultValueBase::ResultValueBase; @@ -4789,12 +4924,12 @@ namespace detail { class ParseState { public: - ParseState(ParseResultType type, TokenStream const &remainingTokens) - : m_type(type), - m_remainingTokens(remainingTokens) {} + ParseState( ParseResultType type, TokenStream const &remainingTokens ) + : m_type(type), + m_remainingTokens( remainingTokens ) + {} auto type() const -> ParseResultType { return m_type; } - auto remainingTokens() const -> TokenStream { return m_remainingTokens; } private: @@ -4812,69 +4947,62 @@ namespace detail { }; template - inline auto convertInto(std::string const &source, T& target) -> ParserResult { + inline auto convertInto( std::string const &source, T& target ) -> ParserResult { std::stringstream ss; ss << source; ss >> target; - if (ss.fail()) - return ParserResult::runtimeError("Unable to convert '" + source + "' to destination type"); + if( ss.fail() ) + return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" ); else - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::ok( ParseResultType::Matched ); } - inline auto convertInto(std::string const &source, std::string& target) -> ParserResult { + inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult { target = source; - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::ok( ParseResultType::Matched ); } - 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::transform(srcLC.begin(), srcLC.end(), srcLC.begin(), [](char c) { return static_cast( ::tolower(c) ); } ); + std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast( ::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") target = false; else - return ParserResult::runtimeError("Expected a boolean value but did not recognise: '" + source + "'"); - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); + return ParserResult::ok( ParseResultType::Matched ); } struct BoundRefBase { BoundRefBase() = default; - - BoundRefBase(BoundRefBase const &) = delete; - - BoundRefBase(BoundRefBase &&) = delete; - - BoundRefBase &operator=(BoundRefBase const &) = delete; - - BoundRefBase &operator=(BoundRefBase &&) = delete; + BoundRefBase( BoundRefBase const & ) = delete; + BoundRefBase( BoundRefBase && ) = delete; + BoundRefBase &operator=( BoundRefBase const & ) = delete; + BoundRefBase &operator=( BoundRefBase && ) = delete; virtual ~BoundRefBase() = default; virtual auto isFlag() const -> bool = 0; - virtual auto isContainer() const -> bool { return false; } - - virtual auto setValue(std::string const &arg) -> ParserResult = 0; - - virtual auto setFlag(bool flag) -> ParserResult = 0; + virtual auto setValue( std::string const &arg ) -> ParserResult = 0; + virtual auto setFlag( bool flag ) -> ParserResult = 0; }; struct BoundValueRefBase : BoundRefBase { auto isFlag() const -> bool override { return false; } - auto setFlag(bool) -> ParserResult override { - return ParserResult::logicError("Flags can only be set on boolean fields"); + auto setFlag( bool ) -> ParserResult override { + return ParserResult::logicError( "Flags can only be set on boolean fields" ); } }; struct BoundFlagRefBase : BoundRefBase { auto isFlag() const -> bool override { return true; } - auto setValue(std::string const &arg) -> ParserResult override { + auto setValue( std::string const &arg ) -> ParserResult override { bool flag; - auto result = convertInto(arg, flag); - if (result) - setFlag(flag); + auto result = convertInto( arg, flag ); + if( result ) + setFlag( flag ); return result; } }; @@ -4883,10 +5011,10 @@ namespace detail { struct BoundRef : BoundValueRefBase { T &m_ref; - explicit BoundRef(T &ref) : m_ref(ref) {} + explicit BoundRef( T &ref ) : m_ref( ref ) {} - auto setValue(std::string const &arg) -> ParserResult override { - return convertInto(arg, m_ref); + auto setValue( std::string const &arg ) -> ParserResult override { + return convertInto( arg, m_ref ); } }; @@ -4894,15 +5022,15 @@ namespace detail { struct BoundRef> : BoundValueRefBase { std::vector &m_ref; - explicit BoundRef(std::vector &ref) : m_ref(ref) {} + explicit BoundRef( std::vector &ref ) : m_ref( ref ) {} auto isContainer() const -> bool override { return true; } - auto setValue(std::string const &arg) -> ParserResult override { + auto setValue( std::string const &arg ) -> ParserResult override { T temp; - auto result = convertInto(arg, temp); - if (result) - m_ref.push_back(temp); + auto result = convertInto( arg, temp ); + if( result ) + m_ref.push_back( temp ); return result; } }; @@ -4910,40 +5038,40 @@ namespace detail { struct BoundFlagRef : BoundFlagRefBase { bool &m_ref; - explicit BoundFlagRef(bool &ref) : m_ref(ref) {} + explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {} - auto setFlag(bool flag) -> ParserResult override { + auto setFlag( bool flag ) -> ParserResult override { m_ref = flag; - return ParserResult::ok(ParseResultType::Matched); + return ParserResult::ok( ParseResultType::Matched ); } }; template struct LambdaInvoker { - static_assert(std::is_same::value, "Lambda must return void or clara::ParserResult"); + static_assert( std::is_same::value, "Lambda must return void or clara::ParserResult" ); template - static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { - return lambda(arg); + static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { + return lambda( arg ); } }; template<> struct LambdaInvoker { template - static auto invoke(L const &lambda, ArgType const &arg) -> ParserResult { - lambda(arg); - return ParserResult::ok(ParseResultType::Matched); + static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { + lambda( arg ); + return ParserResult::ok( ParseResultType::Matched ); } }; template - inline auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult { + inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { ArgType temp; - auto result = convertInto(arg, temp); + auto result = convertInto( arg, temp ); return !result - ? result - : LambdaInvoker::ReturnType>::invoke(lambda, temp); + ? result + : LambdaInvoker::ReturnType>::invoke( lambda, temp ); }; template @@ -4951,10 +5079,10 @@ namespace detail { L m_lambda; static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); - explicit BoundLambda(L const &lambda) : m_lambda(lambda) {} + explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {} - auto setValue(std::string const &arg) -> ParserResult override { - return invokeLambda::ArgType>(m_lambda, arg); + auto setValue( std::string const &arg ) -> ParserResult override { + return invokeLambda::ArgType>( m_lambda, arg ); } }; @@ -4965,16 +5093,14 @@ namespace detail { static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); static_assert( std::is_same::ArgType, bool>::value, "flags must be boolean" ); - explicit BoundFlagLambda(L const &lambda) : m_lambda(lambda) {} + explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {} - auto setFlag(bool flag) -> ParserResult override { - return LambdaInvoker::ReturnType>::invoke(m_lambda, flag); + auto setFlag( bool flag ) -> ParserResult override { + return LambdaInvoker::ReturnType>::invoke( m_lambda, flag ); } }; - enum class Optionality { - Optional, Required - }; + enum class Optionality { Optional, Required }; struct Parser; @@ -4985,8 +5111,8 @@ namespace detail { virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; virtual auto cardinality() const -> size_t { return 1; } - auto parse(Args const &args) const -> InternalParseResult { - return parse( args.exeName(), TokenStream(args)); + auto parse( Args const &args ) const -> InternalParseResult { + return parse( args.exeName(), TokenStream( args ) ); } }; @@ -4994,7 +5120,7 @@ namespace detail { class ComposableParserImpl : public ParserBase { public: template - auto operator+(T const &other) const -> Parser; + auto operator|( T const &other ) const -> Parser; }; // Common code and state for Args and Opts @@ -5006,17 +5132,22 @@ namespace detail { std::string m_hint; std::string m_description; - explicit ParserRefImpl(std::shared_ptr const &ref) : m_ref(ref) {} + explicit ParserRefImpl( std::shared_ptr const &ref ) : m_ref( ref ) {} public: template - ParserRefImpl(T &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), m_hint(hint) {} + ParserRefImpl( T &ref, std::string const &hint ) + : m_ref( std::make_shared>( ref ) ), + m_hint( hint ) + {} template - ParserRefImpl(LambdaT const &ref, std::string const &hint) : m_ref(std::make_shared>(ref)), - m_hint(hint) {} + ParserRefImpl( LambdaT const &ref, std::string const &hint ) + : m_ref( std::make_shared>( ref ) ), + m_hint(hint) + {} - auto operator()(std::string const &description) -> DerivedT & { + auto operator()( std::string const &description ) -> DerivedT & { m_description = description; return static_cast( *this ); } @@ -5036,7 +5167,7 @@ namespace detail { } auto cardinality() const -> size_t override { - if (m_ref->isContainer()) + if( m_ref->isContainer() ) return 0; else return 1; @@ -5051,13 +5182,13 @@ namespace detail { template static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { - return std::make_shared>(lambda); + return std::make_shared>( lambda) ; } public: - ExeName() : m_name(std::make_shared("")) {} + ExeName() : m_name( std::make_shared( "" ) ) {} - explicit ExeName(std::string &ref) : ExeName() { + explicit ExeName( std::string &ref ) : ExeName() { m_ref = std::make_shared>( ref ); } @@ -5068,14 +5199,14 @@ namespace detail { // The exe name is not parsed out of the normal tokens, but is handled specially auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { - return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); } auto name() const -> std::string { return *m_name; } auto set( std::string const& newName ) -> ParserResult { auto lastSlash = newName.find_last_of( "\\/" ); - auto filename = (lastSlash == std::string::npos) + auto filename = ( lastSlash == std::string::npos ) ? newName : newName.substr( lastSlash+1 ); @@ -5091,27 +5222,27 @@ namespace detail { public: using ParserRefImpl::ParserRefImpl; - auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override { + auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override { auto validationResult = validate(); - if (!validationResult) - return InternalParseResult(validationResult); + if( !validationResult ) + return InternalParseResult( validationResult ); auto remainingTokens = tokens; auto const &token = *remainingTokens; - if (token.type != TokenType::Argument) - return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + if( token.type != TokenType::Argument ) + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); - auto result = m_ref->setValue(remainingTokens->token); - if (!result) - return InternalParseResult(result); + auto result = m_ref->setValue( remainingTokens->token ); + if( !result ) + return InternalParseResult( result ); else - return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); } }; - inline auto normaliseOpt(std::string const &optName) -> std::string { - if (optName[0] == '/') - return "-" + optName.substr(1); + inline auto normaliseOpt( std::string const &optName ) -> std::string { + if( optName[0] == '/' ) + return "-" + optName.substr( 1 ); else return optName; } @@ -5122,9 +5253,9 @@ namespace detail { public: template - explicit Opt( LambdaT const &ref ) : ParserRefImpl(std::make_shared>(ref)) {} + explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared>( ref ) ) {} - explicit Opt( bool &ref ) : ParserRefImpl(std::make_shared(ref)) {} + explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared( ref ) ) {} template Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} @@ -5132,34 +5263,34 @@ namespace detail { template Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} - auto operator[](std::string const &optName) -> Opt & { - m_optNames.push_back(optName); + auto operator[]( std::string const &optName ) -> Opt & { + m_optNames.push_back( optName ); return *this; } auto getHelpColumns() const -> std::vector { std::ostringstream oss; bool first = true; - for (auto const &opt : m_optNames) { + for( auto const &opt : m_optNames ) { if (first) first = false; else oss << ", "; oss << opt; } - if (!m_hint.empty()) + if( !m_hint.empty() ) oss << " <" << m_hint << ">"; - return {{oss.str(), m_description}}; + return { { oss.str(), m_description } }; } - auto isMatch(std::string const &optToken) const -> bool { -#ifdef CLARA_PLATFORM_WINDOWS + auto isMatch( std::string const &optToken ) const -> bool { +#ifdef CATCH_PLATFORM_WINDOWS auto normalisedToken = normaliseOpt( optToken ); #else auto const &normalisedToken = optToken; #endif - for (auto const &name : m_optNames) { - if (normaliseOpt(name) == normalisedToken) + for( auto const &name : m_optNames ) { + if( normaliseOpt( name ) == normalisedToken ) return true; } return false; @@ -5169,46 +5300,46 @@ namespace detail { auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { auto validationResult = validate(); - if (!validationResult) - return InternalParseResult(validationResult); + if( !validationResult ) + return InternalParseResult( validationResult ); auto remainingTokens = tokens; - if (remainingTokens && remainingTokens->type == TokenType::Option) { + if( remainingTokens && remainingTokens->type == TokenType::Option ) { auto const &token = *remainingTokens; - if (isMatch(token.token)) { - if (m_ref->isFlag()) { - auto result = m_ref->setFlag(true); - if (!result) - return InternalParseResult(result); - if (result.value() == ParseResultType::ShortCircuitAll) - return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + if( isMatch(token.token ) ) { + if( m_ref->isFlag() ) { + auto result = m_ref->setFlag( true ); + if( !result ) + return InternalParseResult( result ); + if( result.value() == ParseResultType::ShortCircuitAll ) + return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); } else { ++remainingTokens; - if (!remainingTokens) - return InternalParseResult::runtimeError("Expected argument following " + token.token); + if( !remainingTokens ) + return InternalParseResult::runtimeError( "Expected argument following " + token.token ); auto const &argToken = *remainingTokens; - if (argToken.type != TokenType::Argument) - return InternalParseResult::runtimeError("Expected argument following " + token.token); - auto result = m_ref->setValue(argToken.token); - if (!result) - return InternalParseResult(result); - if (result.value() == ParseResultType::ShortCircuitAll) - return InternalParseResult::ok(ParseState(result.value(), remainingTokens)); + if( argToken.type != TokenType::Argument ) + return InternalParseResult::runtimeError( "Expected argument following " + token.token ); + auto result = m_ref->setValue( argToken.token ); + if( !result ) + return InternalParseResult( result ); + if( result.value() == ParseResultType::ShortCircuitAll ) + return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); } - return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens)); + return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); } } - return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens)); + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); } auto validate() const -> Result override { - if (m_optNames.empty()) - return Result::logicError("No options supplied to Opt"); - for (auto const &name : m_optNames) { - if (name.empty()) - return Result::logicError("Option name cannot be empty"); - if (name[0] != '-' && name[0] != '/') - return Result::logicError("Option name must begin with '-' or '/'"); + if( m_optNames.empty() ) + return Result::logicError( "No options supplied to Opt" ); + for( auto const &name : m_optNames ) { + if( name.empty() ) + return Result::logicError( "Option name cannot be empty" ); + if( name[0] != '-' && name[0] != '/' ) + return Result::logicError( "Option name must begin with '-' or '/'" ); } return ParserRefImpl::validate(); } @@ -5217,11 +5348,11 @@ namespace detail { struct Help : Opt { Help( bool &showHelpFlag ) : Opt([&]( bool flag ) { - showHelpFlag = flag; - return ParserResult::ok(ParseResultType::ShortCircuitAll); + showHelpFlag = flag; + return ParserResult::ok( ParseResultType::ShortCircuitAll ); }) { - static_cast(*this) + static_cast( *this ) ("display usage information") ["-?"]["-h"]["--help"] .optional(); @@ -5234,61 +5365,61 @@ namespace detail { std::vector m_options; std::vector m_args; - auto operator+=(ExeName const &exeName) -> Parser & { + auto operator|=( ExeName const &exeName ) -> Parser & { m_exeName = exeName; return *this; } - auto operator+=(Arg const &arg) -> Parser & { + auto operator|=( Arg const &arg ) -> Parser & { m_args.push_back(arg); return *this; } - auto operator+=(Opt const &opt) -> Parser & { + auto operator|=( Opt const &opt ) -> Parser & { m_options.push_back(opt); return *this; } - auto operator+=(Parser const &other) -> Parser & { + auto operator|=( Parser const &other ) -> Parser & { m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); return *this; } template - auto operator+(T const &other) const -> Parser { - return Parser(*this) += other; + auto operator|( T const &other ) const -> Parser { + return Parser( *this ) |= other; } auto getHelpColumns() const -> std::vector { std::vector cols; for (auto const &o : m_options) { auto childCols = o.getHelpColumns(); - cols.insert(cols.end(), childCols.begin(), childCols.end()); + cols.insert( cols.end(), childCols.begin(), childCols.end() ); } return cols; } - void writeToStream(std::ostream &os) const { + void writeToStream( std::ostream &os ) const { if (!m_exeName.name().empty()) { os << "usage:\n" << " " << m_exeName.name() << " "; bool required = true, first = true; - for (auto const &arg : m_args) { + for( auto const &arg : m_args ) { if (first) first = false; else os << " "; - if (arg.isOptional() && required) { + if( arg.isOptional() && required ) { os << "["; required = false; } os << "<" << arg.hint() << ">"; - if (arg.cardinality() == 0) + if( arg.cardinality() == 0 ) os << " ... "; } - if (!required) + if( !required ) os << "]"; - if (!m_options.empty()) + if( !m_options.empty() ) os << " options"; os << "\n\nwhere options are:" << std::endl; } @@ -5296,32 +5427,32 @@ namespace detail { auto rows = getHelpColumns(); size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; size_t optWidth = 0; - for (auto const &cols : rows) + for( auto const &cols : rows ) optWidth = std::max(optWidth, cols.left.size() + 2); - for (auto const &cols : rows) { + for( auto const &cols : rows ) { auto row = - TextFlow::Column(cols.left).width(optWidth).indent(2) + + TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + TextFlow::Spacer(4) + - TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth); + TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth ); os << row << std::endl; } } - friend auto operator<<(std::ostream &os, Parser const &parser) -> std::ostream & { - parser.writeToStream(os); + friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& { + parser.writeToStream( os ); return os; } auto validate() const -> Result override { - for (auto const &opt : m_options) { + for( auto const &opt : m_options ) { auto result = opt.validate(); - if (!result) + if( !result ) return result; } - for (auto const &arg : m_args) { + for( auto const &arg : m_args ) { auto result = arg.validate(); - if (!result) + if( !result ) return result; } return Result::ok(); @@ -5329,47 +5460,47 @@ namespace detail { using ParserBase::parse; - auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult override { - std::vector allParsers; - allParsers.reserve(m_args.size() + m_options.size()); - std::set requiredParsers; + auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { - for (auto const &opt : m_options) { - allParsers.push_back(&opt); - if (!opt.isOptional()) - requiredParsers.insert(&opt); - } + struct ParserInfo { + ParserBase const* parser = nullptr; + size_t count = 0; + }; + const size_t totalParsers = m_options.size() + m_args.size(); + assert( totalParsers < 512 ); + // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do + ParserInfo parseInfos[512]; - size_t optionalArgs = 0; - for (auto const &arg : m_args) { - allParsers.push_back(&arg); - if (!arg.isOptional()) { - if (optionalArgs > 0) - return InternalParseResult::logicError( - "Required arguments must preceed any optional arguments"); - else - ++optionalArgs; - requiredParsers.insert(&arg); - } + { + size_t i = 0; + for (auto const &opt : m_options) parseInfos[i++].parser = &opt; + for (auto const &arg : m_args) parseInfos[i++].parser = &arg; } m_exeName.set( exeName ); - auto result = InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens)); - while (result.value().remainingTokens()) { - auto remainingTokenCount = result.value().remainingTokens().count(); - for (auto parser : allParsers) { - result = parser->parse( exeName, result.value().remainingTokens() ); - if (!result || result.value().type() != ParseResultType::NoMatch) { - if (parser->cardinality() == 1) - allParsers.erase(std::remove(allParsers.begin(), allParsers.end(), parser), - allParsers.end()); - requiredParsers.erase(parser); - break; + auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); + while( result.value().remainingTokens() ) { + bool tokenParsed = false; + + for( size_t i = 0; i < totalParsers; ++i ) { + auto& parseInfo = parseInfos[i]; + if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { + result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); + if (!result) + return result; + if (result.value().type() != ParseResultType::NoMatch) { + tokenParsed = true; + ++parseInfo.count; + break; + } } } - if (!result || remainingTokenCount == result.value().remainingTokens().count()) + + if( result.value().type() == ParseResultType::ShortCircuitAll ) return result; + if( !tokenParsed ) + return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); } // !TBD Check missing required options return result; @@ -5378,8 +5509,8 @@ namespace detail { template template - auto ComposableParserImpl::operator+(T const &other) const -> Parser { - return Parser() + static_cast( *this ) + other; + auto ComposableParserImpl::operator|( T const &other ) const -> Parser { + return Parser() | static_cast( *this ) | other; } } // namespace detail @@ -5516,84 +5647,84 @@ namespace Catch { auto cli = ExeName( config.processName ) - + Help( config.showHelp ) - + Opt( config.listTests ) + | Help( config.showHelp ) + | Opt( config.listTests ) ["-l"]["--list-tests"] ( "list all/matching test cases" ) - + Opt( config.listTags ) + | Opt( config.listTags ) ["-t"]["--list-tags"] ( "list all/matching tags" ) - + Opt( config.showSuccessfulTests ) + | Opt( config.showSuccessfulTests ) ["-s"]["--success"] ( "include successful tests in output" ) - + Opt( config.shouldDebugBreak ) + | Opt( config.shouldDebugBreak ) ["-b"]["--break"] ( "break into debugger on failure" ) - + Opt( config.noThrow ) + | Opt( config.noThrow ) ["-e"]["--nothrow"] ( "skip exception tests" ) - + Opt( config.showInvisibles ) + | Opt( config.showInvisibles ) ["-i"]["--invisibles"] ( "show invisibles (tabs, newlines)" ) - + Opt( config.outputFilename, "filename" ) + | Opt( config.outputFilename, "filename" ) ["-o"]["--out"] ( "output filename" ) - + Opt( config.reporterNames, "name" ) + | Opt( config.reporterNames, "name" ) ["-r"]["--reporter"] ( "reporter to use (defaults to console)" ) - + Opt( config.name, "name" ) + | Opt( config.name, "name" ) ["-n"]["--name"] ( "suite name" ) - + Opt( [&]( bool ){ config.abortAfter = 1; } ) + | Opt( [&]( bool ){ config.abortAfter = 1; } ) ["-a"]["--abort"] ( "abort at first failure" ) - + Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) + | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) ["-x"]["--abortx"] ( "abort after x failures" ) - + Opt( setWarning, "warning name" ) + | Opt( setWarning, "warning name" ) ["-w"]["--warn"] ( "enable warnings" ) - + Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) + | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) ["-d"]["--durations"] ( "show test durations" ) - + Opt( loadTestNamesFromFile, "filename" ) + | Opt( loadTestNamesFromFile, "filename" ) ["-f"]["--input-file"] ( "load test names to run from a file" ) - + Opt( config.filenamesAsTags ) + | Opt( config.filenamesAsTags ) ["-#"]["--filenames-as-tags"] ( "adds a tag for the filename" ) - + Opt( config.sectionsToRun, "section name" ) + | Opt( config.sectionsToRun, "section name" ) ["-c"]["--section"] ( "specify section to run" ) - + Opt( setVerbosity, "quiet|normal|high" ) + | Opt( setVerbosity, "quiet|normal|high" ) ["-v"]["--verbosity"] ( "set output verbosity" ) - + Opt( config.listTestNamesOnly ) + | Opt( config.listTestNamesOnly ) ["--list-test-names-only"] ( "list all/matching test cases names only" ) - + Opt( config.listReporters ) + | Opt( config.listReporters ) ["--list-reporters"] ( "list all reporters" ) - + Opt( setTestOrder, "decl|lex|rand" ) + | Opt( setTestOrder, "decl|lex|rand" ) ["--order"] ( "test case order (defaults to decl)" ) - + Opt( setRngSeed, "'time'|number" ) + | Opt( setRngSeed, "'time'|number" ) ["--rng-seed"] ( "set a specific seed for random numbers" ) - + Opt( setColourUsage, "yes|no" ) + | Opt( setColourUsage, "yes|no" ) ["--use-colour"] ( "should output be colourised" ) - + Opt( config.libIdentify ) + | Opt( config.libIdentify ) ["--libidentify"] ( "report name and version according to libidentify standard" ) - + Opt( setWaitForKeypress, "start|exit|both" ) + | Opt( setWaitForKeypress, "start|exit|both" ) ["--wait-for-keypress"] ( "waits for a keypress before exiting" ) - + Opt( config.benchmarkResolutionMultiple, "multiplier" ) + | Opt( config.benchmarkResolutionMultiple, "multiplier" ) ["--benchmark-resolution-multiple"] ( "multiple of clock resolution to run benchmarks" ) - + Arg( config.testsOrTags, "test name|pattern|tags" ) + | Arg( config.testsOrTags, "test name|pattern|tags" ) ( "which test or tests to use" ); return cli; @@ -5731,6 +5862,36 @@ namespace Catch { } // end catch_errno_guard.h +// start catch_windows_h_proxy.h + + +#if defined(CATCH_PLATFORM_WINDOWS) + +#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) +# define CATCH_DEFINED_NOMINMAX +# define NOMINMAX +#endif +#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) +# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +#ifdef CATCH_DEFINED_NOMINMAX +# undef NOMINMAX +#endif +#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +#endif + +#endif // defined(CATCH_PLATFORM_WINDOWS) + +// end catch_windows_h_proxy.h namespace Catch { namespace { @@ -5761,34 +5922,6 @@ namespace Catch { #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// -// start catch_windows_h_proxy.h - - -#if defined(CATCH_PLATFORM_WINDOWS) -# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) -# define CATCH_DEFINED_NOMINMAX -# define NOMINMAX -# endif -# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) -# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# define WIN32_LEAN_AND_MEAN -# endif -#endif - -#ifdef __AFXDLL -#include -#else -#include -#endif - -#ifdef CATCH_DEFINED_NOMINMAX -# undef NOMINMAX -#endif -#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN -# undef WIN32_LEAN_AND_MEAN -#endif - -// end catch_windows_h_proxy.h namespace Catch { namespace { @@ -6220,7 +6353,7 @@ namespace Catch { #endif } catch( TestFailureException& ) { - throw; + std::rethrow_exception(std::current_exception()); } catch( std::exception& ex ) { return ex.what(); @@ -6238,7 +6371,7 @@ namespace Catch { std::string ExceptionTranslatorRegistry::tryTranslators() const { if( m_translators.empty() ) - throw; + std::rethrow_exception(std::current_exception()); else return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); } @@ -6523,6 +6656,9 @@ namespace Catch { static std::set getSupportedVerbosities(); + void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; + void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override; + void testRunStarting( TestRunInfo const& testRunInfo ) override; void testGroupStarting( GroupInfo const& groupInfo ) override; void testCaseStarting( TestCaseInfo const& testInfo ) override; @@ -9649,7 +9785,7 @@ namespace Catch { } Version const& libraryVersion() { - static Version version( 2, 0, 0, "develop", 4 ); + static Version version( 2, 0, 0, "develop", 5 ); return version; } @@ -11204,6 +11340,15 @@ namespace Catch { reporter->noMatchingTestCases( spec ); } + void MultipleReporters::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { + for( auto const& reporter : m_reporters ) + reporter->benchmarkStarting( benchmarkInfo ); + } + void MultipleReporters::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { + for( auto const& reporter : m_reporters ) + reporter->benchmarkEnded( benchmarkStats ); + } + void MultipleReporters::testRunStarting( TestRunInfo const& testRunInfo ) { for( auto const& reporter : m_reporters ) reporter->testRunStarting( testRunInfo ); diff --git a/test_package/conanfile.py b/test_package/conanfile.py index 2311ab7f..96d93985 100644 --- a/test_package/conanfile.py +++ b/test_package/conanfile.py @@ -10,7 +10,7 @@ class CatchConanTest(ConanFile): settings = "os", "compiler", "arch", "build_type" username = getenv("CONAN_USERNAME", "philsquared") channel = getenv("CONAN_CHANNEL", "testing") - requires = "Catch/2.0.0-develop.4@%s/%s" % (username, channel) + requires = "Catch/2.0.0-develop.5@%s/%s" % (username, channel) def build(self): cmake = CMake(self)