diff --git a/test/src/catch.hpp b/test/src/catch.hpp index 5cc33a838..879fc5b1d 100644 --- a/test/src/catch.hpp +++ b/test/src/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.3.4 - * Generated: 2016-02-10 19:24:03.089683 + * Catch v1.5.6 + * Generated: 2016-06-09 19:20:41.460328 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -62,7 +62,11 @@ #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) -#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) @@ -89,7 +93,7 @@ // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? - +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? // **************** // Note to maintainers: if new toggles are added please document them // in configuration.md, too @@ -102,6 +106,18 @@ // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 +#ifdef __cplusplus + +# if __cplusplus >= 201103L +# define CATCH_CPP11_OR_GREATER +# endif + +# if __cplusplus >= 201402L +# define CATCH_CPP14_OR_GREATER +# endif + +#endif + #ifdef __clang__ # if __has_feature(cxx_nullptr) @@ -112,6 +128,10 @@ # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT # endif +# if defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# endif + #endif // __clang__ //////////////////////////////////////////////////////////////////////////////// @@ -136,9 +156,13 @@ // GCC #ifdef __GNUC__ -#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) -# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR -#endif +# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# endif + +# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) +# endif // - otherwise more recent versions define __cplusplus >= 201103L // and will get picked up below @@ -173,13 +197,20 @@ #endif +// Use __COUNTER__ if the compiler supports it +#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ + ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \ + ( defined __clang__ && __clang_major__ >= 3 ) + +#define CATCH_INTERNAL_CONFIG_COUNTER + +#endif + //////////////////////////////////////////////////////////////////////////////// // C++ language feature support // catch all support for C++11 -#if defined(__cplusplus) && __cplusplus >= 201103L - -# define CATCH_CPP11_OR_GREATER +#if defined(CATCH_CPP11_OR_GREATER) # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR @@ -246,6 +277,13 @@ #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_UNIQUE_PTR #endif +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +#endif // noexcept support: #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) @@ -672,24 +710,28 @@ void registerTestCaseFunction #ifdef CATCH_CONFIG_VARIADIC_MACROS /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ + static void TestName() #define INTERNAL_CATCH_TESTCASE( ... ) \ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ namespace{ \ - struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + struct TestName : ClassName{ \ void test(); \ }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ } \ - void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + void TestName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ @@ -697,24 +739,28 @@ void registerTestCaseFunction #else /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ + static void TestName(); \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ + static void TestName() #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ - namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ - static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } /////////////////////////////////////////////////////////////////////////////// - #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ namespace{ \ - struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ + struct TestCaseName : ClassName{ \ void test(); \ }; \ - Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ } \ - void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + void TestCaseName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ @@ -1287,37 +1333,37 @@ namespace Internal { template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs) { - return opCast( lhs ) == opCast( rhs ); + return bool( opCast( lhs ) == opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) != opCast( rhs ); + return bool( opCast( lhs ) != opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) < opCast( rhs ); + return bool( opCast( lhs ) < opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) > opCast( rhs ); + return bool( opCast( lhs ) > opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) >= opCast( rhs ); + return bool( opCast( lhs ) >= opCast( rhs ) ); } }; template struct Evaluator { static bool evaluate( T1 const& lhs, T2 const& rhs ) { - return opCast( lhs ) <= opCast( rhs ); + return bool( opCast( lhs ) <= opCast( rhs ) ); } }; @@ -2020,13 +2066,14 @@ namespace Catch { do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ try { \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ ( __catchResult <= expr ).endExpression(); \ } \ catch( ... ) { \ __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \ } \ INTERNAL_CATCH_REACT( __catchResult ) \ - } while( Catch::isTrue( false && static_cast(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look + } while( Catch::isTrue( false && !!(expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ @@ -2563,10 +2610,12 @@ namespace Catch { } /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ - static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ - namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ - static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ + static std::string translatorName( signature ); \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ + static std::string translatorName( signature ) + +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) // #included from: internal/catch_approx.hpp #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED @@ -3331,6 +3380,11 @@ namespace Catch { InLexicographicalOrder, InRandomOrder }; }; + struct UseColour { enum YesOrNo { + Auto, + Yes, + No + }; }; class TestSpec; @@ -3350,7 +3404,7 @@ namespace Catch { virtual TestSpec const& testSpec() const = 0; virtual RunTests::InWhatOrder runOrder() const = 0; virtual unsigned int rngSeed() const = 0; - virtual bool forceColour() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; }; } @@ -3404,7 +3458,7 @@ namespace Catch { }; class DebugOutStream : public IStream { - std::auto_ptr m_streamBuf; + CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; mutable std::ostream m_os; public: DebugOutStream(); @@ -3439,14 +3493,14 @@ namespace Catch { noThrow( false ), showHelp( false ), showInvisibles( false ), - forceColour( false ), filenamesAsTags( false ), abortAfter( -1 ), rngSeed( 0 ), verbosity( Verbosity::Normal ), warnings( WarnAbout::Nothing ), showDurations( ShowDurations::DefaultForReporter ), - runOrder( RunTests::InDeclarationOrder ) + runOrder( RunTests::InDeclarationOrder ), + useColour( UseColour::Auto ) {} bool listTests; @@ -3459,7 +3513,6 @@ namespace Catch { bool noThrow; bool showHelp; bool showInvisibles; - bool forceColour; bool filenamesAsTags; int abortAfter; @@ -3469,6 +3522,7 @@ namespace Catch { WarnAbout::What warnings; ShowDurations::OrNot showDurations; RunTests::InWhatOrder runOrder; + UseColour::YesOrNo useColour; std::string outputFilename; std::string name; @@ -3534,7 +3588,7 @@ namespace Catch { virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; } virtual unsigned int rngSeed() const { return m_data.rngSeed; } - virtual bool forceColour() const { return m_data.forceColour; } + virtual UseColour::YesOrNo useColour() const { return m_data.useColour; } private: @@ -3552,7 +3606,7 @@ namespace Catch { } ConfigData m_data; - std::auto_ptr m_stream; + CATCH_AUTO_PTR( IStream const ) m_stream; TestSpec m_testSpec; }; @@ -3572,7 +3626,7 @@ namespace Catch { #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { // #included from: ../external/clara.h -// Version 0.0.1.1 +// Version 0.0.2.4 // Only use header guard if we are not using an outer namespace #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) @@ -3888,6 +3942,10 @@ namespace Tbc { #include #include +#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define CLARA_PLATFORM_WINDOWS +#endif + // Use optional outer namespace #ifdef STITCH_CLARA_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE @@ -3911,9 +3969,6 @@ namespace Clara { const unsigned int consoleWidth = 80; #endif - // Use this to try and stop compiler from warning about unreachable code - inline bool isTrue( bool value ) { return value; } - using namespace Tbc; inline bool startsWith( std::string const& str, std::string const& prefix ) { @@ -3949,14 +4004,6 @@ namespace Clara { else throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); } - inline void convertInto( bool _source, bool& _dest ) { - _dest = _source; - } - template - inline void convertInto( bool, T& ) { - if( isTrue( true ) ) - throw std::runtime_error( "Invalid conversion" ); - } template struct IArgFunction { @@ -3966,7 +4013,6 @@ namespace Clara { IArgFunction( IArgFunction const& ) = default; #endif virtual void set( ConfigT& config, std::string const& value ) const = 0; - virtual void setFlag( ConfigT& config ) const = 0; virtual bool takesArg() const = 0; virtual IArgFunction* clone() const = 0; }; @@ -3988,9 +4034,6 @@ namespace Clara { void set( ConfigT& config, std::string const& value ) const { functionObj->set( config, value ); } - void setFlag( ConfigT& config ) const { - functionObj->setFlag( config ); - } bool takesArg() const { return functionObj->takesArg(); } bool isSet() const { @@ -4003,7 +4046,6 @@ namespace Clara { template struct NullBinder : IArgFunction{ virtual void set( C&, std::string const& ) const {} - virtual void setFlag( C& ) const {} virtual bool takesArg() const { return true; } virtual IArgFunction* clone() const { return new NullBinder( *this ); } }; @@ -4014,9 +4056,6 @@ namespace Clara { virtual void set( C& p, std::string const& stringValue ) const { convertInto( stringValue, p.*member ); } - virtual void setFlag( C& p ) const { - convertInto( true, p.*member ); - } virtual bool takesArg() const { return !IsBool::value; } virtual IArgFunction* clone() const { return new BoundDataMember( *this ); } M C::* member; @@ -4029,11 +4068,6 @@ namespace Clara { convertInto( stringValue, value ); (p.*member)( value ); } - virtual void setFlag( C& p ) const { - typename RemoveConstRef::type value; - convertInto( true, value ); - (p.*member)( value ); - } virtual bool takesArg() const { return !IsBool::value; } virtual IArgFunction* clone() const { return new BoundUnaryMethod( *this ); } void (C::*member)( M ); @@ -4047,9 +4081,6 @@ namespace Clara { if( value ) (p.*member)(); } - virtual void setFlag( C& p ) const { - (p.*member)(); - } virtual bool takesArg() const { return false; } virtual IArgFunction* clone() const { return new BoundNullaryMethod( *this ); } void (C::*member)(); @@ -4064,9 +4095,6 @@ namespace Clara { if( value ) function( obj ); } - virtual void setFlag( C& p ) const { - function( p ); - } virtual bool takesArg() const { return false; } virtual IArgFunction* clone() const { return new BoundUnaryFunction( *this ); } void (*function)( C& ); @@ -4080,11 +4108,6 @@ namespace Clara { convertInto( stringValue, value ); function( obj, value ); } - virtual void setFlag( C& obj ) const { - typename RemoveConstRef::type value; - convertInto( true, value ); - function( obj, value ); - } virtual bool takesArg() const { return !IsBool::value; } virtual IArgFunction* clone() const { return new BoundBinaryFunction( *this ); } void (*function)( C&, T ); @@ -4092,8 +4115,20 @@ namespace Clara { } // namespace Detail - struct Parser { - Parser() : separators( " \t=:" ) {} + inline std::vector argsToVector( int argc, char const* const* const argv ) { + std::vector args( static_cast( argc ) ); + for( std::size_t i = 0; i < static_cast( argc ); ++i ) + args[i] = argv[i]; + + return args; + } + + class Parser { + enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; + Mode mode; + std::size_t from; + bool inQuotes; + public: struct Token { enum Type { Positional, ShortOpt, LongOpt }; @@ -4102,38 +4137,75 @@ namespace Clara { std::string data; }; - void parseIntoTokens( int argc, char const* const argv[], std::vector& tokens ) const { + Parser() : mode( None ), from( 0 ), inQuotes( false ){} + + void parseIntoTokens( std::vector const& args, std::vector& tokens ) { const std::string doubleDash = "--"; - for( int i = 1; i < argc && argv[i] != doubleDash; ++i ) - parseIntoTokens( argv[i] , tokens); + for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) + parseIntoTokens( args[i], tokens); } - void parseIntoTokens( std::string arg, std::vector& tokens ) const { - while( !arg.empty() ) { - Parser::Token token( Parser::Token::Positional, arg ); - arg = ""; - if( token.data[0] == '-' ) { - if( token.data.size() > 1 && token.data[1] == '-' ) { - token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) ); - } - else { - token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) ); - if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) { - arg = "-" + token.data.substr( 1 ); - token.data = token.data.substr( 0, 1 ); - } - } - } - if( token.type != Parser::Token::Positional ) { - std::size_t pos = token.data.find_first_of( separators ); - if( pos != std::string::npos ) { - arg = token.data.substr( pos+1 ); - token.data = token.data.substr( 0, pos ); - } - } - tokens.push_back( token ); + + void parseIntoTokens( std::string const& arg, std::vector& tokens ) { + for( std::size_t i = 0; i <= arg.size(); ++i ) { + char c = arg[i]; + if( c == '"' ) + inQuotes = !inQuotes; + mode = handleMode( i, c, arg, tokens ); } } - std::string separators; + Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + switch( mode ) { + case None: return handleNone( i, c ); + case MaybeShortOpt: return handleMaybeShortOpt( i, c ); + case ShortOpt: + case LongOpt: + case SlashOpt: return handleOpt( i, c, arg, tokens ); + case Positional: return handlePositional( i, c, arg, tokens ); + default: throw std::logic_error( "Unknown mode" ); + } + } + + Mode handleNone( std::size_t i, char c ) { + if( inQuotes ) { + from = i; + return Positional; + } + switch( c ) { + case '-': return MaybeShortOpt; +#ifdef CLARA_PLATFORM_WINDOWS + case '/': from = i+1; return SlashOpt; +#endif + default: from = i; return Positional; + } + } + Mode handleMaybeShortOpt( std::size_t i, char c ) { + switch( c ) { + case '-': from = i+1; return LongOpt; + default: from = i; return ShortOpt; + } + } + Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) + return mode; + + std::string optName = arg.substr( from, i-from ); + if( mode == ShortOpt ) + for( std::size_t j = 0; j < optName.size(); ++j ) + tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); + else if( mode == SlashOpt && optName.size() == 1 ) + tokens.push_back( Token( Token::ShortOpt, optName ) ); + else + tokens.push_back( Token( Token::LongOpt, optName ) ); + return None; + } + Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector& tokens ) { + if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos ) + return mode; + + std::string data = arg.substr( from, i-from ); + tokens.push_back( Token( Token::Positional, data ) ); + return None; + } }; template @@ -4436,21 +4508,21 @@ namespace Clara { return oss.str(); } - ConfigT parse( int argc, char const* const argv[] ) const { + ConfigT parse( std::vector const& args ) const { ConfigT config; - parseInto( argc, argv, config ); + parseInto( args, config ); return config; } - std::vector parseInto( int argc, char const* argv[], ConfigT& config ) const { - std::string processName = argv[0]; + std::vector parseInto( std::vector const& args, ConfigT& config ) const { + std::string processName = args[0]; std::size_t lastSlash = processName.find_last_of( "/\\" ); if( lastSlash != std::string::npos ) processName = processName.substr( lastSlash+1 ); m_boundProcessName.set( config, processName ); std::vector tokens; Parser parser; - parser.parseIntoTokens( argc, argv, tokens ); + parser.parseIntoTokens( args, tokens ); return populate( tokens, config ); } @@ -4481,7 +4553,7 @@ namespace Clara { arg.boundField.set( config, tokens[++i].data ); } else { - arg.boundField.setFlag( config ); + arg.boundField.set( config, "true" ); } break; } @@ -4624,6 +4696,21 @@ namespace Catch { ? ShowDurations::Always : ShowDurations::Never; } + inline void setUseColour( ConfigData& config, std::string const& value ) { + std::string mode = toLower( value ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); + } + inline void forceColour( ConfigData& config ) { + config.useColour = UseColour::Yes; + } inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { std::ifstream f( _filename.c_str() ); if( !f.is_open() ) @@ -4710,7 +4797,7 @@ namespace Catch { cli["-d"]["--durations"] .describe( "show test durations" ) - .bind( &setShowDurations, "yes/no" ); + .bind( &setShowDurations, "yes|no" ); cli["-f"]["--input-file"] .describe( "load test names to run from a file" ) @@ -4738,8 +4825,12 @@ namespace Catch { .bind( &setRngSeed, "'time'|number" ); cli["--force-colour"] - .describe( "force colourised output" ) - .bind( &ConfigData::forceColour ); + .describe( "force colourised output (deprecated)" ) + .bind( &forceColour ); + + cli["--use-colour"] + .describe( "should output be colourised" ) + .bind( &setUseColour, "yes|no" ); return cli; } @@ -5170,6 +5261,8 @@ namespace Catch bool aborting; }; + class MultipleReporters; + struct IStreamingReporter : IShared { virtual ~IStreamingReporter(); @@ -5197,6 +5290,8 @@ namespace Catch virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + + virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } }; struct IReporterFactory : IShared { @@ -5414,6 +5509,10 @@ namespace TestCaseTracking { virtual void addChild( Ptr const& child ) = 0; virtual ITracker* findChild( std::string const& name ) = 0; virtual void openChild() = 0; + + // Debug/ checking + virtual bool isSectionTracker() const = 0; + virtual bool isIndexTracker() const = 0; }; class TrackerContext { @@ -5538,6 +5637,10 @@ namespace TestCaseTracking { m_parent->openChild(); } } + + virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } + virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } + void open() { m_runState = Executing; moveToThis(); @@ -5601,13 +5704,16 @@ namespace TestCaseTracking { {} virtual ~SectionTracker(); + virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { SectionTracker* section = CATCH_NULL; ITracker& currentTracker = ctx.currentTracker(); if( ITracker* childTracker = currentTracker.findChild( name ) ) { - section = dynamic_cast( childTracker ); - assert( section ); + assert( childTracker ); + assert( childTracker->isSectionTracker() ); + section = static_cast( childTracker ); } else { section = new SectionTracker( name, ctx, ¤tTracker ); @@ -5632,13 +5738,16 @@ namespace TestCaseTracking { {} virtual ~IndexTracker(); + virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { IndexTracker* tracker = CATCH_NULL; ITracker& currentTracker = ctx.currentTracker(); if( ITracker* childTracker = currentTracker.findChild( name ) ) { - tracker = dynamic_cast( childTracker ); - assert( tracker ); + assert( childTracker ); + assert( childTracker->isIndexTracker() ); + tracker = static_cast( childTracker ); } else { tracker = new IndexTracker( name, ctx, ¤tTracker, size ); @@ -5845,6 +5954,11 @@ namespace Catch { while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); Totals deltaTotals = m_totals.delta( prevTotals ); + if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { + deltaTotals.assertions.failed++; + deltaTotals.testCases.passed--; + deltaTotals.testCases.failed++; + } m_totals.testCases += deltaTotals.testCases; m_reporter->testCaseEnded( TestCaseStats( testInfo, deltaTotals, @@ -6236,10 +6350,10 @@ namespace Catch { Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; } - int applyCommandLine( int argc, char const* argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { try { m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); - m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); + m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); if( m_configData.showHelp ) showHelp( m_configData.processName ); m_config.reset(); @@ -6263,16 +6377,13 @@ namespace Catch { m_config.reset(); } - int run( int argc, char const* argv[] ) { + int run( int argc, char const* const* const argv ) { int returnCode = applyCommandLine( argc, argv ); if( returnCode == 0 ) returnCode = run(); return returnCode; } - int run( int argc, char* argv[] ) { - return run( argc, const_cast( argv ) ); - } int run() { if( m_configData.showHelp ) @@ -6336,13 +6447,31 @@ namespace Catch { #include #include +#ifdef CATCH_CPP14_OR_GREATER +#include +#endif + namespace Catch { - struct LexSort { - bool operator() (TestCase i,TestCase j) const { return (i + static void shuffle( V& vector ) { + RandomNumberGenerator rng; +#ifdef CATCH_CPP14_OR_GREATER + std::shuffle( vector.begin(), vector.end(), rng ); +#else + std::random_shuffle( vector.begin(), vector.end(), rng ); +#endif + } }; inline std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { @@ -6351,14 +6480,12 @@ namespace Catch { switch( config.runOrder() ) { case RunTests::InLexicographicalOrder: - std::sort( sorted.begin(), sorted.end(), LexSort() ); + std::sort( sorted.begin(), sorted.end() ); break; case RunTests::InRandomOrder: { seedRng( config ); - - RandomNumberGenerator rng; - std::random_shuffle( sorted.begin(), sorted.end(), rng ); + RandomNumberGenerator::shuffle( sorted ); } break; case RunTests::InDeclarationOrder: @@ -6377,13 +6504,15 @@ namespace Catch { it != itEnd; ++it ) { std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); - if( !prev.second ){ - Catch::cerr() - << Colour( Colour::Red ) - << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" - << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; - exit(1); + if( !prev.second ) { + std::ostringstream ss; + + ss << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + + throw std::runtime_error(ss.str()); } } } @@ -6971,7 +7100,18 @@ namespace { IColourImpl* platformColourInstance() { static Win32ColourImpl s_instance; - return &s_instance; + + Ptr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = !isDebuggerActive() + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? &s_instance + : NoColourImpl::instance(); } } // end anon namespace @@ -7022,7 +7162,14 @@ namespace { IColourImpl* platformColourInstance() { Ptr config = getCurrentContext().getConfig(); - return (config && config->forceColour()) || isatty(STDOUT_FILENO) + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes ? PosixColourImpl::instance() : NoColourImpl::instance(); } @@ -7047,9 +7194,7 @@ namespace Catch { Colour::~Colour(){ if( !m_moved ) use( None ); } void Colour::use( Code _colourCode ) { - static IColourImpl* impl = isDebuggerActive() - ? NoColourImpl::instance() - : platformColourInstance(); + static IColourImpl* impl = platformColourInstance(); impl->use( _colourCode ); } @@ -7426,7 +7571,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 3, 4, "", 0 ); + Version libraryVersion( 1, 5, 6, "", 0 ); } @@ -8405,13 +8550,18 @@ public: // IStreamingReporter ++it ) (*it)->skipTest( testInfo ); } + + virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { + return this; + } + }; Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { Ptr resultingReporter; if( existingReporter ) { - MultipleReporters* multi = dynamic_cast( existingReporter.get() ); + MultipleReporters* multi = existingReporter->tryAsMulti(); if( !multi ) { multi = new MultipleReporters; resultingReporter = Ptr( multi ); @@ -8591,7 +8741,7 @@ namespace Catch { virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - virtual bool assertionEnded( AssertionStats const& assertionStats ) { + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { assert( !m_sectionStack.empty() ); SectionNode& sectionNode = *m_sectionStack.back(); sectionNode.assertions.push_back( assertionStats ); @@ -9722,7 +9872,7 @@ namespace Catch { if( totals.testCases.total() == 0 ) { stream << Colour( Colour::Warning ) << "No tests ran\n"; } - else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) { + else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { stream << Colour( Colour::ResultSuccess ) << "All tests passed"; stream << " (" << pluralise( totals.assertions.passed, "assertion" ) << " in "