diff --git a/README.md b/README.md index d12d676a..28439d09 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.0 build 30 (master branch)* +*v1.0 build 32 (master branch)* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/catch.hpp b/include/catch.hpp index a90ac2e2..b509d579 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -19,6 +19,9 @@ #ifdef CATCH_CONFIG_MAIN # define CATCH_CONFIG_RUNNER +#endif + +#ifdef CATCH_CONFIG_RUNNER # ifndef CLARA_CONFIG_MAIN # define CLARA_CONFIG_MAIN_NOT_DEFINED # define CLARA_CONFIG_MAIN diff --git a/include/internal/clara.h b/include/external/clara.h similarity index 82% rename from include/internal/clara.h rename to include/external/clara.h index f8198423..4b83d1d6 100644 --- a/include/internal/clara.h +++ b/include/external/clara.h @@ -191,7 +191,11 @@ namespace Clara { struct UnpositionalTag {}; - static const UnpositionalTag _; + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif namespace Detail { @@ -369,26 +373,6 @@ namespace Clara { void (*function)( C&, T ); }; - template - BoundArgFunction makeBoundField( M C::* _member ) { - return BoundArgFunction( new BoundDataMember( _member ) ); - } - template - BoundArgFunction makeBoundField( void (C::*_member)( M ) ) { - return BoundArgFunction( new BoundUnaryMethod( _member ) ); - } - template - BoundArgFunction makeBoundField( void (C::*_member)() ) { - return BoundArgFunction( new BoundNullaryMethod( _member ) ); - } - template - BoundArgFunction makeBoundField( void (*_function)( C& ) ) { - return BoundArgFunction( new BoundUnaryFunction( _function ) ); - } - template - BoundArgFunction makeBoundField( void (*_function)( C&, T ) ) { - return BoundArgFunction( new BoundBinaryFunction( _function ) ); - } } // namespace Detail struct Parser { @@ -435,31 +419,49 @@ namespace Clara { std::string separators; }; + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + template class CommandLine { - struct Arg { - Arg() : position( -1 ) {} - Arg( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ), position( -1 ) {} + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD - bool hasShortName( std::string const& shortName ) const { - for( std::vector::const_iterator - it = shortNames.begin(), itEnd = shortNames.end(); - it != itEnd; - ++it ) - if( *it == shortName ) - return true; - return false; - } - bool hasLongName( std::string const& _longName ) const { - return _longName == longName; - } - bool takesArg() const { - return !placeholder.empty(); - } - bool isFixedPositional() const { - return position != -1; - } bool isAnyPositional() const { return position == -1 && shortNames.empty() && longName.empty(); } @@ -470,10 +472,6 @@ namespace Clara { return "-" + shortNames[0]; return "positional args"; } - void validate() const { - if( boundField.takesArg() && !takesArg() ) - throw std::logic_error( "command line argument '" + dbgName() + "' must specify a placeholder" ); - } std::string commands() const { std::ostringstream oss; bool first = true; @@ -494,13 +492,6 @@ namespace Clara { oss << " <" << placeholder << ">"; return oss.str(); } - - Detail::BoundArgFunction boundField; - std::vector shortNames; - std::string longName; - std::string description; - std::string placeholder; - int position; }; // NOTE: std::auto_ptr is deprecated in c++11/c++0x @@ -510,72 +501,75 @@ namespace Clara { typedef std::auto_ptr ArgAutoPtr; #endif + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + + class ArgBuilder { public: - ArgBuilder( CommandLine* cl ) - : m_cl( cl ) - {} + ArgBuilder( Arg& arg ) : m_arg( arg ) {} - - ArgBuilder( ArgBuilder& other ) - : m_cl( other.m_cl ), - m_arg( other.m_arg ) - { - other.m_cl = NULL; - } - // !TBD: Need to include workarounds to be able to declare this - // destructor as able to throw exceptions - ~ArgBuilder() /* noexcept(false) */ { - if( m_cl && !std::uncaught_exception() ) { - m_arg.validate(); - if( m_arg.isFixedPositional() ) { - m_cl->m_positionalArgs.insert( std::make_pair( m_arg.position, m_arg ) ); - if( m_arg.position > m_cl->m_highestSpecifiedArgPosition ) - m_cl->m_highestSpecifiedArgPosition = m_arg.position; - } - else if( m_arg.isAnyPositional() ) { - if( m_cl->m_arg.get() ) - throw std::logic_error( "Only one unpositional argument can be added" ); - m_cl->m_arg = ArgAutoPtr( new Arg( m_arg ) ); - } - else - m_cl->m_options.push_back( m_arg ); - } - } - - template - void into( F f ) - { - m_arg.boundField = Detail::makeBoundField( f ); - } - - friend void addOptName( ArgBuilder& builder, std::string const& optName ) - { - if( optName.empty() ) - return; - if( Detail::startsWith( optName, "--" ) ) { - if( !builder.m_arg.longName.empty() ) - throw std::logic_error( "Only one long opt may be specified. '" - + builder.m_arg.longName - + "' already specified, now attempting to add '" - + optName + "'" ); - builder.m_arg.longName = optName.substr( 2 ); - } - else if( Detail::startsWith( optName, "-" ) ) - builder.m_arg.shortNames.push_back( optName.substr( 1 ) ); - else - throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); - } - friend void setPositionalArg( ArgBuilder& builder, int position ) - { - builder.m_arg.position = position; - } - - - // Can only supply placeholder after [str] - if it takes an arg - ArgBuilder& placeholder( std::string const& placeholder ) { + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg.boundField = new Detail::BoundDataMember( field ); + m_arg.placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg.boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::*_unaryMethod)( M ), std::string const& placeholder ) { + m_arg.boundField = new Detail::BoundUnaryMethod( _unaryMethod ); + m_arg.placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::*_unaryMethod)( bool ) ) { + m_arg.boundField = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::*_nullaryMethod)() ) { + m_arg.boundField = new Detail::BoundNullaryMethod( _nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (*_unaryFunction)( C& ) ) { + m_arg.boundField = new Detail::BoundUnaryFunction( _unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (*_binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg.boundField = new Detail::BoundBinaryFunction( _binaryFunction ); m_arg.placeholder = placeholder; - return *this; } ArgBuilder& describe( std::string const& description ) { @@ -588,17 +582,17 @@ namespace Clara { return *this; } - private: - CommandLine* m_cl; - Arg m_arg; + protected: + Arg& m_arg; }; + class OptBuilder : public ArgBuilder { public: - OptBuilder( CommandLine* cl ) : ArgBuilder( cl ) {} + OptBuilder( Arg& arg ) : ArgBuilder( arg ) {} OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} OptBuilder& operator[]( std::string const& optName ) { - addOptName( *this, optName ); + addOptName( ArgBuilder::m_arg, optName ); return *this; } }; @@ -617,8 +611,8 @@ namespace Clara { m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) { - if( other.m_arg.get() ) - m_arg = ArgAutoPtr( new Arg( *other.m_arg ) ); + if( other.m_floatingArg.get() ) + m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) ); } CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { @@ -628,26 +622,37 @@ namespace Clara { OptBuilder operator[]( std::string const& optName ) { - OptBuilder builder( this ); - addOptName( builder, optName ); + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( m_options.back() ); return builder; } ArgBuilder operator[]( int position ) { - ArgBuilder builder( this ); - setPositionalArg( builder, position ); + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( m_positionalArgs[position] ); return builder; } // Invoke this with the _ instance ArgBuilder operator[]( UnpositionalTag ) { - ArgBuilder builder( this ); + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg = ArgAutoPtr( new Arg() ); + ArgBuilder builder( *m_floatingArg ); return builder; } - template - void bindProcessName( F f ) { - m_boundProcessName = Detail::makeBoundField( f ); + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); } void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { @@ -688,16 +693,16 @@ namespace Clara { typename std::map::const_iterator it = m_positionalArgs.find( i ); if( it != m_positionalArgs.end() ) os << "<" << it->second.placeholder << ">"; - else if( m_arg.get() ) - os << "<" << m_arg->placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; else throw std::logic_error( "non consecutive positional arguments with no floating args" ); } // !TBD No indication of mandatory args - if( m_arg.get() ) { + if( m_floatingArg.get() ) { if( m_highestSpecifiedArgPosition > 1 ) os << " "; - os << "[<" << m_arg->placeholder << "> ...]"; + os << "[<" << m_floatingArg->placeholder << "> ...]"; } } std::string argSynopsis() const { @@ -813,13 +818,13 @@ namespace Clara { return unusedTokens; } std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { - if( !m_arg.get() ) + if( !m_floatingArg.get() ) return tokens; std::vector unusedTokens; for( std::size_t i = 0; i < tokens.size(); ++i ) { Parser::Token const& token = tokens[i]; if( token.type == Parser::Token::Positional ) - m_arg->boundField.set( config, token.data ); + m_floatingArg->boundField.set( config, token.data ); else unusedTokens.push_back( token ); } @@ -830,7 +835,7 @@ namespace Clara { Detail::BoundArgFunction m_boundProcessName; std::vector m_options; std::map m_positionalArgs; - ArgAutoPtr m_arg; + ArgAutoPtr m_floatingArg; int m_highestSpecifiedArgPosition; bool m_throwOnUnrecognisedTokens; }; diff --git a/include/internal/tbc_text_format.h b/include/external/tbc_text_format.h similarity index 100% rename from include/internal/tbc_text_format.h rename to include/external/tbc_text_format.h diff --git a/include/internal/catch_clara.h b/include/internal/catch_clara.h index e1f0c25a..bfe2f4b7 100644 --- a/include/internal/catch_clara.h +++ b/include/internal/catch_clara.h @@ -19,7 +19,7 @@ // Declare Clara inside the Catch namespace #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { -#include "clara.h" +#include "../external/clara.h" #undef STITCH_CLARA_OPEN_NAMESPACE diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index 126c861c..b72ac022 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -10,7 +10,10 @@ #include "catch_config.hpp" #include "catch_common.h" + +#ifdef CLARA_CONFIG_MAIN #include "catch_clara.h" +#endif #include @@ -53,6 +56,7 @@ namespace Catch { } } +#ifdef CLARA_CONFIG_MAIN inline Clara::CommandLine makeCommandLineParser() { using namespace Clara; @@ -62,57 +66,52 @@ namespace Catch { cli["-?"]["-h"]["--help"] .describe( "display usage information" ) - .into( &ConfigData::showHelp ); + .bind( &ConfigData::showHelp ); cli["-l"]["--list-tests"] .describe( "list all/matching test cases" ) - .into( &ConfigData::listTests ); + .bind( &ConfigData::listTests ); cli["-t"]["--list-tags"] .describe( "list all/matching tags" ) - .into( &ConfigData::listTags ); + .bind( &ConfigData::listTags ); cli["-s"]["--success"] .describe( "include successful tests in output" ) - .into( &ConfigData::showSuccessfulTests ); + .bind( &ConfigData::showSuccessfulTests ); cli["-b"]["--break"] .describe( "break into debugger on failure" ) - .into( &ConfigData::shouldDebugBreak ); + .bind( &ConfigData::shouldDebugBreak ); cli["-e"]["--nothrow"] .describe( "skip exception tests" ) - .into( &ConfigData::noThrow ); + .bind( &ConfigData::noThrow ); cli["-o"]["--out"] - .placeholder( "filename" ) .describe( "output filename" ) - .into( &ConfigData::outputFilename ); + .bind( &ConfigData::outputFilename, "filename" ); cli["-r"]["--reporter"] // .placeholder( "name[:filename]" ) - .placeholder( "name" ) .describe( "reporter to use (defaults to console)" ) - .into( &ConfigData::reporterName ); + .bind( &ConfigData::reporterName, "name" ); cli["-n"]["--name"] - .placeholder( "name" ) .describe( "suite name" ) - .into( &ConfigData::name ); + .bind( &ConfigData::name, "name" ); cli["-a"]["--abort"] .describe( "abort at first failure" ) - .into( &abortAfterFirst ); + .bind( &abortAfterFirst ); cli["-x"]["--abortx"] - .placeholder( "number of failures" ) .describe( "abort after x failures" ) - .into( &abortAfterX ); + .bind( &abortAfterX, "no. failures" ); cli["-w"]["--warn"] - .placeholder( "warning name" ) .describe( "enable warnings" ) - .into( &addWarning ); + .bind( &addWarning, "warning name" ); // - needs updating if reinstated // cli.into( &setVerbosity ) @@ -122,31 +121,29 @@ namespace Catch { // .placeholder( "level" ); cli[_] - .placeholder( "test name, pattern or tags" ) .describe( "which test or tests to use" ) - .into( &addTestOrTags ); + .bind( &addTestOrTags, "test name, pattern or tags" ); cli["-d"]["--durations"] - .placeholder( "yes/no" ) .describe( "show test durations" ) - .into( &setShowDurations ); + .bind( &setShowDurations, "yes/no" ); cli["-f"]["--input-file"] - .placeholder( "filename" ) .describe( "load test names to run from a file" ) - .into( &loadTestNamesFromFile ); + .bind( &loadTestNamesFromFile, "filename" ); // Less common commands which don't have a short form cli["--list-test-names-only"] .describe( "list all/matching test cases names only" ) - .into( &ConfigData::listTestNamesOnly ); + .bind( &ConfigData::listTestNamesOnly ); cli["--list-reporters"] .describe( "list all reporters" ) - .into( &ConfigData::listReporters ); + .bind( &ConfigData::listReporters ); return cli; } +#endif } // end namespace Catch diff --git a/include/internal/catch_text.h b/include/internal/catch_text.h index 4657f744..b66751f3 100644 --- a/include/internal/catch_text.h +++ b/include/internal/catch_text.h @@ -13,7 +13,7 @@ #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch -#include "tbc_text_format.h" +#include "../external/tbc_text_format.h" #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE namespace Catch { diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index e7321101..938a5b23 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -14,7 +14,7 @@ namespace Catch { // These numbers are maintained by a script template - const T LibraryVersionInfo::value( 1, 0, 30, "master" ); + const T LibraryVersionInfo::value( 1, 0, 32, "master" ); } #endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED diff --git a/projects/SelfTest/ClassTests.cpp b/projects/SelfTest/ClassTests.cpp index 4c306c36..9220cd4c 100644 --- a/projects/SelfTest/ClassTests.cpp +++ b/projects/SelfTest/ClassTests.cpp @@ -31,6 +31,7 @@ public: METHOD_AS_TEST_CASE( ::TestClass::succeedingCase, "A METHOD_AS_TEST_CASE based test run that succeeds", "[class]" ) METHOD_AS_TEST_CASE( ::TestClass::failingCase, "A METHOD_AS_TEST_CASE based test run that fails", "[.][class][failing]" ) + struct Fixture { Fixture() : m_a( 1 ) {} diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 9ed89634..f7b6126d 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -8,6 +8,8 @@ #if !defined(_WINDLL) #define CATCH_CONFIG_MAIN +#else +#define CLARA_CONFIG_MAIN #endif #include "catch.hpp" diff --git a/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index 03225a7f..e4a77c0d 100644 --- a/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj +++ b/projects/XCode4/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -66,7 +66,6 @@ 263FD06017AF8DF200988A20 /* catch_timer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_timer.hpp; sourceTree = ""; }; 263FD06117AF8DF200988A20 /* catch_timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_timer.h; sourceTree = ""; }; 266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VariadicMacrosTests.cpp; path = ../../../SelfTest/VariadicMacrosTests.cpp; sourceTree = ""; }; - 266E9AD117230ACF0061DAB2 /* catch_text.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_text.hpp; sourceTree = ""; }; 266ECD73170F3C620030D735 /* BDDTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BDDTests.cpp; path = ../../../SelfTest/BDDTests.cpp; sourceTree = ""; }; 266ECD8C1713614B0030D735 /* catch_legacy_reporter_adapter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_legacy_reporter_adapter.hpp; sourceTree = ""; }; 266ECD8D1713614B0030D735 /* catch_legacy_reporter_adapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_legacy_reporter_adapter.h; sourceTree = ""; }; @@ -76,12 +75,12 @@ 26847E5C16BBACB60043B9C1 /* catch_message.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_message.hpp; sourceTree = ""; }; 26847E5D16BBADB40043B9C1 /* catch_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_message.cpp; path = ../../../SelfTest/SurrogateCpps/catch_message.cpp; sourceTree = ""; }; 268F47B018A93F7800D8C14F /* catch_clara.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_clara.h; sourceTree = ""; }; - 268F47B118A944DB00D8C14F /* tbc_text_format.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tbc_text_format.h; path = ../../../../include/internal/tbc_text_format.h; sourceTree = ""; }; + 26926E8318D7777D004E10F2 /* clara.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = clara.h; path = ../../../../include/external/clara.h; sourceTree = ""; }; + 26926E8418D77809004E10F2 /* tbc_text_format.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tbc_text_format.h; path = ../../../../include/external/tbc_text_format.h; sourceTree = ""; }; 26948284179A9AB900ED166E /* SectionTrackerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SectionTrackerTests.cpp; path = ../../../SelfTest/SectionTrackerTests.cpp; sourceTree = ""; }; 26948287179EF7F900ED166E /* catch_test_case_tracker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_tracker.hpp; sourceTree = ""; }; 2694A1FB16A0000E004816E3 /* catch_text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = catch_text.cpp; sourceTree = ""; }; 26AEAF1617BEA18E009E32C9 /* catch_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_platform.h; sourceTree = ""; }; - 26C5F3EC17514B970056FB3C /* clara.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = clara.h; path = ../../../../include/internal/clara.h; sourceTree = ""; }; 26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = ""; }; 4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_info.hpp; sourceTree = ""; }; 4A084F1D15DAD15F0027E631 /* catch_test_spec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_test_spec.h; sourceTree = ""; }; @@ -199,8 +198,8 @@ 26C5F3EB17514B670056FB3C /* External */ = { isa = PBXGroup; children = ( - 26C5F3EC17514B970056FB3C /* clara.h */, - 268F47B118A944DB00D8C14F /* tbc_text_format.h */, + 26926E8418D77809004E10F2 /* tbc_text_format.h */, + 26926E8318D7777D004E10F2 /* clara.h */, ); name = External; sourceTree = ""; @@ -326,7 +325,6 @@ 4A6D0C5F149B3E3D00DB3EAA /* catch_section.hpp */, 261488FA184C81130041FBEB /* catch_test_spec.hpp */, 263FD06017AF8DF200988A20 /* catch_timer.hpp */, - 266E9AD117230ACF0061DAB2 /* catch_text.hpp */, 4A4B0F9C15CEFA8300AE2392 /* catch_impl.hpp */, 4A4B0F9715CE6CFB00AE2392 /* catch_registry_hub.hpp */, 4A6D0C50149B3E3D00DB3EAA /* catch_generators_impl.hpp */, diff --git a/single_include/catch.hpp b/single_include/catch.hpp index cae3e8dd..050ab0a0 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * CATCH v1.0 build 30 (master branch) - * Generated: 2014-03-10 11:19:55.332000 + * CATCH v1.0 build 32 (master branch) + * Generated: 2014-03-24 10:11:09.751000 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -23,6 +23,9 @@ #ifdef CATCH_CONFIG_MAIN # define CATCH_CONFIG_RUNNER +#endif + +#ifdef CATCH_CONFIG_RUNNER # ifndef CLARA_CONFIG_MAIN # define CLARA_CONFIG_MAIN_NOT_DEFINED # define CLARA_CONFIG_MAIN @@ -471,7 +474,7 @@ namespace Catch { #ifdef INTERNAL_CATCH_VS_NATIVE -#pragma warning( disable : 4505 ) // required for including CppUnitTest.h at /W4 +#pragma warning( disable:4505 ) // required for including CppUnitTest.h at /W4 #include @@ -4174,7 +4177,7 @@ return @ desc; \ #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch -// #included from: tbc_text_format.h +// #included from: ../external/tbc_text_format.h // Only use header guard if we are not using an outer namespace #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED @@ -4331,6 +4334,7 @@ namespace Catch { // #included from: internal/catch_commandline.hpp #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED +#ifdef CLARA_CONFIG_MAIN // #included from: catch_clara.h #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED @@ -4343,7 +4347,7 @@ namespace Catch { // Declare Clara inside the Catch namespace #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { -// #included from: clara.h +// #included from: ../external/clara.h // Only use header guard if we are not using an outer namespace #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) @@ -4521,7 +4525,11 @@ namespace Clara { struct UnpositionalTag {}; - static const UnpositionalTag _; + extern UnpositionalTag _; + +#ifdef CLARA_CONFIG_MAIN + UnpositionalTag _; +#endif namespace Detail { @@ -4698,26 +4706,6 @@ namespace Clara { void (*function)( C&, T ); }; - template - BoundArgFunction makeBoundField( M C::* _member ) { - return BoundArgFunction( new BoundDataMember( _member ) ); - } - template - BoundArgFunction makeBoundField( void (C::*_member)( M ) ) { - return BoundArgFunction( new BoundUnaryMethod( _member ) ); - } - template - BoundArgFunction makeBoundField( void (C::*_member)() ) { - return BoundArgFunction( new BoundNullaryMethod( _member ) ); - } - template - BoundArgFunction makeBoundField( void (*_function)( C& ) ) { - return BoundArgFunction( new BoundUnaryFunction( _function ) ); - } - template - BoundArgFunction makeBoundField( void (*_function)( C&, T ) ) { - return BoundArgFunction( new BoundBinaryFunction( _function ) ); - } } // namespace Detail struct Parser { @@ -4764,31 +4752,49 @@ namespace Clara { std::string separators; }; + template + struct CommonArgProperties { + CommonArgProperties() {} + CommonArgProperties( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ) {} + + Detail::BoundArgFunction boundField; + std::string description; + std::string placeholder; // Only value if boundField takes an arg + + bool takesArg() const { + return !placeholder.empty(); + } + }; + struct OptionArgProperties { + std::vector shortNames; + std::string longName; + + bool hasShortName( std::string const& shortName ) const { + return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); + } + bool hasLongName( std::string const& _longName ) const { + return _longName == longName; + } + + }; + struct PositionalArgProperties { + PositionalArgProperties() : position( -1 ) {} + int position; // -1 means non-positional (floating) + + bool isFixedPositional() const { + return position != -1; + } + }; + template class CommandLine { - struct Arg { - Arg() : position( -1 ) {} - Arg( Detail::BoundArgFunction const& _boundField ) : boundField( _boundField ), position( -1 ) {} + struct Arg : CommonArgProperties, OptionArgProperties, PositionalArgProperties { + Arg() {} + Arg( Detail::BoundArgFunction const& _boundField ) : CommonArgProperties( _boundField ) {} + + using CommonArgProperties::placeholder; // !TBD - bool hasShortName( std::string const& shortName ) const { - for( std::vector::const_iterator - it = shortNames.begin(), itEnd = shortNames.end(); - it != itEnd; - ++it ) - if( *it == shortName ) - return true; - return false; - } - bool hasLongName( std::string const& _longName ) const { - return _longName == longName; - } - bool takesArg() const { - return !placeholder.empty(); - } - bool isFixedPositional() const { - return position != -1; - } bool isAnyPositional() const { return position == -1 && shortNames.empty() && longName.empty(); } @@ -4799,10 +4805,6 @@ namespace Clara { return "-" + shortNames[0]; return "positional args"; } - void validate() const { - if( boundField.takesArg() && !takesArg() ) - throw std::logic_error( "command line argument '" + dbgName() + "' must specify a placeholder" ); - } std::string commands() const { std::ostringstream oss; bool first = true; @@ -4823,13 +4825,6 @@ namespace Clara { oss << " <" << placeholder << ">"; return oss.str(); } - - Detail::BoundArgFunction boundField; - std::vector shortNames; - std::string longName; - std::string description; - std::string placeholder; - int position; }; // NOTE: std::auto_ptr is deprecated in c++11/c++0x @@ -4839,70 +4834,74 @@ namespace Clara { typedef std::auto_ptr ArgAutoPtr; #endif + friend void addOptName( Arg& arg, std::string const& optName ) + { + if( optName.empty() ) + return; + if( Detail::startsWith( optName, "--" ) ) { + if( !arg.longName.empty() ) + throw std::logic_error( "Only one long opt may be specified. '" + + arg.longName + + "' already specified, now attempting to add '" + + optName + "'" ); + arg.longName = optName.substr( 2 ); + } + else if( Detail::startsWith( optName, "-" ) ) + arg.shortNames.push_back( optName.substr( 1 ) ); + else + throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); + } + friend void setPositionalArg( Arg& arg, int position ) + { + arg.position = position; + } + class ArgBuilder { public: - ArgBuilder( CommandLine* cl ) - : m_cl( cl ) - {} + ArgBuilder( Arg& arg ) : m_arg( arg ) {} - ArgBuilder( ArgBuilder& other ) - : m_cl( other.m_cl ), - m_arg( other.m_arg ) - { - other.m_cl = NULL; - } - // !TBD: Need to include workarounds to be able to declare this - // destructor as able to throw exceptions - ~ArgBuilder() /* noexcept(false) */ { - if( m_cl && !std::uncaught_exception() ) { - m_arg.validate(); - if( m_arg.isFixedPositional() ) { - m_cl->m_positionalArgs.insert( std::make_pair( m_arg.position, m_arg ) ); - if( m_arg.position > m_cl->m_highestSpecifiedArgPosition ) - m_cl->m_highestSpecifiedArgPosition = m_arg.position; - } - else if( m_arg.isAnyPositional() ) { - if( m_cl->m_arg.get() ) - throw std::logic_error( "Only one unpositional argument can be added" ); - m_cl->m_arg = ArgAutoPtr( new Arg( m_arg ) ); - } - else - m_cl->m_options.push_back( m_arg ); - } - } - - template - void into( F f ) - { - m_arg.boundField = Detail::makeBoundField( f ); - } - - friend void addOptName( ArgBuilder& builder, std::string const& optName ) - { - if( optName.empty() ) - return; - if( Detail::startsWith( optName, "--" ) ) { - if( !builder.m_arg.longName.empty() ) - throw std::logic_error( "Only one long opt may be specified. '" - + builder.m_arg.longName - + "' already specified, now attempting to add '" - + optName + "'" ); - builder.m_arg.longName = optName.substr( 2 ); - } - else if( Detail::startsWith( optName, "-" ) ) - builder.m_arg.shortNames.push_back( optName.substr( 1 ) ); - else - throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); - } - friend void setPositionalArg( ArgBuilder& builder, int position ) - { - builder.m_arg.position = position; - } - - // Can only supply placeholder after [str] - if it takes an arg - ArgBuilder& placeholder( std::string const& placeholder ) { + // Bind a non-boolean data member (requires placeholder string) + template + void bind( M C::* field, std::string const& placeholder ) { + m_arg.boundField = new Detail::BoundDataMember( field ); + m_arg.placeholder = placeholder; + } + // Bind a boolean data member (no placeholder required) + template + void bind( bool C::* field ) { + m_arg.boundField = new Detail::BoundDataMember( field ); + } + + // Bind a method taking a single, non-boolean argument (requires a placeholder string) + template + void bind( void (C::*_unaryMethod)( M ), std::string const& placeholder ) { + m_arg.boundField = new Detail::BoundUnaryMethod( _unaryMethod ); + m_arg.placeholder = placeholder; + } + + // Bind a method taking a single, boolean argument (no placeholder string required) + template + void bind( void (C::*_unaryMethod)( bool ) ) { + m_arg.boundField = new Detail::BoundUnaryMethod( _unaryMethod ); + } + + // Bind a method that takes no arguments (will be called if opt is present) + template + void bind( void (C::*_nullaryMethod)() ) { + m_arg.boundField = new Detail::BoundNullaryMethod( _nullaryMethod ); + } + + // Bind a free function taking a single argument - the object to operate on (no placeholder string required) + template + void bind( void (*_unaryFunction)( C& ) ) { + m_arg.boundField = new Detail::BoundUnaryFunction( _unaryFunction ); + } + + // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) + template + void bind( void (*_binaryFunction)( C&, T ), std::string const& placeholder ) { + m_arg.boundField = new Detail::BoundBinaryFunction( _binaryFunction ); m_arg.placeholder = placeholder; - return *this; } ArgBuilder& describe( std::string const& description ) { @@ -4915,17 +4914,17 @@ namespace Clara { return *this; } - private: - CommandLine* m_cl; - Arg m_arg; + protected: + Arg& m_arg; }; + class OptBuilder : public ArgBuilder { public: - OptBuilder( CommandLine* cl ) : ArgBuilder( cl ) {} + OptBuilder( Arg& arg ) : ArgBuilder( arg ) {} OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} OptBuilder& operator[]( std::string const& optName ) { - addOptName( *this, optName ); + addOptName( ArgBuilder::m_arg, optName ); return *this; } }; @@ -4944,8 +4943,8 @@ namespace Clara { m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) { - if( other.m_arg.get() ) - m_arg = ArgAutoPtr( new Arg( *other.m_arg ) ); + if( other.m_floatingArg.get() ) + m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) ); } CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { @@ -4954,26 +4953,37 @@ namespace Clara { } OptBuilder operator[]( std::string const& optName ) { - OptBuilder builder( this ); - addOptName( builder, optName ); + m_options.push_back( Arg() ); + addOptName( m_options.back(), optName ); + OptBuilder builder( m_options.back() ); return builder; } ArgBuilder operator[]( int position ) { - ArgBuilder builder( this ); - setPositionalArg( builder, position ); + m_positionalArgs.insert( std::make_pair( position, Arg() ) ); + if( position > m_highestSpecifiedArgPosition ) + m_highestSpecifiedArgPosition = position; + setPositionalArg( m_positionalArgs[position], position ); + ArgBuilder builder( m_positionalArgs[position] ); return builder; } // Invoke this with the _ instance ArgBuilder operator[]( UnpositionalTag ) { - ArgBuilder builder( this ); + if( m_floatingArg.get() ) + throw std::logic_error( "Only one unpositional argument can be added" ); + m_floatingArg = ArgAutoPtr( new Arg() ); + ArgBuilder builder( *m_floatingArg ); return builder; } - template - void bindProcessName( F f ) { - m_boundProcessName = Detail::makeBoundField( f ); + template + void bindProcessName( M C::* field ) { + m_boundProcessName = new Detail::BoundDataMember( field ); + } + template + void bindProcessName( void (C::*_unaryMethod)( M ) ) { + m_boundProcessName = new Detail::BoundUnaryMethod( _unaryMethod ); } void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { @@ -5014,16 +5024,16 @@ namespace Clara { typename std::map::const_iterator it = m_positionalArgs.find( i ); if( it != m_positionalArgs.end() ) os << "<" << it->second.placeholder << ">"; - else if( m_arg.get() ) - os << "<" << m_arg->placeholder << ">"; + else if( m_floatingArg.get() ) + os << "<" << m_floatingArg->placeholder << ">"; else throw std::logic_error( "non consecutive positional arguments with no floating args" ); } // !TBD No indication of mandatory args - if( m_arg.get() ) { + if( m_floatingArg.get() ) { if( m_highestSpecifiedArgPosition > 1 ) os << " "; - os << "[<" << m_arg->placeholder << "> ...]"; + os << "[<" << m_floatingArg->placeholder << "> ...]"; } } std::string argSynopsis() const { @@ -5139,13 +5149,13 @@ namespace Clara { return unusedTokens; } std::vector populateFloatingArgs( std::vector const& tokens, ConfigT& config ) const { - if( !m_arg.get() ) + if( !m_floatingArg.get() ) return tokens; std::vector unusedTokens; for( std::size_t i = 0; i < tokens.size(); ++i ) { Parser::Token const& token = tokens[i]; if( token.type == Parser::Token::Positional ) - m_arg->boundField.set( config, token.data ); + m_floatingArg->boundField.set( config, token.data ); else unusedTokens.push_back( token ); } @@ -5156,7 +5166,7 @@ namespace Clara { Detail::BoundArgFunction m_boundProcessName; std::vector m_options; std::map m_positionalArgs; - ArgAutoPtr m_arg; + ArgAutoPtr m_floatingArg; int m_highestSpecifiedArgPosition; bool m_throwOnUnrecognisedTokens; }; @@ -5176,6 +5186,8 @@ STITCH_CLARA_CLOSE_NAMESPACE #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #endif +#endif + #include namespace Catch { @@ -5217,6 +5229,7 @@ namespace Catch { } } +#ifdef CLARA_CONFIG_MAIN inline Clara::CommandLine makeCommandLineParser() { using namespace Clara; @@ -5226,57 +5239,52 @@ namespace Catch { cli["-?"]["-h"]["--help"] .describe( "display usage information" ) - .into( &ConfigData::showHelp ); + .bind( &ConfigData::showHelp ); cli["-l"]["--list-tests"] .describe( "list all/matching test cases" ) - .into( &ConfigData::listTests ); + .bind( &ConfigData::listTests ); cli["-t"]["--list-tags"] .describe( "list all/matching tags" ) - .into( &ConfigData::listTags ); + .bind( &ConfigData::listTags ); cli["-s"]["--success"] .describe( "include successful tests in output" ) - .into( &ConfigData::showSuccessfulTests ); + .bind( &ConfigData::showSuccessfulTests ); cli["-b"]["--break"] .describe( "break into debugger on failure" ) - .into( &ConfigData::shouldDebugBreak ); + .bind( &ConfigData::shouldDebugBreak ); cli["-e"]["--nothrow"] .describe( "skip exception tests" ) - .into( &ConfigData::noThrow ); + .bind( &ConfigData::noThrow ); cli["-o"]["--out"] - .placeholder( "filename" ) .describe( "output filename" ) - .into( &ConfigData::outputFilename ); + .bind( &ConfigData::outputFilename, "filename" ); cli["-r"]["--reporter"] // .placeholder( "name[:filename]" ) - .placeholder( "name" ) .describe( "reporter to use (defaults to console)" ) - .into( &ConfigData::reporterName ); + .bind( &ConfigData::reporterName, "name" ); cli["-n"]["--name"] - .placeholder( "name" ) .describe( "suite name" ) - .into( &ConfigData::name ); + .bind( &ConfigData::name, "name" ); cli["-a"]["--abort"] .describe( "abort at first failure" ) - .into( &abortAfterFirst ); + .bind( &abortAfterFirst ); cli["-x"]["--abortx"] - .placeholder( "number of failures" ) .describe( "abort after x failures" ) - .into( &abortAfterX ); + .bind( &abortAfterX, "no. failures" ); cli["-w"]["--warn"] - .placeholder( "warning name" ) .describe( "enable warnings" ) - .into( &addWarning ); + .bind( &addWarning, "warning name" ); // - needs updating if reinstated // cli.into( &setVerbosity ) @@ -5286,31 +5294,29 @@ namespace Catch { // .placeholder( "level" ); cli[_] - .placeholder( "test name, pattern or tags" ) .describe( "which test or tests to use" ) - .into( &addTestOrTags ); + .bind( &addTestOrTags, "test name, pattern or tags" ); cli["-d"]["--durations"] - .placeholder( "yes/no" ) .describe( "show test durations" ) - .into( &setShowDurations ); + .bind( &setShowDurations, "yes/no" ); cli["-f"]["--input-file"] - .placeholder( "filename" ) .describe( "load test names to run from a file" ) - .into( &loadTestNamesFromFile ); + .bind( &loadTestNamesFromFile, "filename" ); // Less common commands which don't have a short form cli["--list-test-names-only"] .describe( "list all/matching test cases names only" ) - .into( &ConfigData::listTestNamesOnly ); + .bind( &ConfigData::listTestNamesOnly ); cli["--list-reporters"] .describe( "list all reporters" ) - .into( &ConfigData::listReporters ); + .bind( &ConfigData::listReporters ); return cli; } +#endif } // end namespace Catch @@ -7559,7 +7565,7 @@ namespace Catch { // These numbers are maintained by a script template - const T LibraryVersionInfo::value( 1, 0, 30, "master" ); + const T LibraryVersionInfo::value( 1, 0, 32, "master" ); } // #included from: catch_message.hpp diff --git a/single_include_projects/SelfTest/ClassTests.cpp b/single_include_projects/SelfTest/ClassTests.cpp index 4c306c36..9220cd4c 100644 --- a/single_include_projects/SelfTest/ClassTests.cpp +++ b/single_include_projects/SelfTest/ClassTests.cpp @@ -31,6 +31,7 @@ public: METHOD_AS_TEST_CASE( ::TestClass::succeedingCase, "A METHOD_AS_TEST_CASE based test run that succeeds", "[class]" ) METHOD_AS_TEST_CASE( ::TestClass::failingCase, "A METHOD_AS_TEST_CASE based test run that fails", "[.][class][failing]" ) + struct Fixture { Fixture() : m_a( 1 ) {} diff --git a/single_include_projects/SelfTest/TestMain.cpp b/single_include_projects/SelfTest/TestMain.cpp index 9ed89634..f7b6126d 100644 --- a/single_include_projects/SelfTest/TestMain.cpp +++ b/single_include_projects/SelfTest/TestMain.cpp @@ -8,6 +8,8 @@ #if !defined(_WINDLL) #define CATCH_CONFIG_MAIN +#else +#define CLARA_CONFIG_MAIN #endif #include "catch.hpp"