Merge build 32

This commit is contained in:
Malcolm Noyes 2014-03-24 11:07:10 +00:00
commit 48064ca589
14 changed files with 353 additions and 338 deletions

View File

@ -1,6 +1,6 @@
![catch logo](catch-logo-small.png) ![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) Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch)

View File

@ -19,6 +19,9 @@
#ifdef CATCH_CONFIG_MAIN #ifdef CATCH_CONFIG_MAIN
# define CATCH_CONFIG_RUNNER # define CATCH_CONFIG_RUNNER
#endif
#ifdef CATCH_CONFIG_RUNNER
# ifndef CLARA_CONFIG_MAIN # ifndef CLARA_CONFIG_MAIN
# define CLARA_CONFIG_MAIN_NOT_DEFINED # define CLARA_CONFIG_MAIN_NOT_DEFINED
# define CLARA_CONFIG_MAIN # define CLARA_CONFIG_MAIN

View File

@ -191,7 +191,11 @@ namespace Clara {
struct UnpositionalTag {}; struct UnpositionalTag {};
static const UnpositionalTag _; extern UnpositionalTag _;
#ifdef CLARA_CONFIG_MAIN
UnpositionalTag _;
#endif
namespace Detail { namespace Detail {
@ -369,26 +373,6 @@ namespace Clara {
void (*function)( C&, T ); void (*function)( C&, T );
}; };
template<typename C, typename M>
BoundArgFunction<C> makeBoundField( M C::* _member ) {
return BoundArgFunction<C>( new BoundDataMember<C,M>( _member ) );
}
template<typename C, typename M>
BoundArgFunction<C> makeBoundField( void (C::*_member)( M ) ) {
return BoundArgFunction<C>( new BoundUnaryMethod<C,M>( _member ) );
}
template<typename C>
BoundArgFunction<C> makeBoundField( void (C::*_member)() ) {
return BoundArgFunction<C>( new BoundNullaryMethod<C>( _member ) );
}
template<typename C>
BoundArgFunction<C> makeBoundField( void (*_function)( C& ) ) {
return BoundArgFunction<C>( new BoundUnaryFunction<C>( _function ) );
}
template<typename C, typename T>
BoundArgFunction<C> makeBoundField( void (*_function)( C&, T ) ) {
return BoundArgFunction<C>( new BoundBinaryFunction<C, T>( _function ) );
}
} // namespace Detail } // namespace Detail
struct Parser { struct Parser {
@ -436,30 +420,48 @@ namespace Clara {
}; };
template<typename ConfigT> template<typename ConfigT>
class CommandLine { struct CommonArgProperties {
CommonArgProperties() {}
CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
struct Arg { Detail::BoundArgFunction<ConfigT> boundField;
Arg() : position( -1 ) {} std::string description;
Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ), position( -1 ) {} std::string placeholder; // Only value if boundField takes an arg
bool takesArg() const {
return !placeholder.empty();
}
};
struct OptionArgProperties {
std::vector<std::string> shortNames;
std::string longName;
bool hasShortName( std::string const& shortName ) const { bool hasShortName( std::string const& shortName ) const {
for( std::vector<std::string>::const_iterator return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
it = shortNames.begin(), itEnd = shortNames.end();
it != itEnd;
++it )
if( *it == shortName )
return true;
return false;
} }
bool hasLongName( std::string const& _longName ) const { bool hasLongName( std::string const& _longName ) const {
return _longName == longName; return _longName == longName;
} }
bool takesArg() const {
return !placeholder.empty(); };
} struct PositionalArgProperties {
PositionalArgProperties() : position( -1 ) {}
int position; // -1 means non-positional (floating)
bool isFixedPositional() const { bool isFixedPositional() const {
return position != -1; return position != -1;
} }
};
template<typename ConfigT>
class CommandLine {
struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
Arg() {}
Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
using CommonArgProperties<ConfigT>::placeholder; // !TBD
bool isAnyPositional() const { bool isAnyPositional() const {
return position == -1 && shortNames.empty() && longName.empty(); return position == -1 && shortNames.empty() && longName.empty();
} }
@ -470,10 +472,6 @@ namespace Clara {
return "-" + shortNames[0]; return "-" + shortNames[0];
return "positional args"; 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::string commands() const {
std::ostringstream oss; std::ostringstream oss;
bool first = true; bool first = true;
@ -494,13 +492,6 @@ namespace Clara {
oss << " <" << placeholder << ">"; oss << " <" << placeholder << ">";
return oss.str(); return oss.str();
} }
Detail::BoundArgFunction<ConfigT> boundField;
std::vector<std::string> shortNames;
std::string longName;
std::string description;
std::string placeholder;
int position;
}; };
// NOTE: std::auto_ptr is deprecated in c++11/c++0x // NOTE: std::auto_ptr is deprecated in c++11/c++0x
@ -510,72 +501,75 @@ namespace Clara {
typedef std::auto_ptr<Arg> ArgAutoPtr; typedef std::auto_ptr<Arg> ArgAutoPtr;
#endif #endif
class ArgBuilder { friend void addOptName( Arg& arg, std::string const& optName )
public:
ArgBuilder( CommandLine* cl )
: m_cl( cl )
{}
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<typename F>
void into( F f )
{
m_arg.boundField = Detail::makeBoundField( f );
}
friend void addOptName( ArgBuilder& builder, std::string const& optName )
{ {
if( optName.empty() ) if( optName.empty() )
return; return;
if( Detail::startsWith( optName, "--" ) ) { if( Detail::startsWith( optName, "--" ) ) {
if( !builder.m_arg.longName.empty() ) if( !arg.longName.empty() )
throw std::logic_error( "Only one long opt may be specified. '" throw std::logic_error( "Only one long opt may be specified. '"
+ builder.m_arg.longName + arg.longName
+ "' already specified, now attempting to add '" + "' already specified, now attempting to add '"
+ optName + "'" ); + optName + "'" );
builder.m_arg.longName = optName.substr( 2 ); arg.longName = optName.substr( 2 );
} }
else if( Detail::startsWith( optName, "-" ) ) else if( Detail::startsWith( optName, "-" ) )
builder.m_arg.shortNames.push_back( optName.substr( 1 ) ); arg.shortNames.push_back( optName.substr( 1 ) );
else else
throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
} }
friend void setPositionalArg( ArgBuilder& builder, int position ) friend void setPositionalArg( Arg& arg, int position )
{ {
builder.m_arg.position = position; arg.position = position;
} }
// Can only supply placeholder after [str] - if it takes an arg class ArgBuilder {
ArgBuilder& placeholder( std::string const& placeholder ) { public:
ArgBuilder( Arg& arg ) : m_arg( arg ) {}
// Bind a non-boolean data member (requires placeholder string)
template<typename C, typename M>
void bind( M C::* field, std::string const& placeholder ) {
m_arg.boundField = new Detail::BoundDataMember<C,M>( field );
m_arg.placeholder = placeholder;
}
// Bind a boolean data member (no placeholder required)
template<typename C>
void bind( bool C::* field ) {
m_arg.boundField = new Detail::BoundDataMember<C,bool>( field );
}
// Bind a method taking a single, non-boolean argument (requires a placeholder string)
template<typename C, typename M>
void bind( void (C::*_unaryMethod)( M ), std::string const& placeholder ) {
m_arg.boundField = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
m_arg.placeholder = placeholder;
}
// Bind a method taking a single, boolean argument (no placeholder string required)
template<typename C>
void bind( void (C::*_unaryMethod)( bool ) ) {
m_arg.boundField = new Detail::BoundUnaryMethod<C,bool>( _unaryMethod );
}
// Bind a method that takes no arguments (will be called if opt is present)
template<typename C>
void bind( void (C::*_nullaryMethod)() ) {
m_arg.boundField = new Detail::BoundNullaryMethod<C>( _nullaryMethod );
}
// Bind a free function taking a single argument - the object to operate on (no placeholder string required)
template<typename C>
void bind( void (*_unaryFunction)( C& ) ) {
m_arg.boundField = new Detail::BoundUnaryFunction<C>( _unaryFunction );
}
// Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
template<typename C, typename T>
void bind( void (*_binaryFunction)( C&, T ), std::string const& placeholder ) {
m_arg.boundField = new Detail::BoundBinaryFunction<C, T>( _binaryFunction );
m_arg.placeholder = placeholder; m_arg.placeholder = placeholder;
return *this;
} }
ArgBuilder& describe( std::string const& description ) { ArgBuilder& describe( std::string const& description ) {
@ -588,17 +582,17 @@ namespace Clara {
return *this; return *this;
} }
private: protected:
CommandLine* m_cl; Arg& m_arg;
Arg m_arg;
}; };
class OptBuilder : public ArgBuilder { class OptBuilder : public ArgBuilder {
public: public:
OptBuilder( CommandLine* cl ) : ArgBuilder( cl ) {} OptBuilder( Arg& arg ) : ArgBuilder( arg ) {}
OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
OptBuilder& operator[]( std::string const& optName ) { OptBuilder& operator[]( std::string const& optName ) {
addOptName( *this, optName ); addOptName( ArgBuilder::m_arg, optName );
return *this; return *this;
} }
}; };
@ -617,8 +611,8 @@ namespace Clara {
m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
{ {
if( other.m_arg.get() ) if( other.m_floatingArg.get() )
m_arg = ArgAutoPtr( new Arg( *other.m_arg ) ); m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) );
} }
CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
@ -628,26 +622,37 @@ namespace Clara {
OptBuilder operator[]( std::string const& optName ) { OptBuilder operator[]( std::string const& optName ) {
OptBuilder builder( this ); m_options.push_back( Arg() );
addOptName( builder, optName ); addOptName( m_options.back(), optName );
OptBuilder builder( m_options.back() );
return builder; return builder;
} }
ArgBuilder operator[]( int position ) { ArgBuilder operator[]( int position ) {
ArgBuilder builder( this ); m_positionalArgs.insert( std::make_pair( position, Arg() ) );
setPositionalArg( builder, position ); if( position > m_highestSpecifiedArgPosition )
m_highestSpecifiedArgPosition = position;
setPositionalArg( m_positionalArgs[position], position );
ArgBuilder builder( m_positionalArgs[position] );
return builder; return builder;
} }
// Invoke this with the _ instance // Invoke this with the _ instance
ArgBuilder operator[]( UnpositionalTag ) { 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; return builder;
} }
template<typename F> template<typename C, typename M>
void bindProcessName( F f ) { void bindProcessName( M C::* field ) {
m_boundProcessName = Detail::makeBoundField( f ); m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
}
template<typename C, typename M>
void bindProcessName( void (C::*_unaryMethod)( M ) ) {
m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
} }
void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { 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<int, Arg>::const_iterator it = m_positionalArgs.find( i ); typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
if( it != m_positionalArgs.end() ) if( it != m_positionalArgs.end() )
os << "<" << it->second.placeholder << ">"; os << "<" << it->second.placeholder << ">";
else if( m_arg.get() ) else if( m_floatingArg.get() )
os << "<" << m_arg->placeholder << ">"; os << "<" << m_floatingArg->placeholder << ">";
else else
throw std::logic_error( "non consecutive positional arguments with no floating args" ); throw std::logic_error( "non consecutive positional arguments with no floating args" );
} }
// !TBD No indication of mandatory args // !TBD No indication of mandatory args
if( m_arg.get() ) { if( m_floatingArg.get() ) {
if( m_highestSpecifiedArgPosition > 1 ) if( m_highestSpecifiedArgPosition > 1 )
os << " "; os << " ";
os << "[<" << m_arg->placeholder << "> ...]"; os << "[<" << m_floatingArg->placeholder << "> ...]";
} }
} }
std::string argSynopsis() const { std::string argSynopsis() const {
@ -813,13 +818,13 @@ namespace Clara {
return unusedTokens; return unusedTokens;
} }
std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
if( !m_arg.get() ) if( !m_floatingArg.get() )
return tokens; return tokens;
std::vector<Parser::Token> unusedTokens; std::vector<Parser::Token> unusedTokens;
for( std::size_t i = 0; i < tokens.size(); ++i ) { for( std::size_t i = 0; i < tokens.size(); ++i ) {
Parser::Token const& token = tokens[i]; Parser::Token const& token = tokens[i];
if( token.type == Parser::Token::Positional ) if( token.type == Parser::Token::Positional )
m_arg->boundField.set( config, token.data ); m_floatingArg->boundField.set( config, token.data );
else else
unusedTokens.push_back( token ); unusedTokens.push_back( token );
} }
@ -830,7 +835,7 @@ namespace Clara {
Detail::BoundArgFunction<ConfigT> m_boundProcessName; Detail::BoundArgFunction<ConfigT> m_boundProcessName;
std::vector<Arg> m_options; std::vector<Arg> m_options;
std::map<int, Arg> m_positionalArgs; std::map<int, Arg> m_positionalArgs;
ArgAutoPtr m_arg; ArgAutoPtr m_floatingArg;
int m_highestSpecifiedArgPosition; int m_highestSpecifiedArgPosition;
bool m_throwOnUnrecognisedTokens; bool m_throwOnUnrecognisedTokens;
}; };

View File

@ -19,7 +19,7 @@
// Declare Clara inside the Catch namespace // Declare Clara inside the Catch namespace
#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
#include "clara.h" #include "../external/clara.h"
#undef STITCH_CLARA_OPEN_NAMESPACE #undef STITCH_CLARA_OPEN_NAMESPACE

View File

@ -10,7 +10,10 @@
#include "catch_config.hpp" #include "catch_config.hpp"
#include "catch_common.h" #include "catch_common.h"
#ifdef CLARA_CONFIG_MAIN
#include "catch_clara.h" #include "catch_clara.h"
#endif
#include <fstream> #include <fstream>
@ -53,6 +56,7 @@ namespace Catch {
} }
} }
#ifdef CLARA_CONFIG_MAIN
inline Clara::CommandLine<ConfigData> makeCommandLineParser() { inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
using namespace Clara; using namespace Clara;
@ -62,57 +66,52 @@ namespace Catch {
cli["-?"]["-h"]["--help"] cli["-?"]["-h"]["--help"]
.describe( "display usage information" ) .describe( "display usage information" )
.into( &ConfigData::showHelp ); .bind( &ConfigData::showHelp );
cli["-l"]["--list-tests"] cli["-l"]["--list-tests"]
.describe( "list all/matching test cases" ) .describe( "list all/matching test cases" )
.into( &ConfigData::listTests ); .bind( &ConfigData::listTests );
cli["-t"]["--list-tags"] cli["-t"]["--list-tags"]
.describe( "list all/matching tags" ) .describe( "list all/matching tags" )
.into( &ConfigData::listTags ); .bind( &ConfigData::listTags );
cli["-s"]["--success"] cli["-s"]["--success"]
.describe( "include successful tests in output" ) .describe( "include successful tests in output" )
.into( &ConfigData::showSuccessfulTests ); .bind( &ConfigData::showSuccessfulTests );
cli["-b"]["--break"] cli["-b"]["--break"]
.describe( "break into debugger on failure" ) .describe( "break into debugger on failure" )
.into( &ConfigData::shouldDebugBreak ); .bind( &ConfigData::shouldDebugBreak );
cli["-e"]["--nothrow"] cli["-e"]["--nothrow"]
.describe( "skip exception tests" ) .describe( "skip exception tests" )
.into( &ConfigData::noThrow ); .bind( &ConfigData::noThrow );
cli["-o"]["--out"] cli["-o"]["--out"]
.placeholder( "filename" )
.describe( "output filename" ) .describe( "output filename" )
.into( &ConfigData::outputFilename ); .bind( &ConfigData::outputFilename, "filename" );
cli["-r"]["--reporter"] cli["-r"]["--reporter"]
// .placeholder( "name[:filename]" ) // .placeholder( "name[:filename]" )
.placeholder( "name" )
.describe( "reporter to use (defaults to console)" ) .describe( "reporter to use (defaults to console)" )
.into( &ConfigData::reporterName ); .bind( &ConfigData::reporterName, "name" );
cli["-n"]["--name"] cli["-n"]["--name"]
.placeholder( "name" )
.describe( "suite name" ) .describe( "suite name" )
.into( &ConfigData::name ); .bind( &ConfigData::name, "name" );
cli["-a"]["--abort"] cli["-a"]["--abort"]
.describe( "abort at first failure" ) .describe( "abort at first failure" )
.into( &abortAfterFirst ); .bind( &abortAfterFirst );
cli["-x"]["--abortx"] cli["-x"]["--abortx"]
.placeholder( "number of failures" )
.describe( "abort after x failures" ) .describe( "abort after x failures" )
.into( &abortAfterX ); .bind( &abortAfterX, "no. failures" );
cli["-w"]["--warn"] cli["-w"]["--warn"]
.placeholder( "warning name" )
.describe( "enable warnings" ) .describe( "enable warnings" )
.into( &addWarning ); .bind( &addWarning, "warning name" );
// - needs updating if reinstated // - needs updating if reinstated
// cli.into( &setVerbosity ) // cli.into( &setVerbosity )
@ -122,31 +121,29 @@ namespace Catch {
// .placeholder( "level" ); // .placeholder( "level" );
cli[_] cli[_]
.placeholder( "test name, pattern or tags" )
.describe( "which test or tests to use" ) .describe( "which test or tests to use" )
.into( &addTestOrTags ); .bind( &addTestOrTags, "test name, pattern or tags" );
cli["-d"]["--durations"] cli["-d"]["--durations"]
.placeholder( "yes/no" )
.describe( "show test durations" ) .describe( "show test durations" )
.into( &setShowDurations ); .bind( &setShowDurations, "yes/no" );
cli["-f"]["--input-file"] cli["-f"]["--input-file"]
.placeholder( "filename" )
.describe( "load test names to run from a file" ) .describe( "load test names to run from a file" )
.into( &loadTestNamesFromFile ); .bind( &loadTestNamesFromFile, "filename" );
// Less common commands which don't have a short form // Less common commands which don't have a short form
cli["--list-test-names-only"] cli["--list-test-names-only"]
.describe( "list all/matching test cases names only" ) .describe( "list all/matching test cases names only" )
.into( &ConfigData::listTestNamesOnly ); .bind( &ConfigData::listTestNamesOnly );
cli["--list-reporters"] cli["--list-reporters"]
.describe( "list all reporters" ) .describe( "list all reporters" )
.into( &ConfigData::listReporters ); .bind( &ConfigData::listReporters );
return cli; return cli;
} }
#endif
} // end namespace Catch } // end namespace Catch

View File

@ -13,7 +13,7 @@
#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch #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 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
namespace Catch { namespace Catch {

View File

@ -14,7 +14,7 @@ namespace Catch {
// These numbers are maintained by a script // These numbers are maintained by a script
template <typename T> template <typename T>
const T LibraryVersionInfo<T>::value( 1, 0, 30, "master" ); const T LibraryVersionInfo<T>::value( 1, 0, 32, "master" );
} }
#endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED #endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED

View File

@ -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::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]" ) METHOD_AS_TEST_CASE( ::TestClass::failingCase, "A METHOD_AS_TEST_CASE based test run that fails", "[.][class][failing]" )
struct Fixture struct Fixture
{ {
Fixture() : m_a( 1 ) {} Fixture() : m_a( 1 ) {}

View File

@ -8,6 +8,8 @@
#if !defined(_WINDLL) #if !defined(_WINDLL)
#define CATCH_CONFIG_MAIN #define CATCH_CONFIG_MAIN
#else
#define CLARA_CONFIG_MAIN
#endif #endif
#include "catch.hpp" #include "catch.hpp"

View File

@ -66,7 +66,6 @@
263FD06017AF8DF200988A20 /* catch_timer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_timer.hpp; sourceTree = "<group>"; }; 263FD06017AF8DF200988A20 /* catch_timer.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_timer.hpp; sourceTree = "<group>"; };
263FD06117AF8DF200988A20 /* catch_timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_timer.h; sourceTree = "<group>"; }; 263FD06117AF8DF200988A20 /* catch_timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_timer.h; sourceTree = "<group>"; };
266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VariadicMacrosTests.cpp; path = ../../../SelfTest/VariadicMacrosTests.cpp; sourceTree = "<group>"; }; 266B06B616F3A60A004ED264 /* VariadicMacrosTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VariadicMacrosTests.cpp; path = ../../../SelfTest/VariadicMacrosTests.cpp; sourceTree = "<group>"; };
266E9AD117230ACF0061DAB2 /* catch_text.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_text.hpp; sourceTree = "<group>"; };
266ECD73170F3C620030D735 /* BDDTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BDDTests.cpp; path = ../../../SelfTest/BDDTests.cpp; sourceTree = "<group>"; }; 266ECD73170F3C620030D735 /* BDDTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BDDTests.cpp; path = ../../../SelfTest/BDDTests.cpp; sourceTree = "<group>"; };
266ECD8C1713614B0030D735 /* catch_legacy_reporter_adapter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_legacy_reporter_adapter.hpp; sourceTree = "<group>"; }; 266ECD8C1713614B0030D735 /* catch_legacy_reporter_adapter.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_legacy_reporter_adapter.hpp; sourceTree = "<group>"; };
266ECD8D1713614B0030D735 /* catch_legacy_reporter_adapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_legacy_reporter_adapter.h; sourceTree = "<group>"; }; 266ECD8D1713614B0030D735 /* catch_legacy_reporter_adapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_legacy_reporter_adapter.h; sourceTree = "<group>"; };
@ -76,12 +75,12 @@
26847E5C16BBACB60043B9C1 /* catch_message.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_message.hpp; sourceTree = "<group>"; }; 26847E5C16BBACB60043B9C1 /* catch_message.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_message.hpp; sourceTree = "<group>"; };
26847E5D16BBADB40043B9C1 /* catch_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_message.cpp; path = ../../../SelfTest/SurrogateCpps/catch_message.cpp; sourceTree = "<group>"; }; 26847E5D16BBADB40043B9C1 /* catch_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_message.cpp; path = ../../../SelfTest/SurrogateCpps/catch_message.cpp; sourceTree = "<group>"; };
268F47B018A93F7800D8C14F /* catch_clara.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_clara.h; sourceTree = "<group>"; }; 268F47B018A93F7800D8C14F /* catch_clara.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_clara.h; sourceTree = "<group>"; };
268F47B118A944DB00D8C14F /* tbc_text_format.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = tbc_text_format.h; path = ../../../../include/internal/tbc_text_format.h; sourceTree = "<group>"; }; 26926E8318D7777D004E10F2 /* clara.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = clara.h; path = ../../../../include/external/clara.h; sourceTree = "<group>"; };
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 = "<group>"; };
26948284179A9AB900ED166E /* SectionTrackerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SectionTrackerTests.cpp; path = ../../../SelfTest/SectionTrackerTests.cpp; sourceTree = "<group>"; }; 26948284179A9AB900ED166E /* SectionTrackerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SectionTrackerTests.cpp; path = ../../../SelfTest/SectionTrackerTests.cpp; sourceTree = "<group>"; };
26948287179EF7F900ED166E /* catch_test_case_tracker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_tracker.hpp; sourceTree = "<group>"; }; 26948287179EF7F900ED166E /* catch_test_case_tracker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_tracker.hpp; sourceTree = "<group>"; };
2694A1FB16A0000E004816E3 /* catch_text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = catch_text.cpp; sourceTree = "<group>"; }; 2694A1FB16A0000E004816E3 /* catch_text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = catch_text.cpp; sourceTree = "<group>"; };
26AEAF1617BEA18E009E32C9 /* catch_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_platform.h; sourceTree = "<group>"; }; 26AEAF1617BEA18E009E32C9 /* catch_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_platform.h; sourceTree = "<group>"; };
26C5F3EC17514B970056FB3C /* clara.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = clara.h; path = ../../../../include/internal/clara.h; sourceTree = "<group>"; };
26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = "<group>"; }; 26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = "<group>"; };
4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_info.hpp; sourceTree = "<group>"; }; 4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_info.hpp; sourceTree = "<group>"; };
4A084F1D15DAD15F0027E631 /* catch_test_spec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_test_spec.h; sourceTree = "<group>"; }; 4A084F1D15DAD15F0027E631 /* catch_test_spec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_test_spec.h; sourceTree = "<group>"; };
@ -199,8 +198,8 @@
26C5F3EB17514B670056FB3C /* External */ = { 26C5F3EB17514B670056FB3C /* External */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
26C5F3EC17514B970056FB3C /* clara.h */, 26926E8418D77809004E10F2 /* tbc_text_format.h */,
268F47B118A944DB00D8C14F /* tbc_text_format.h */, 26926E8318D7777D004E10F2 /* clara.h */,
); );
name = External; name = External;
sourceTree = "<group>"; sourceTree = "<group>";
@ -326,7 +325,6 @@
4A6D0C5F149B3E3D00DB3EAA /* catch_section.hpp */, 4A6D0C5F149B3E3D00DB3EAA /* catch_section.hpp */,
261488FA184C81130041FBEB /* catch_test_spec.hpp */, 261488FA184C81130041FBEB /* catch_test_spec.hpp */,
263FD06017AF8DF200988A20 /* catch_timer.hpp */, 263FD06017AF8DF200988A20 /* catch_timer.hpp */,
266E9AD117230ACF0061DAB2 /* catch_text.hpp */,
4A4B0F9C15CEFA8300AE2392 /* catch_impl.hpp */, 4A4B0F9C15CEFA8300AE2392 /* catch_impl.hpp */,
4A4B0F9715CE6CFB00AE2392 /* catch_registry_hub.hpp */, 4A4B0F9715CE6CFB00AE2392 /* catch_registry_hub.hpp */,
4A6D0C50149B3E3D00DB3EAA /* catch_generators_impl.hpp */, 4A6D0C50149B3E3D00DB3EAA /* catch_generators_impl.hpp */,

View File

@ -1,6 +1,6 @@
/* /*
* CATCH v1.0 build 30 (master branch) * CATCH v1.0 build 32 (master branch)
* Generated: 2014-03-10 11:19:55.332000 * Generated: 2014-03-24 10:11:09.751000
* ---------------------------------------------------------- * ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly * This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@ -23,6 +23,9 @@
#ifdef CATCH_CONFIG_MAIN #ifdef CATCH_CONFIG_MAIN
# define CATCH_CONFIG_RUNNER # define CATCH_CONFIG_RUNNER
#endif
#ifdef CATCH_CONFIG_RUNNER
# ifndef CLARA_CONFIG_MAIN # ifndef CLARA_CONFIG_MAIN
# define CLARA_CONFIG_MAIN_NOT_DEFINED # define CLARA_CONFIG_MAIN_NOT_DEFINED
# define CLARA_CONFIG_MAIN # define CLARA_CONFIG_MAIN
@ -471,7 +474,7 @@ namespace Catch {
#ifdef INTERNAL_CATCH_VS_NATIVE #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 <CppUnitTest.h> #include <CppUnitTest.h>
@ -4174,7 +4177,7 @@ return @ desc; \
#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch #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 // Only use header guard if we are not using an outer namespace
#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
@ -4331,6 +4334,7 @@ namespace Catch {
// #included from: internal/catch_commandline.hpp // #included from: internal/catch_commandline.hpp
#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
#ifdef CLARA_CONFIG_MAIN
// #included from: catch_clara.h // #included from: catch_clara.h
#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
@ -4343,7 +4347,7 @@ namespace Catch {
// Declare Clara inside the Catch namespace // Declare Clara inside the Catch namespace
#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { #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 // Only use header guard if we are not using an outer namespace
#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
@ -4521,7 +4525,11 @@ namespace Clara {
struct UnpositionalTag {}; struct UnpositionalTag {};
static const UnpositionalTag _; extern UnpositionalTag _;
#ifdef CLARA_CONFIG_MAIN
UnpositionalTag _;
#endif
namespace Detail { namespace Detail {
@ -4698,26 +4706,6 @@ namespace Clara {
void (*function)( C&, T ); void (*function)( C&, T );
}; };
template<typename C, typename M>
BoundArgFunction<C> makeBoundField( M C::* _member ) {
return BoundArgFunction<C>( new BoundDataMember<C,M>( _member ) );
}
template<typename C, typename M>
BoundArgFunction<C> makeBoundField( void (C::*_member)( M ) ) {
return BoundArgFunction<C>( new BoundUnaryMethod<C,M>( _member ) );
}
template<typename C>
BoundArgFunction<C> makeBoundField( void (C::*_member)() ) {
return BoundArgFunction<C>( new BoundNullaryMethod<C>( _member ) );
}
template<typename C>
BoundArgFunction<C> makeBoundField( void (*_function)( C& ) ) {
return BoundArgFunction<C>( new BoundUnaryFunction<C>( _function ) );
}
template<typename C, typename T>
BoundArgFunction<C> makeBoundField( void (*_function)( C&, T ) ) {
return BoundArgFunction<C>( new BoundBinaryFunction<C, T>( _function ) );
}
} // namespace Detail } // namespace Detail
struct Parser { struct Parser {
@ -4765,30 +4753,48 @@ namespace Clara {
}; };
template<typename ConfigT> template<typename ConfigT>
class CommandLine { struct CommonArgProperties {
CommonArgProperties() {}
CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
struct Arg { Detail::BoundArgFunction<ConfigT> boundField;
Arg() : position( -1 ) {} std::string description;
Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ), position( -1 ) {} std::string placeholder; // Only value if boundField takes an arg
bool takesArg() const {
return !placeholder.empty();
}
};
struct OptionArgProperties {
std::vector<std::string> shortNames;
std::string longName;
bool hasShortName( std::string const& shortName ) const { bool hasShortName( std::string const& shortName ) const {
for( std::vector<std::string>::const_iterator return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
it = shortNames.begin(), itEnd = shortNames.end();
it != itEnd;
++it )
if( *it == shortName )
return true;
return false;
} }
bool hasLongName( std::string const& _longName ) const { bool hasLongName( std::string const& _longName ) const {
return _longName == longName; return _longName == longName;
} }
bool takesArg() const {
return !placeholder.empty(); };
} struct PositionalArgProperties {
PositionalArgProperties() : position( -1 ) {}
int position; // -1 means non-positional (floating)
bool isFixedPositional() const { bool isFixedPositional() const {
return position != -1; return position != -1;
} }
};
template<typename ConfigT>
class CommandLine {
struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
Arg() {}
Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
using CommonArgProperties<ConfigT>::placeholder; // !TBD
bool isAnyPositional() const { bool isAnyPositional() const {
return position == -1 && shortNames.empty() && longName.empty(); return position == -1 && shortNames.empty() && longName.empty();
} }
@ -4799,10 +4805,6 @@ namespace Clara {
return "-" + shortNames[0]; return "-" + shortNames[0];
return "positional args"; 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::string commands() const {
std::ostringstream oss; std::ostringstream oss;
bool first = true; bool first = true;
@ -4823,13 +4825,6 @@ namespace Clara {
oss << " <" << placeholder << ">"; oss << " <" << placeholder << ">";
return oss.str(); return oss.str();
} }
Detail::BoundArgFunction<ConfigT> boundField;
std::vector<std::string> shortNames;
std::string longName;
std::string description;
std::string placeholder;
int position;
}; };
// NOTE: std::auto_ptr is deprecated in c++11/c++0x // NOTE: std::auto_ptr is deprecated in c++11/c++0x
@ -4839,70 +4834,74 @@ namespace Clara {
typedef std::auto_ptr<Arg> ArgAutoPtr; typedef std::auto_ptr<Arg> ArgAutoPtr;
#endif #endif
class ArgBuilder { friend void addOptName( Arg& arg, std::string const& optName )
public:
ArgBuilder( CommandLine* cl )
: m_cl( cl )
{}
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<typename F>
void into( F f )
{
m_arg.boundField = Detail::makeBoundField( f );
}
friend void addOptName( ArgBuilder& builder, std::string const& optName )
{ {
if( optName.empty() ) if( optName.empty() )
return; return;
if( Detail::startsWith( optName, "--" ) ) { if( Detail::startsWith( optName, "--" ) ) {
if( !builder.m_arg.longName.empty() ) if( !arg.longName.empty() )
throw std::logic_error( "Only one long opt may be specified. '" throw std::logic_error( "Only one long opt may be specified. '"
+ builder.m_arg.longName + arg.longName
+ "' already specified, now attempting to add '" + "' already specified, now attempting to add '"
+ optName + "'" ); + optName + "'" );
builder.m_arg.longName = optName.substr( 2 ); arg.longName = optName.substr( 2 );
} }
else if( Detail::startsWith( optName, "-" ) ) else if( Detail::startsWith( optName, "-" ) )
builder.m_arg.shortNames.push_back( optName.substr( 1 ) ); arg.shortNames.push_back( optName.substr( 1 ) );
else else
throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
} }
friend void setPositionalArg( ArgBuilder& builder, int position ) friend void setPositionalArg( Arg& arg, int position )
{ {
builder.m_arg.position = position; arg.position = position;
} }
// Can only supply placeholder after [str] - if it takes an arg class ArgBuilder {
ArgBuilder& placeholder( std::string const& placeholder ) { public:
ArgBuilder( Arg& arg ) : m_arg( arg ) {}
// Bind a non-boolean data member (requires placeholder string)
template<typename C, typename M>
void bind( M C::* field, std::string const& placeholder ) {
m_arg.boundField = new Detail::BoundDataMember<C,M>( field );
m_arg.placeholder = placeholder;
}
// Bind a boolean data member (no placeholder required)
template<typename C>
void bind( bool C::* field ) {
m_arg.boundField = new Detail::BoundDataMember<C,bool>( field );
}
// Bind a method taking a single, non-boolean argument (requires a placeholder string)
template<typename C, typename M>
void bind( void (C::*_unaryMethod)( M ), std::string const& placeholder ) {
m_arg.boundField = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
m_arg.placeholder = placeholder;
}
// Bind a method taking a single, boolean argument (no placeholder string required)
template<typename C>
void bind( void (C::*_unaryMethod)( bool ) ) {
m_arg.boundField = new Detail::BoundUnaryMethod<C,bool>( _unaryMethod );
}
// Bind a method that takes no arguments (will be called if opt is present)
template<typename C>
void bind( void (C::*_nullaryMethod)() ) {
m_arg.boundField = new Detail::BoundNullaryMethod<C>( _nullaryMethod );
}
// Bind a free function taking a single argument - the object to operate on (no placeholder string required)
template<typename C>
void bind( void (*_unaryFunction)( C& ) ) {
m_arg.boundField = new Detail::BoundUnaryFunction<C>( _unaryFunction );
}
// Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
template<typename C, typename T>
void bind( void (*_binaryFunction)( C&, T ), std::string const& placeholder ) {
m_arg.boundField = new Detail::BoundBinaryFunction<C, T>( _binaryFunction );
m_arg.placeholder = placeholder; m_arg.placeholder = placeholder;
return *this;
} }
ArgBuilder& describe( std::string const& description ) { ArgBuilder& describe( std::string const& description ) {
@ -4915,17 +4914,17 @@ namespace Clara {
return *this; return *this;
} }
private: protected:
CommandLine* m_cl; Arg& m_arg;
Arg m_arg;
}; };
class OptBuilder : public ArgBuilder { class OptBuilder : public ArgBuilder {
public: public:
OptBuilder( CommandLine* cl ) : ArgBuilder( cl ) {} OptBuilder( Arg& arg ) : ArgBuilder( arg ) {}
OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
OptBuilder& operator[]( std::string const& optName ) { OptBuilder& operator[]( std::string const& optName ) {
addOptName( *this, optName ); addOptName( ArgBuilder::m_arg, optName );
return *this; return *this;
} }
}; };
@ -4944,8 +4943,8 @@ namespace Clara {
m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
{ {
if( other.m_arg.get() ) if( other.m_floatingArg.get() )
m_arg = ArgAutoPtr( new Arg( *other.m_arg ) ); m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) );
} }
CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
@ -4954,26 +4953,37 @@ namespace Clara {
} }
OptBuilder operator[]( std::string const& optName ) { OptBuilder operator[]( std::string const& optName ) {
OptBuilder builder( this ); m_options.push_back( Arg() );
addOptName( builder, optName ); addOptName( m_options.back(), optName );
OptBuilder builder( m_options.back() );
return builder; return builder;
} }
ArgBuilder operator[]( int position ) { ArgBuilder operator[]( int position ) {
ArgBuilder builder( this ); m_positionalArgs.insert( std::make_pair( position, Arg() ) );
setPositionalArg( builder, position ); if( position > m_highestSpecifiedArgPosition )
m_highestSpecifiedArgPosition = position;
setPositionalArg( m_positionalArgs[position], position );
ArgBuilder builder( m_positionalArgs[position] );
return builder; return builder;
} }
// Invoke this with the _ instance // Invoke this with the _ instance
ArgBuilder operator[]( UnpositionalTag ) { 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; return builder;
} }
template<typename F> template<typename C, typename M>
void bindProcessName( F f ) { void bindProcessName( M C::* field ) {
m_boundProcessName = Detail::makeBoundField( f ); m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
}
template<typename C, typename M>
void bindProcessName( void (C::*_unaryMethod)( M ) ) {
m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
} }
void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { 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<int, Arg>::const_iterator it = m_positionalArgs.find( i ); typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
if( it != m_positionalArgs.end() ) if( it != m_positionalArgs.end() )
os << "<" << it->second.placeholder << ">"; os << "<" << it->second.placeholder << ">";
else if( m_arg.get() ) else if( m_floatingArg.get() )
os << "<" << m_arg->placeholder << ">"; os << "<" << m_floatingArg->placeholder << ">";
else else
throw std::logic_error( "non consecutive positional arguments with no floating args" ); throw std::logic_error( "non consecutive positional arguments with no floating args" );
} }
// !TBD No indication of mandatory args // !TBD No indication of mandatory args
if( m_arg.get() ) { if( m_floatingArg.get() ) {
if( m_highestSpecifiedArgPosition > 1 ) if( m_highestSpecifiedArgPosition > 1 )
os << " "; os << " ";
os << "[<" << m_arg->placeholder << "> ...]"; os << "[<" << m_floatingArg->placeholder << "> ...]";
} }
} }
std::string argSynopsis() const { std::string argSynopsis() const {
@ -5139,13 +5149,13 @@ namespace Clara {
return unusedTokens; return unusedTokens;
} }
std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
if( !m_arg.get() ) if( !m_floatingArg.get() )
return tokens; return tokens;
std::vector<Parser::Token> unusedTokens; std::vector<Parser::Token> unusedTokens;
for( std::size_t i = 0; i < tokens.size(); ++i ) { for( std::size_t i = 0; i < tokens.size(); ++i ) {
Parser::Token const& token = tokens[i]; Parser::Token const& token = tokens[i];
if( token.type == Parser::Token::Positional ) if( token.type == Parser::Token::Positional )
m_arg->boundField.set( config, token.data ); m_floatingArg->boundField.set( config, token.data );
else else
unusedTokens.push_back( token ); unusedTokens.push_back( token );
} }
@ -5156,7 +5166,7 @@ namespace Clara {
Detail::BoundArgFunction<ConfigT> m_boundProcessName; Detail::BoundArgFunction<ConfigT> m_boundProcessName;
std::vector<Arg> m_options; std::vector<Arg> m_options;
std::map<int, Arg> m_positionalArgs; std::map<int, Arg> m_positionalArgs;
ArgAutoPtr m_arg; ArgAutoPtr m_floatingArg;
int m_highestSpecifiedArgPosition; int m_highestSpecifiedArgPosition;
bool m_throwOnUnrecognisedTokens; bool m_throwOnUnrecognisedTokens;
}; };
@ -5176,6 +5186,8 @@ STITCH_CLARA_CLOSE_NAMESPACE
#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
#endif #endif
#endif
#include <fstream> #include <fstream>
namespace Catch { namespace Catch {
@ -5217,6 +5229,7 @@ namespace Catch {
} }
} }
#ifdef CLARA_CONFIG_MAIN
inline Clara::CommandLine<ConfigData> makeCommandLineParser() { inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
using namespace Clara; using namespace Clara;
@ -5226,57 +5239,52 @@ namespace Catch {
cli["-?"]["-h"]["--help"] cli["-?"]["-h"]["--help"]
.describe( "display usage information" ) .describe( "display usage information" )
.into( &ConfigData::showHelp ); .bind( &ConfigData::showHelp );
cli["-l"]["--list-tests"] cli["-l"]["--list-tests"]
.describe( "list all/matching test cases" ) .describe( "list all/matching test cases" )
.into( &ConfigData::listTests ); .bind( &ConfigData::listTests );
cli["-t"]["--list-tags"] cli["-t"]["--list-tags"]
.describe( "list all/matching tags" ) .describe( "list all/matching tags" )
.into( &ConfigData::listTags ); .bind( &ConfigData::listTags );
cli["-s"]["--success"] cli["-s"]["--success"]
.describe( "include successful tests in output" ) .describe( "include successful tests in output" )
.into( &ConfigData::showSuccessfulTests ); .bind( &ConfigData::showSuccessfulTests );
cli["-b"]["--break"] cli["-b"]["--break"]
.describe( "break into debugger on failure" ) .describe( "break into debugger on failure" )
.into( &ConfigData::shouldDebugBreak ); .bind( &ConfigData::shouldDebugBreak );
cli["-e"]["--nothrow"] cli["-e"]["--nothrow"]
.describe( "skip exception tests" ) .describe( "skip exception tests" )
.into( &ConfigData::noThrow ); .bind( &ConfigData::noThrow );
cli["-o"]["--out"] cli["-o"]["--out"]
.placeholder( "filename" )
.describe( "output filename" ) .describe( "output filename" )
.into( &ConfigData::outputFilename ); .bind( &ConfigData::outputFilename, "filename" );
cli["-r"]["--reporter"] cli["-r"]["--reporter"]
// .placeholder( "name[:filename]" ) // .placeholder( "name[:filename]" )
.placeholder( "name" )
.describe( "reporter to use (defaults to console)" ) .describe( "reporter to use (defaults to console)" )
.into( &ConfigData::reporterName ); .bind( &ConfigData::reporterName, "name" );
cli["-n"]["--name"] cli["-n"]["--name"]
.placeholder( "name" )
.describe( "suite name" ) .describe( "suite name" )
.into( &ConfigData::name ); .bind( &ConfigData::name, "name" );
cli["-a"]["--abort"] cli["-a"]["--abort"]
.describe( "abort at first failure" ) .describe( "abort at first failure" )
.into( &abortAfterFirst ); .bind( &abortAfterFirst );
cli["-x"]["--abortx"] cli["-x"]["--abortx"]
.placeholder( "number of failures" )
.describe( "abort after x failures" ) .describe( "abort after x failures" )
.into( &abortAfterX ); .bind( &abortAfterX, "no. failures" );
cli["-w"]["--warn"] cli["-w"]["--warn"]
.placeholder( "warning name" )
.describe( "enable warnings" ) .describe( "enable warnings" )
.into( &addWarning ); .bind( &addWarning, "warning name" );
// - needs updating if reinstated // - needs updating if reinstated
// cli.into( &setVerbosity ) // cli.into( &setVerbosity )
@ -5286,31 +5294,29 @@ namespace Catch {
// .placeholder( "level" ); // .placeholder( "level" );
cli[_] cli[_]
.placeholder( "test name, pattern or tags" )
.describe( "which test or tests to use" ) .describe( "which test or tests to use" )
.into( &addTestOrTags ); .bind( &addTestOrTags, "test name, pattern or tags" );
cli["-d"]["--durations"] cli["-d"]["--durations"]
.placeholder( "yes/no" )
.describe( "show test durations" ) .describe( "show test durations" )
.into( &setShowDurations ); .bind( &setShowDurations, "yes/no" );
cli["-f"]["--input-file"] cli["-f"]["--input-file"]
.placeholder( "filename" )
.describe( "load test names to run from a file" ) .describe( "load test names to run from a file" )
.into( &loadTestNamesFromFile ); .bind( &loadTestNamesFromFile, "filename" );
// Less common commands which don't have a short form // Less common commands which don't have a short form
cli["--list-test-names-only"] cli["--list-test-names-only"]
.describe( "list all/matching test cases names only" ) .describe( "list all/matching test cases names only" )
.into( &ConfigData::listTestNamesOnly ); .bind( &ConfigData::listTestNamesOnly );
cli["--list-reporters"] cli["--list-reporters"]
.describe( "list all reporters" ) .describe( "list all reporters" )
.into( &ConfigData::listReporters ); .bind( &ConfigData::listReporters );
return cli; return cli;
} }
#endif
} // end namespace Catch } // end namespace Catch
@ -7559,7 +7565,7 @@ namespace Catch {
// These numbers are maintained by a script // These numbers are maintained by a script
template <typename T> template <typename T>
const T LibraryVersionInfo<T>::value( 1, 0, 30, "master" ); const T LibraryVersionInfo<T>::value( 1, 0, 32, "master" );
} }
// #included from: catch_message.hpp // #included from: catch_message.hpp

View File

@ -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::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]" ) METHOD_AS_TEST_CASE( ::TestClass::failingCase, "A METHOD_AS_TEST_CASE based test run that fails", "[.][class][failing]" )
struct Fixture struct Fixture
{ {
Fixture() : m_a( 1 ) {} Fixture() : m_a( 1 ) {}

View File

@ -8,6 +8,8 @@
#if !defined(_WINDLL) #if !defined(_WINDLL)
#define CATCH_CONFIG_MAIN #define CATCH_CONFIG_MAIN
#else
#define CLARA_CONFIG_MAIN
#endif #endif
#include "catch.hpp" #include "catch.hpp"