mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-04 21:29:54 +01:00
Refactored command line parser to be more cohesive
Also added a set of unit tests for them (incomplete)
This commit is contained in:
parent
06e959be3e
commit
163088a11f
@ -22,10 +22,14 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
|
||||||
|
INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
|
||||||
|
INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
|
||||||
|
|
||||||
inline int Main( Config& config ) {
|
inline int Main( Config& config ) {
|
||||||
|
|
||||||
// Handle list request
|
// Handle list request
|
||||||
if( config.listWhat() != Config::List::None )
|
if( config.listWhat() != List::None )
|
||||||
return List( config );
|
return List( config );
|
||||||
|
|
||||||
// Open output file, if specified
|
// Open output file, if specified
|
||||||
@ -72,28 +76,33 @@ namespace Catch {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void showUsage( std::ostream& os ) {
|
||||||
|
os << "\t-l, --list <tests | reporters> [xml]\n"
|
||||||
|
<< "\t-t, --test <testspec> [<testspec>...]\n"
|
||||||
|
<< "\t-r, --reporter <reporter name>\n"
|
||||||
|
<< "\t-o, --out <file name>|<%stream name>\n"
|
||||||
|
<< "\t-s, --success\n"
|
||||||
|
<< "\t-b, --break\n"
|
||||||
|
<< "\t-n, --name <name>\n\n"
|
||||||
|
<< "For more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line" << std::endl;
|
||||||
|
}
|
||||||
inline void showHelp( std::string exeName ) {
|
inline void showHelp( std::string exeName ) {
|
||||||
std::string::size_type pos = exeName.find_last_of( "/\\" );
|
std::string::size_type pos = exeName.find_last_of( "/\\" );
|
||||||
if( pos != std::string::npos ) {
|
if( pos != std::string::npos ) {
|
||||||
exeName = exeName.substr( pos+1 );
|
exeName = exeName.substr( pos+1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << exeName << " is a CATCH host application. Options are as follows:\n\n"
|
std::cout << exeName << " is a CATCH host application. Options are as follows:\n\n";
|
||||||
<< "\t-l, --list <tests | reporters> [xml]\n"
|
showUsage( std::cout );
|
||||||
<< "\t-t, --test <testspec> [<testspec>...]\n"
|
|
||||||
<< "\t-r, --reporter <reporter name>\n"
|
|
||||||
<< "\t-o, --out <file name>|<%stream name>\n"
|
|
||||||
<< "\t-s, --success\n"
|
|
||||||
<< "\t-b, --break\n"
|
|
||||||
<< "\t-n, --name <name>\n\n"
|
|
||||||
<< "For more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Main( int argc, char* const argv[], Config& config ) {
|
inline int Main( int argc, char* const argv[], Config& config ) {
|
||||||
ArgParser( argc, argv, config );
|
|
||||||
|
parseIntoConfig( CommandParser( argc, argv ), config );
|
||||||
|
|
||||||
if( !config.getMessage().empty() ) {
|
if( !config.getMessage().empty() ) {
|
||||||
std::cerr << config.getMessage() << std::endl;
|
std::cerr << config.getMessage() << + "\n\nUsage: ...\n\n";
|
||||||
|
showUsage( std::cerr );
|
||||||
Catch::Context::cleanUp();
|
Catch::Context::cleanUp();
|
||||||
return (std::numeric_limits<int>::max)();
|
return (std::numeric_limits<int>::max)();
|
||||||
}
|
}
|
||||||
|
@ -12,175 +12,162 @@
|
|||||||
#include "catch_runner_impl.hpp"
|
#include "catch_runner_impl.hpp"
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
// -l, --list tests [xml] lists available tests (optionally in xml)
|
|
||||||
// -l, --list reporters [xml] lists available reports (optionally in xml)
|
|
||||||
// -l, --list all [xml] lists available tests and reports (optionally in xml)
|
|
||||||
// -t, --test "testspec" ["testspec", ...]
|
|
||||||
// -r, --reporter <type>
|
|
||||||
// -o, --out filename to write to
|
|
||||||
// -s, --success report successful cases too
|
|
||||||
// -b, --break breaks into debugger on test failure
|
|
||||||
// -n, --name specifies an optional name for the test run
|
|
||||||
class ArgParser : NonCopyable {
|
|
||||||
|
|
||||||
enum Mode {
|
|
||||||
modeNone,
|
|
||||||
modeList,
|
|
||||||
modeTest,
|
|
||||||
modeReport,
|
|
||||||
modeOutput,
|
|
||||||
modeSuccess,
|
|
||||||
modeBreak,
|
|
||||||
modeName,
|
|
||||||
modeHelp,
|
|
||||||
|
|
||||||
modeError
|
|
||||||
};
|
|
||||||
|
|
||||||
|
class Command {
|
||||||
public:
|
public:
|
||||||
ArgParser ( int argc, char * const argv[], Config& config )
|
Command(){}
|
||||||
: m_mode( modeNone ),
|
|
||||||
m_config( config ) {
|
|
||||||
|
|
||||||
for( int i=1; i < argc; ++i ) {
|
Command( const std::string& name ) : m_name( name ) {}
|
||||||
if( argv[i][0] == '-' ) {
|
|
||||||
std::string cmd = ( argv[i] );
|
Command& operator += ( const std::string& arg ) {
|
||||||
if( cmd == "-l" || cmd == "--list" )
|
m_args.push_back( arg );
|
||||||
changeMode( cmd, modeList );
|
return *this;
|
||||||
else if( cmd == "-t" || cmd == "--test" )
|
}
|
||||||
changeMode( cmd, modeTest );
|
Command& operator += ( const Command& other ) {
|
||||||
else if( cmd == "-r" || cmd == "--reporter" )
|
std::copy( other.m_args.begin(), other.m_args.end(), std::back_inserter( m_args ) );
|
||||||
changeMode( cmd, modeReport );
|
if( m_name.empty() )
|
||||||
else if( cmd == "-o" || cmd == "--out" )
|
m_name = other.m_name;
|
||||||
changeMode( cmd, modeOutput );
|
return *this;
|
||||||
else if( cmd == "-s" || cmd == "--success" )
|
}
|
||||||
changeMode( cmd, modeSuccess );
|
Command operator + ( const Command& other ) {
|
||||||
else if( cmd == "-b" || cmd == "--break" )
|
Command newCommand( *this );
|
||||||
changeMode( cmd, modeBreak );
|
newCommand += other;
|
||||||
else if( cmd == "-n" || cmd == "--name" )
|
return newCommand;
|
||||||
changeMode( cmd, modeName );
|
|
||||||
else if( cmd == "-h" || cmd == "-?" || cmd == "--help" )
|
|
||||||
changeMode( cmd, modeHelp );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_args.push_back( argv[i] );
|
|
||||||
}
|
|
||||||
if( m_mode == modeError )
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
changeMode( "", modeNone );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
operator SafeBool::type() const {
|
||||||
std::string argsAsString() {
|
return SafeBool::makeSafe( !m_name.empty() );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name() const { return m_name; }
|
||||||
|
std::string operator[]( std::size_t i ) const { return m_args[i]; }
|
||||||
|
std::size_t argsCount() const { return m_args.size(); }
|
||||||
|
|
||||||
|
void raiseError( const std::string& message ) const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
std::vector<std::string>::const_iterator it = m_args.begin();
|
oss << "Error while parsing " << m_name << ". " << message << ".";
|
||||||
std::vector<std::string>::const_iterator itEnd = m_args.end();
|
if( m_args.size() > 0 )
|
||||||
for( bool first = true; it != itEnd; ++it, first = false ) {
|
oss << " Arguments where:";
|
||||||
if( !first )
|
for( std::size_t i = 0; i < m_args.size(); ++i )
|
||||||
oss << " ";
|
oss << " " << m_args[i];
|
||||||
oss << *it;
|
throw std::domain_error( oss.str() );
|
||||||
}
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeMode( const std::string& cmd, Mode mode ) {
|
|
||||||
m_command = cmd;
|
|
||||||
switch( m_mode ) {
|
|
||||||
case modeNone:
|
|
||||||
if( m_args.size() > 0 )
|
|
||||||
return setErrorMode( "Unexpected arguments before " + m_command + ": " + argsAsString() );
|
|
||||||
break;
|
|
||||||
case modeList:
|
|
||||||
if( m_args.size() > 2 ) {
|
|
||||||
return setErrorMode( m_command + " expected upto 2 arguments but recieved: " + argsAsString() );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Config::List::What listSpec = Config::List::All;
|
|
||||||
if( m_args.size() >= 1 ) {
|
|
||||||
if( m_args[0] == "tests" )
|
|
||||||
listSpec = Config::List::Tests;
|
|
||||||
else if( m_args[0] == "reporters" )
|
|
||||||
listSpec = Config::List::Reports;
|
|
||||||
else
|
|
||||||
return setErrorMode( m_command + " expected [tests] or [reporters] but recieved: [" + m_args[0] + "]" );
|
|
||||||
}
|
|
||||||
if( m_args.size() >= 2 ) {
|
|
||||||
if( m_args[1] == "xml" )
|
|
||||||
listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsXml );
|
|
||||||
else if( m_args[1] == "text" )
|
|
||||||
listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsText );
|
|
||||||
else
|
|
||||||
return setErrorMode( m_command + " expected [xml] or [text] but recieved: [" + m_args[1] + "]" );
|
|
||||||
}
|
|
||||||
m_config.setListSpec( static_cast<Config::List::What>( m_config.getListSpec() | listSpec ) );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case modeTest:
|
|
||||||
if( m_args.size() == 0 )
|
|
||||||
return setErrorMode( m_command + " expected at least 1 argument but recieved none" );
|
|
||||||
{
|
|
||||||
std::vector<std::string>::const_iterator it = m_args.begin();
|
|
||||||
std::vector<std::string>::const_iterator itEnd = m_args.end();
|
|
||||||
for(; it != itEnd; ++it )
|
|
||||||
m_config.addTestSpec( *it );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case modeReport:
|
|
||||||
if( m_args.size() != 1 )
|
|
||||||
return setErrorMode( m_command + " expected one argument, recieved: " + argsAsString() );
|
|
||||||
m_config.setReporter( m_args[0] );
|
|
||||||
break;
|
|
||||||
case modeOutput:
|
|
||||||
if( m_args.size() == 0 )
|
|
||||||
return setErrorMode( m_command + " expected filename" );
|
|
||||||
if( m_args[0][0] == '%' )
|
|
||||||
m_config.useStream( m_args[0].substr( 1 ) );
|
|
||||||
else
|
|
||||||
m_config.setFilename( m_args[0] );
|
|
||||||
break;
|
|
||||||
case modeSuccess:
|
|
||||||
if( m_args.size() != 0 )
|
|
||||||
return setErrorMode( m_command + " does not accept arguments" );
|
|
||||||
m_config.setIncludeWhat( Config::Include::SuccessfulResults );
|
|
||||||
break;
|
|
||||||
case modeBreak:
|
|
||||||
if( m_args.size() != 0 )
|
|
||||||
return setErrorMode( m_command + " does not accept arguments" );
|
|
||||||
m_config.setShouldDebugBreak( true );
|
|
||||||
break;
|
|
||||||
case modeName:
|
|
||||||
if( m_args.size() != 1 )
|
|
||||||
return setErrorMode( m_command + " requires exactly one argument (a name)" );
|
|
||||||
m_config.setName( m_args[0] );
|
|
||||||
break;
|
|
||||||
case modeHelp:
|
|
||||||
if( m_args.size() != 0 )
|
|
||||||
return setErrorMode( m_command + " does not accept arguments" );
|
|
||||||
m_config.setShowHelp( true );
|
|
||||||
break;
|
|
||||||
case modeError:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
m_args.clear();
|
|
||||||
m_mode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setErrorMode( const std::string& errorMessage ) {
|
|
||||||
m_mode = modeError;
|
|
||||||
m_command = "";
|
|
||||||
m_config.setError( errorMessage );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Mode m_mode;
|
std::string m_name;
|
||||||
std::string m_command;
|
|
||||||
std::vector<std::string> m_args;
|
std::vector<std::string> m_args;
|
||||||
Config& m_config;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CommandParser {
|
||||||
|
public:
|
||||||
|
CommandParser( int argc, char const * const * argv ) : m_argc( argc ), m_argv( argv ) {}
|
||||||
|
|
||||||
|
Command find( const std::string& arg1, const std::string& arg2, const std::string& arg3 ) const {
|
||||||
|
return find( arg1 ) + find( arg2 ) + find( arg3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Command find( const std::string& shortArg, const std::string& longArg ) const {
|
||||||
|
return find( shortArg ) + find( longArg );
|
||||||
|
}
|
||||||
|
Command find( const std::string& arg ) const {
|
||||||
|
for( std::size_t i = 0; i < m_argc; ++i )
|
||||||
|
if( m_argv[i] == arg )
|
||||||
|
return getArgs( i );
|
||||||
|
return Command();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Command getArgs( std::size_t from ) const {
|
||||||
|
Command command( m_argv[from] );
|
||||||
|
for( std::size_t i = from+1; i < m_argc && m_argv[i][0] != '-'; ++i )
|
||||||
|
command += m_argv[i];
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
int m_argc;
|
||||||
|
char const * const * m_argv;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool parseIntoConfig( const CommandParser& parser, Config& config ) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if( Command cmd = parser.find( "-l", "--list" ) ) {
|
||||||
|
if( cmd.argsCount() > 2 )
|
||||||
|
throw std::domain_error( cmd.name() + " expected upto 2 arguments but recieved: " );
|
||||||
|
|
||||||
|
List::What listSpec = List::All;
|
||||||
|
if( cmd.argsCount() >= 1 ) {
|
||||||
|
if( cmd[0] == "tests" )
|
||||||
|
listSpec = List::Tests;
|
||||||
|
else if( cmd[0] == "reporters" )
|
||||||
|
listSpec = List::Reports;
|
||||||
|
else
|
||||||
|
throw std::domain_error( cmd.name() + " expected [tests] or [reporters] but recieved: : " );
|
||||||
|
}
|
||||||
|
if( cmd.argsCount() >= 2 ) {
|
||||||
|
if( cmd[1] == "xml" )
|
||||||
|
listSpec = static_cast<List::What>( listSpec | List::AsXml );
|
||||||
|
else if( cmd[1] == "text" )
|
||||||
|
listSpec = static_cast<List::What>( listSpec | List::AsText );
|
||||||
|
else
|
||||||
|
throw std::domain_error( cmd.name() + " expected [xml] or [text] but recieved: " );
|
||||||
|
}
|
||||||
|
config.setListSpec( static_cast<List::What>( config.getListSpec() | listSpec ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-t", "--test" ) ) {
|
||||||
|
if( cmd.argsCount() == 0 )
|
||||||
|
throw std::domain_error( cmd.name() + " expected at least 1 argument but recieved none" );
|
||||||
|
for( std::size_t i = 0; i < cmd.argsCount(); ++i )
|
||||||
|
config.addTestSpec( cmd[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-r", "--reporter" ) ) {
|
||||||
|
if( cmd.argsCount() != 1 )
|
||||||
|
cmd.raiseError( "Expected one argument" );
|
||||||
|
config.setReporter( cmd[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-o", "--out" ) ) {
|
||||||
|
if( cmd.argsCount() == 0 )
|
||||||
|
throw std::domain_error( cmd.name() + " expected filename" );
|
||||||
|
if( cmd[0][0] == '%' )
|
||||||
|
config.useStream( cmd[0].substr( 1 ) );
|
||||||
|
else
|
||||||
|
config.setFilename( cmd[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-s", "--success" ) ) {
|
||||||
|
if( cmd.argsCount() != 0 )
|
||||||
|
throw std::domain_error( cmd.name() + " does not accept arguments" );
|
||||||
|
config.setIncludeWhichResults( Include::SuccessfulResults );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-b", "--break" ) ) {
|
||||||
|
if( cmd.argsCount() != 0 )
|
||||||
|
throw std::domain_error( cmd.name() + " does not accept arguments" );
|
||||||
|
config.setShouldDebugBreak( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-n", "--name" ) ) {
|
||||||
|
if( cmd.argsCount() != 1 )
|
||||||
|
throw std::domain_error( cmd.name() + " requires exactly one argument (a name)" );
|
||||||
|
config.setName( cmd[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-h", "-?", "--help" ) ) {
|
||||||
|
if( cmd.argsCount() != 0 )
|
||||||
|
throw std::domain_error( cmd.name() + " does not accept arguments" );
|
||||||
|
config.setShowHelp( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( std::exception& ex ) {
|
||||||
|
config.setError( ex.what() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
|
@ -35,6 +35,17 @@ namespace Catch {
|
|||||||
virtual ~NonCopyable() {}
|
virtual ~NonCopyable() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SafeBool {
|
||||||
|
public:
|
||||||
|
typedef void (SafeBool::*type)() const;
|
||||||
|
|
||||||
|
static type makeSafe( bool value ) {
|
||||||
|
return value ? &SafeBool::trueValue : 0;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void trueValue() const {}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename ContainerT>
|
template<typename ContainerT>
|
||||||
inline void deleteAll( ContainerT& container ) {
|
inline void deleteAll( ContainerT& container ) {
|
||||||
typename ContainerT::const_iterator it = container.begin();
|
typename ContainerT::const_iterator it = container.begin();
|
||||||
|
@ -18,40 +18,39 @@
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
struct Include { enum WhichResults {
|
||||||
|
FailedOnly,
|
||||||
|
SuccessfulResults
|
||||||
|
}; };
|
||||||
|
|
||||||
|
struct List{ enum What {
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
Reports = 1,
|
||||||
|
Tests = 2,
|
||||||
|
All = 3,
|
||||||
|
|
||||||
|
WhatMask = 0xf,
|
||||||
|
|
||||||
|
AsText = 0x10,
|
||||||
|
AsXml = 0x11,
|
||||||
|
|
||||||
|
AsMask = 0xf0
|
||||||
|
}; };
|
||||||
|
|
||||||
class Config : public IReporterConfig {
|
class Config : public IReporterConfig {
|
||||||
private:
|
private:
|
||||||
Config( const Config& other );
|
Config( const Config& other );
|
||||||
Config& operator = ( const Config& other );
|
Config& operator = ( const Config& other );
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct Include { enum What {
|
|
||||||
FailedOnly,
|
|
||||||
SuccessfulResults
|
|
||||||
}; };
|
|
||||||
|
|
||||||
struct List{ enum What {
|
|
||||||
None = 0,
|
|
||||||
|
|
||||||
Reports = 1,
|
|
||||||
Tests = 2,
|
|
||||||
All = 3,
|
|
||||||
|
|
||||||
WhatMask = 0xf,
|
|
||||||
|
|
||||||
AsText = 0x10,
|
|
||||||
AsXml = 0x11,
|
|
||||||
|
|
||||||
AsMask = 0xf0
|
|
||||||
}; };
|
|
||||||
|
|
||||||
|
|
||||||
Config()
|
Config()
|
||||||
: m_listSpec( List::None ),
|
: m_listSpec( List::None ),
|
||||||
m_shouldDebugBreak( false ),
|
m_shouldDebugBreak( false ),
|
||||||
m_showHelp( false ),
|
m_showHelp( false ),
|
||||||
m_streambuf( NULL ),
|
m_streambuf( NULL ),
|
||||||
m_os( std::cout.rdbuf() ),
|
m_os( std::cout.rdbuf() ),
|
||||||
m_includeWhat( Include::FailedOnly )
|
m_includeWhichResults( Include::FailedOnly )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~Config() {
|
~Config() {
|
||||||
@ -98,7 +97,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setError( const std::string& errorMessage ) {
|
void setError( const std::string& errorMessage ) {
|
||||||
m_message = errorMessage + "\n\n" + "Usage: ...";
|
m_message = errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setReporter( IReporter* reporter ) {
|
void setReporter( IReporter* reporter ) {
|
||||||
@ -119,8 +118,8 @@ namespace Catch {
|
|||||||
return static_cast<List::What>( m_listSpec & List::AsMask );
|
return static_cast<List::What>( m_listSpec & List::AsMask );
|
||||||
}
|
}
|
||||||
|
|
||||||
void setIncludeWhat( Include::What includeWhat ) {
|
void setIncludeWhichResults( Include::WhichResults includeWhichResults ) {
|
||||||
m_includeWhat = includeWhat;
|
m_includeWhichResults = includeWhichResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setShouldDebugBreak( bool shouldDebugBreakFlag ) {
|
void setShouldDebugBreak( bool shouldDebugBreakFlag ) {
|
||||||
@ -163,7 +162,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual bool includeSuccessfulResults() const {
|
virtual bool includeSuccessfulResults() const {
|
||||||
return m_includeWhat == Include::SuccessfulResults;
|
return m_includeWhichResults == Include::SuccessfulResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -176,10 +175,23 @@ namespace Catch {
|
|||||||
bool m_showHelp;
|
bool m_showHelp;
|
||||||
std::streambuf* m_streambuf;
|
std::streambuf* m_streambuf;
|
||||||
mutable std::ostream m_os;
|
mutable std::ostream m_os;
|
||||||
Include::What m_includeWhat;
|
Include::WhichResults m_includeWhichResults;
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NewConfig {
|
||||||
|
std::string reporter;
|
||||||
|
std::string outputFilename;
|
||||||
|
List::What listSpec;
|
||||||
|
std::vector<std::string> testSpecs;
|
||||||
|
bool shouldDebugBreak;
|
||||||
|
bool showHelp;
|
||||||
|
Include::WhichResults includeWhichResults;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
|
||||||
|
@ -15,7 +15,7 @@ namespace Catch {
|
|||||||
inline int List( Config& config ) {
|
inline int List( Config& config ) {
|
||||||
|
|
||||||
IContext& context = getCurrentContext();
|
IContext& context = getCurrentContext();
|
||||||
if( config.listWhat() & Config::List::Reports ) {
|
if( config.listWhat() & List::Reports ) {
|
||||||
std::cout << "Available reports:\n";
|
std::cout << "Available reports:\n";
|
||||||
IReporterRegistry::FactoryMap::const_iterator it = context.getReporterRegistry().getFactories().begin();
|
IReporterRegistry::FactoryMap::const_iterator it = context.getReporterRegistry().getFactories().begin();
|
||||||
IReporterRegistry::FactoryMap::const_iterator itEnd = context.getReporterRegistry().getFactories().end();
|
IReporterRegistry::FactoryMap::const_iterator itEnd = context.getReporterRegistry().getFactories().end();
|
||||||
@ -26,7 +26,7 @@ namespace Catch {
|
|||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( config.listWhat() & Config::List::Tests ) {
|
if( config.listWhat() & List::Tests ) {
|
||||||
std::cout << "Available tests:\n";
|
std::cout << "Available tests:\n";
|
||||||
std::vector<TestCaseInfo>::const_iterator it = context.getTestCaseRegistry().getAllTests().begin();
|
std::vector<TestCaseInfo>::const_iterator it = context.getTestCaseRegistry().getAllTests().begin();
|
||||||
std::vector<TestCaseInfo>::const_iterator itEnd = context.getTestCaseRegistry().getAllTests().end();
|
std::vector<TestCaseInfo>::const_iterator itEnd = context.getTestCaseRegistry().getAllTests().end();
|
||||||
@ -37,7 +37,7 @@ namespace Catch {
|
|||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( config.listWhat() & Config::List::All ) == 0 ) {
|
if( ( config.listWhat() & List::All ) == 0 ) {
|
||||||
std::cerr << "Unknown list type" << std::endl;
|
std::cerr << "Unknown list type" << std::endl;
|
||||||
return (std::numeric_limits<int>::max)();
|
return (std::numeric_limits<int>::max)();
|
||||||
}
|
}
|
||||||
|
@ -316,8 +316,6 @@ namespace Catch {
|
|||||||
std::vector<SpanInfo> m_sectionSpans;
|
std::vector<SpanInfo> m_sectionSpans;
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
|
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
|
||||||
|
@ -218,8 +218,6 @@ namespace Catch {
|
|||||||
std::ostringstream m_stdErr;
|
std::ostringstream m_stdErr;
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
|
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
|
||||||
|
@ -134,8 +134,6 @@ namespace Catch {
|
|||||||
XmlWriter m_xml;
|
XmlWriter m_xml;
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
|
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
|
||||||
|
@ -280,3 +280,18 @@ TEST_CASE("./succeeding/matchers/Equals", "")
|
|||||||
{
|
{
|
||||||
CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) );
|
CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline unsigned int Factorial( unsigned int number )
|
||||||
|
{
|
||||||
|
// return number <= 1 ? number : Factorial(number-1)*number;
|
||||||
|
return number > 1 ? Factorial(number-1)*number : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "example/factorial", "The Factorial function should return the factorial of the number passed in" )
|
||||||
|
{
|
||||||
|
REQUIRE( Factorial(0) == 1 );
|
||||||
|
REQUIRE( Factorial(1) == 1 );
|
||||||
|
REQUIRE( Factorial(2) == 2 );
|
||||||
|
REQUIRE( Factorial(3) == 6 );
|
||||||
|
REQUIRE( Factorial(10) == 3628800 );
|
||||||
|
}
|
||||||
|
@ -53,3 +53,151 @@ TEST_CASE( "meta/Misc/Sections", "looped tests" ) {
|
|||||||
CHECK( runner.getTotals().assertions.passed == 2 );
|
CHECK( runner.getTotals().assertions.passed == 2 );
|
||||||
CHECK( runner.getTotals().assertions.failed == 1 );
|
CHECK( runner.getTotals().assertions.failed == 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "catch_commandline.hpp"
|
||||||
|
#include "catch_reporter_basic.hpp"
|
||||||
|
#include "catch_reporter_xml.hpp"
|
||||||
|
#include "catch_reporter_junit.hpp"
|
||||||
|
|
||||||
|
template<size_t size>
|
||||||
|
bool parseIntoConfig( const char * (&argv)[size], Catch::Config& config ) {
|
||||||
|
return Catch::parseIntoConfig( Catch::CommandParser( size, argv ), config );
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE( "selftest/parser", "" ) {
|
||||||
|
|
||||||
|
SECTION( "default", "" ) {
|
||||||
|
const char* argv[] = { "test" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) );
|
||||||
|
|
||||||
|
CHECK( config.getTestSpecs().empty() );
|
||||||
|
CHECK( config.shouldDebugBreak() == false );
|
||||||
|
CHECK( config.showHelp() == false );
|
||||||
|
CHECK( dynamic_cast<Catch::BasicReporter*>( config.getReporter().get() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION( "test lists", "" ) {
|
||||||
|
SECTION( "-t/1", "Specify one test case using -t" ) {
|
||||||
|
const char* argv[] = { "test", "-t", "test1" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) );
|
||||||
|
|
||||||
|
REQUIRE( config.getTestSpecs().size() == 1 );
|
||||||
|
REQUIRE( config.getTestSpecs()[0] == "test1" );
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION( "--test/1", "Specify one test case using --test" ) {
|
||||||
|
const char* argv[] = { "test", "--test", "test1" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) );
|
||||||
|
|
||||||
|
REQUIRE( config.getTestSpecs().size() == 1 );
|
||||||
|
REQUIRE( config.getTestSpecs()[0] == "test1" );
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION( "-t/2", "Specify two test cases using -t" ) {
|
||||||
|
const char* argv[] = { "test", "-t", "test1", "test2" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) );
|
||||||
|
|
||||||
|
REQUIRE( config.getTestSpecs().size() == 2 );
|
||||||
|
REQUIRE( config.getTestSpecs()[0] == "test1" );
|
||||||
|
REQUIRE( config.getTestSpecs()[1] == "test2" );
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION( "-t/0", "When no test names are supplied it is an error" ) {
|
||||||
|
const char* argv[] = { "test", "-t" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) == false );
|
||||||
|
|
||||||
|
REQUIRE_THAT( config.getMessage(), Contains( "none" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION( "reporter", "" ) {
|
||||||
|
SECTION( "-r/basic", "" ) {
|
||||||
|
const char* argv[] = { "test", "-reporter", "basic" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) );
|
||||||
|
|
||||||
|
REQUIRE( dynamic_cast<Catch::BasicReporter*>( config.getReporter().get() ) );
|
||||||
|
}
|
||||||
|
SECTION( "-r/xml", "" ) {
|
||||||
|
const char* argv[] = { "test", "-r", "xml" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) );
|
||||||
|
|
||||||
|
REQUIRE( dynamic_cast<Catch::XmlReporter*>( config.getReporter().get() ) );
|
||||||
|
}
|
||||||
|
SECTION( "-r/junit", "" ) {
|
||||||
|
const char* argv[] = { "test", "-r", "junit" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) );
|
||||||
|
|
||||||
|
REQUIRE( dynamic_cast<Catch::JunitReporter*>( config.getReporter().get() ) );
|
||||||
|
}
|
||||||
|
SECTION( "-r/error", "reporter config only accepts one argument" ) {
|
||||||
|
const char* argv[] = { "test", "-r", "one", "two" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) == false );
|
||||||
|
|
||||||
|
REQUIRE_THAT( config.getMessage(), Contains( "one argument" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION( "debugger", "" ) {
|
||||||
|
SECTION( "-b", "" ) {
|
||||||
|
const char* argv[] = { "test", "-b" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) );
|
||||||
|
|
||||||
|
REQUIRE( config.shouldDebugBreak() == true );
|
||||||
|
}
|
||||||
|
SECTION( "--break", "" ) {
|
||||||
|
const char* argv[] = { "test", "--break" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) );
|
||||||
|
|
||||||
|
REQUIRE( config.shouldDebugBreak() );
|
||||||
|
}
|
||||||
|
SECTION( "-b", "break option has no arguments" ) {
|
||||||
|
const char* argv[] = { "test", "-b", "unexpected" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) == false );
|
||||||
|
|
||||||
|
REQUIRE_THAT( config.getMessage(), Contains( "not accept" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION( "help", "" ) {
|
||||||
|
SECTION( "-h", "" ) {
|
||||||
|
const char* argv[] = { "test", "-h" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) );
|
||||||
|
|
||||||
|
REQUIRE( config.showHelp() );
|
||||||
|
}
|
||||||
|
SECTION( "-?", "" ) {
|
||||||
|
const char* argv[] = { "test", "-?" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) );
|
||||||
|
|
||||||
|
REQUIRE( config.showHelp() );
|
||||||
|
}
|
||||||
|
SECTION( "--help", "" ) {
|
||||||
|
const char* argv[] = { "test", "--help" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) );
|
||||||
|
|
||||||
|
REQUIRE( config.showHelp() );
|
||||||
|
}
|
||||||
|
SECTION( "-h", "help option has no arguments" ) {
|
||||||
|
const char* argv[] = { "test", "-h", "unexpected" };
|
||||||
|
Catch::Config config;
|
||||||
|
CHECK( parseIntoConfig( argv, config ) == false );
|
||||||
|
|
||||||
|
REQUIRE_THAT( config.getMessage(), Contains( "not accept" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Generated: 2012-05-25 08:50:58.340151
|
* Generated: 2012-05-31 19:40:06.141562
|
||||||
* ----------------------------------------------------------
|
* ----------------------------------------------------------
|
||||||
* 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.
|
||||||
@ -41,6 +41,17 @@ namespace Catch {
|
|||||||
virtual ~NonCopyable() {}
|
virtual ~NonCopyable() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SafeBool {
|
||||||
|
public:
|
||||||
|
typedef void (SafeBool::*type)() const;
|
||||||
|
|
||||||
|
static type makeSafe( bool value ) {
|
||||||
|
return value ? &SafeBool::trueValue : 0;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void trueValue() const {}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename ContainerT>
|
template<typename ContainerT>
|
||||||
inline void deleteAll( ContainerT& container ) {
|
inline void deleteAll( ContainerT& container ) {
|
||||||
typename ContainerT::const_iterator it = container.begin();
|
typename ContainerT::const_iterator it = container.begin();
|
||||||
@ -2358,39 +2369,39 @@ namespace Catch {
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
struct Include { enum WhichResults {
|
||||||
|
FailedOnly,
|
||||||
|
SuccessfulResults
|
||||||
|
}; };
|
||||||
|
|
||||||
|
struct List{ enum What {
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
Reports = 1,
|
||||||
|
Tests = 2,
|
||||||
|
All = 3,
|
||||||
|
|
||||||
|
WhatMask = 0xf,
|
||||||
|
|
||||||
|
AsText = 0x10,
|
||||||
|
AsXml = 0x11,
|
||||||
|
|
||||||
|
AsMask = 0xf0
|
||||||
|
}; };
|
||||||
|
|
||||||
class Config : public IReporterConfig {
|
class Config : public IReporterConfig {
|
||||||
private:
|
private:
|
||||||
Config( const Config& other );
|
Config( const Config& other );
|
||||||
Config& operator = ( const Config& other );
|
Config& operator = ( const Config& other );
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct Include { enum What {
|
|
||||||
FailedOnly,
|
|
||||||
SuccessfulResults
|
|
||||||
}; };
|
|
||||||
|
|
||||||
struct List{ enum What {
|
|
||||||
None = 0,
|
|
||||||
|
|
||||||
Reports = 1,
|
|
||||||
Tests = 2,
|
|
||||||
All = 3,
|
|
||||||
|
|
||||||
WhatMask = 0xf,
|
|
||||||
|
|
||||||
AsText = 0x10,
|
|
||||||
AsXml = 0x11,
|
|
||||||
|
|
||||||
AsMask = 0xf0
|
|
||||||
}; };
|
|
||||||
|
|
||||||
Config()
|
Config()
|
||||||
: m_listSpec( List::None ),
|
: m_listSpec( List::None ),
|
||||||
m_shouldDebugBreak( false ),
|
m_shouldDebugBreak( false ),
|
||||||
m_showHelp( false ),
|
m_showHelp( false ),
|
||||||
m_streambuf( NULL ),
|
m_streambuf( NULL ),
|
||||||
m_os( std::cout.rdbuf() ),
|
m_os( std::cout.rdbuf() ),
|
||||||
m_includeWhat( Include::FailedOnly )
|
m_includeWhichResults( Include::FailedOnly )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
~Config() {
|
~Config() {
|
||||||
@ -2437,7 +2448,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setError( const std::string& errorMessage ) {
|
void setError( const std::string& errorMessage ) {
|
||||||
m_message = errorMessage + "\n\n" + "Usage: ...";
|
m_message = errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setReporter( IReporter* reporter ) {
|
void setReporter( IReporter* reporter ) {
|
||||||
@ -2458,8 +2469,8 @@ namespace Catch {
|
|||||||
return static_cast<List::What>( m_listSpec & List::AsMask );
|
return static_cast<List::What>( m_listSpec & List::AsMask );
|
||||||
}
|
}
|
||||||
|
|
||||||
void setIncludeWhat( Include::What includeWhat ) {
|
void setIncludeWhichResults( Include::WhichResults includeWhichResults ) {
|
||||||
m_includeWhat = includeWhat;
|
m_includeWhichResults = includeWhichResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setShouldDebugBreak( bool shouldDebugBreakFlag ) {
|
void setShouldDebugBreak( bool shouldDebugBreakFlag ) {
|
||||||
@ -2502,7 +2513,7 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual bool includeSuccessfulResults() const {
|
virtual bool includeSuccessfulResults() const {
|
||||||
return m_includeWhat == Include::SuccessfulResults;
|
return m_includeWhichResults == Include::SuccessfulResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -2515,10 +2526,21 @@ namespace Catch {
|
|||||||
bool m_showHelp;
|
bool m_showHelp;
|
||||||
std::streambuf* m_streambuf;
|
std::streambuf* m_streambuf;
|
||||||
mutable std::ostream m_os;
|
mutable std::ostream m_os;
|
||||||
Include::What m_includeWhat;
|
Include::WhichResults m_includeWhichResults;
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NewConfig {
|
||||||
|
std::string reporter;
|
||||||
|
std::string outputFilename;
|
||||||
|
List::What listSpec;
|
||||||
|
std::vector<std::string> testSpecs;
|
||||||
|
bool shouldDebugBreak;
|
||||||
|
bool showHelp;
|
||||||
|
Include::WhichResults includeWhichResults;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
// #included from: catch_running_test.hpp
|
// #included from: catch_running_test.hpp
|
||||||
@ -3394,175 +3416,163 @@ namespace Catch {
|
|||||||
// #included from: internal/catch_commandline.hpp
|
// #included from: internal/catch_commandline.hpp
|
||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
// -l, --list tests [xml] lists available tests (optionally in xml)
|
|
||||||
// -l, --list reporters [xml] lists available reports (optionally in xml)
|
|
||||||
// -l, --list all [xml] lists available tests and reports (optionally in xml)
|
|
||||||
// -t, --test "testspec" ["testspec", ...]
|
|
||||||
// -r, --reporter <type>
|
|
||||||
// -o, --out filename to write to
|
|
||||||
// -s, --success report successful cases too
|
|
||||||
// -b, --break breaks into debugger on test failure
|
|
||||||
// -n, --name specifies an optional name for the test run
|
|
||||||
class ArgParser : NonCopyable {
|
|
||||||
|
|
||||||
enum Mode {
|
|
||||||
modeNone,
|
|
||||||
modeList,
|
|
||||||
modeTest,
|
|
||||||
modeReport,
|
|
||||||
modeOutput,
|
|
||||||
modeSuccess,
|
|
||||||
modeBreak,
|
|
||||||
modeName,
|
|
||||||
modeHelp,
|
|
||||||
|
|
||||||
modeError
|
|
||||||
};
|
|
||||||
|
|
||||||
|
class Command {
|
||||||
public:
|
public:
|
||||||
ArgParser ( int argc, char * const argv[], Config& config )
|
Command(){}
|
||||||
: m_mode( modeNone ),
|
|
||||||
m_config( config ) {
|
|
||||||
|
|
||||||
for( int i=1; i < argc; ++i ) {
|
Command( const std::string& name ) : m_name( name ) {}
|
||||||
if( argv[i][0] == '-' ) {
|
|
||||||
std::string cmd = ( argv[i] );
|
Command& operator += ( const std::string& arg ) {
|
||||||
if( cmd == "-l" || cmd == "--list" )
|
m_args.push_back( arg );
|
||||||
changeMode( cmd, modeList );
|
return *this;
|
||||||
else if( cmd == "-t" || cmd == "--test" )
|
}
|
||||||
changeMode( cmd, modeTest );
|
Command& operator += ( const Command& other ) {
|
||||||
else if( cmd == "-r" || cmd == "--reporter" )
|
std::copy( other.m_args.begin(), other.m_args.end(), std::back_inserter( m_args ) );
|
||||||
changeMode( cmd, modeReport );
|
if( m_name.empty() )
|
||||||
else if( cmd == "-o" || cmd == "--out" )
|
m_name = other.m_name;
|
||||||
changeMode( cmd, modeOutput );
|
return *this;
|
||||||
else if( cmd == "-s" || cmd == "--success" )
|
}
|
||||||
changeMode( cmd, modeSuccess );
|
Command operator + ( const Command& other ) {
|
||||||
else if( cmd == "-b" || cmd == "--break" )
|
Command newCommand( *this );
|
||||||
changeMode( cmd, modeBreak );
|
newCommand += other;
|
||||||
else if( cmd == "-n" || cmd == "--name" )
|
return newCommand;
|
||||||
changeMode( cmd, modeName );
|
|
||||||
else if( cmd == "-h" || cmd == "-?" || cmd == "--help" )
|
|
||||||
changeMode( cmd, modeHelp );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_args.push_back( argv[i] );
|
|
||||||
}
|
|
||||||
if( m_mode == modeError )
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
changeMode( "", modeNone );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
operator SafeBool::type() const {
|
||||||
std::string argsAsString() {
|
return SafeBool::makeSafe( !m_name.empty() );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name() const { return m_name; }
|
||||||
|
std::string operator[]( std::size_t i ) const { return m_args[i]; }
|
||||||
|
std::size_t argsCount() const { return m_args.size(); }
|
||||||
|
|
||||||
|
void raiseError( const std::string& message ) const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
std::vector<std::string>::const_iterator it = m_args.begin();
|
oss << "Error while parsing " << m_name << ". " << message << ".";
|
||||||
std::vector<std::string>::const_iterator itEnd = m_args.end();
|
if( m_args.size() > 0 )
|
||||||
for( bool first = true; it != itEnd; ++it, first = false ) {
|
oss << " Arguments where:";
|
||||||
if( !first )
|
for( std::size_t i = 0; i < m_args.size(); ++i )
|
||||||
oss << " ";
|
oss << " " << m_args[i];
|
||||||
oss << *it;
|
throw std::domain_error( oss.str() );
|
||||||
}
|
|
||||||
return oss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void changeMode( const std::string& cmd, Mode mode ) {
|
|
||||||
m_command = cmd;
|
|
||||||
switch( m_mode ) {
|
|
||||||
case modeNone:
|
|
||||||
if( m_args.size() > 0 )
|
|
||||||
return setErrorMode( "Unexpected arguments before " + m_command + ": " + argsAsString() );
|
|
||||||
break;
|
|
||||||
case modeList:
|
|
||||||
if( m_args.size() > 2 ) {
|
|
||||||
return setErrorMode( m_command + " expected upto 2 arguments but recieved: " + argsAsString() );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Config::List::What listSpec = Config::List::All;
|
|
||||||
if( m_args.size() >= 1 ) {
|
|
||||||
if( m_args[0] == "tests" )
|
|
||||||
listSpec = Config::List::Tests;
|
|
||||||
else if( m_args[0] == "reporters" )
|
|
||||||
listSpec = Config::List::Reports;
|
|
||||||
else
|
|
||||||
return setErrorMode( m_command + " expected [tests] or [reporters] but recieved: [" + m_args[0] + "]" );
|
|
||||||
}
|
|
||||||
if( m_args.size() >= 2 ) {
|
|
||||||
if( m_args[1] == "xml" )
|
|
||||||
listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsXml );
|
|
||||||
else if( m_args[1] == "text" )
|
|
||||||
listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsText );
|
|
||||||
else
|
|
||||||
return setErrorMode( m_command + " expected [xml] or [text] but recieved: [" + m_args[1] + "]" );
|
|
||||||
}
|
|
||||||
m_config.setListSpec( static_cast<Config::List::What>( m_config.getListSpec() | listSpec ) );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case modeTest:
|
|
||||||
if( m_args.size() == 0 )
|
|
||||||
return setErrorMode( m_command + " expected at least 1 argument but recieved none" );
|
|
||||||
{
|
|
||||||
std::vector<std::string>::const_iterator it = m_args.begin();
|
|
||||||
std::vector<std::string>::const_iterator itEnd = m_args.end();
|
|
||||||
for(; it != itEnd; ++it )
|
|
||||||
m_config.addTestSpec( *it );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case modeReport:
|
|
||||||
if( m_args.size() != 1 )
|
|
||||||
return setErrorMode( m_command + " expected one argument, recieved: " + argsAsString() );
|
|
||||||
m_config.setReporter( m_args[0] );
|
|
||||||
break;
|
|
||||||
case modeOutput:
|
|
||||||
if( m_args.size() == 0 )
|
|
||||||
return setErrorMode( m_command + " expected filename" );
|
|
||||||
if( m_args[0][0] == '%' )
|
|
||||||
m_config.useStream( m_args[0].substr( 1 ) );
|
|
||||||
else
|
|
||||||
m_config.setFilename( m_args[0] );
|
|
||||||
break;
|
|
||||||
case modeSuccess:
|
|
||||||
if( m_args.size() != 0 )
|
|
||||||
return setErrorMode( m_command + " does not accept arguments" );
|
|
||||||
m_config.setIncludeWhat( Config::Include::SuccessfulResults );
|
|
||||||
break;
|
|
||||||
case modeBreak:
|
|
||||||
if( m_args.size() != 0 )
|
|
||||||
return setErrorMode( m_command + " does not accept arguments" );
|
|
||||||
m_config.setShouldDebugBreak( true );
|
|
||||||
break;
|
|
||||||
case modeName:
|
|
||||||
if( m_args.size() != 1 )
|
|
||||||
return setErrorMode( m_command + " requires exactly one argument (a name)" );
|
|
||||||
m_config.setName( m_args[0] );
|
|
||||||
break;
|
|
||||||
case modeHelp:
|
|
||||||
if( m_args.size() != 0 )
|
|
||||||
return setErrorMode( m_command + " does not accept arguments" );
|
|
||||||
m_config.setShowHelp( true );
|
|
||||||
break;
|
|
||||||
case modeError:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
m_args.clear();
|
|
||||||
m_mode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setErrorMode( const std::string& errorMessage ) {
|
|
||||||
m_mode = modeError;
|
|
||||||
m_command = "";
|
|
||||||
m_config.setError( errorMessage );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Mode m_mode;
|
std::string m_name;
|
||||||
std::string m_command;
|
|
||||||
std::vector<std::string> m_args;
|
std::vector<std::string> m_args;
|
||||||
Config& m_config;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CommandParser {
|
||||||
|
public:
|
||||||
|
CommandParser( int argc, char const * const * argv ) : m_argc( argc ), m_argv( argv ) {}
|
||||||
|
|
||||||
|
Command find( const std::string& arg1, const std::string& arg2, const std::string& arg3 ) const {
|
||||||
|
return find( arg1 ) + find( arg2 ) + find( arg3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
Command find( const std::string& shortArg, const std::string& longArg ) const {
|
||||||
|
return find( shortArg ) + find( longArg );
|
||||||
|
}
|
||||||
|
Command find( const std::string& arg ) const {
|
||||||
|
for( std::size_t i = 0; i < m_argc; ++i )
|
||||||
|
if( m_argv[i] == arg )
|
||||||
|
return getArgs( i );
|
||||||
|
return Command();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Command getArgs( std::size_t from ) const {
|
||||||
|
Command command( m_argv[from] );
|
||||||
|
for( std::size_t i = from+1; i < m_argc && m_argv[i][0] != '-'; ++i )
|
||||||
|
command += m_argv[i];
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
int m_argc;
|
||||||
|
char const * const * m_argv;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool parseIntoConfig( const CommandParser& parser, Config& config ) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if( Command cmd = parser.find( "-l", "--list" ) ) {
|
||||||
|
if( cmd.argsCount() > 2 )
|
||||||
|
throw std::domain_error( cmd.name() + " expected upto 2 arguments but recieved: " );
|
||||||
|
|
||||||
|
List::What listSpec = List::All;
|
||||||
|
if( cmd.argsCount() >= 1 ) {
|
||||||
|
if( cmd[0] == "tests" )
|
||||||
|
listSpec = List::Tests;
|
||||||
|
else if( cmd[0] == "reporters" )
|
||||||
|
listSpec = List::Reports;
|
||||||
|
else
|
||||||
|
throw std::domain_error( cmd.name() + " expected [tests] or [reporters] but recieved: : " );
|
||||||
|
}
|
||||||
|
if( cmd.argsCount() >= 2 ) {
|
||||||
|
if( cmd[1] == "xml" )
|
||||||
|
listSpec = static_cast<List::What>( listSpec | List::AsXml );
|
||||||
|
else if( cmd[1] == "text" )
|
||||||
|
listSpec = static_cast<List::What>( listSpec | List::AsText );
|
||||||
|
else
|
||||||
|
throw std::domain_error( cmd.name() + " expected [xml] or [text] but recieved: " );
|
||||||
|
}
|
||||||
|
config.setListSpec( static_cast<List::What>( config.getListSpec() | listSpec ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-t", "--test" ) ) {
|
||||||
|
if( cmd.argsCount() == 0 )
|
||||||
|
throw std::domain_error( cmd.name() + " expected at least 1 argument but recieved none" );
|
||||||
|
for( std::size_t i = 0; i < cmd.argsCount(); ++i )
|
||||||
|
config.addTestSpec( cmd[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-r", "--reporter" ) ) {
|
||||||
|
if( cmd.argsCount() != 1 )
|
||||||
|
cmd.raiseError( "Expected one argument" );
|
||||||
|
config.setReporter( cmd[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-o", "--out" ) ) {
|
||||||
|
if( cmd.argsCount() == 0 )
|
||||||
|
throw std::domain_error( cmd.name() + " expected filename" );
|
||||||
|
if( cmd[0][0] == '%' )
|
||||||
|
config.useStream( cmd[0].substr( 1 ) );
|
||||||
|
else
|
||||||
|
config.setFilename( cmd[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-s", "--success" ) ) {
|
||||||
|
if( cmd.argsCount() != 0 )
|
||||||
|
throw std::domain_error( cmd.name() + " does not accept arguments" );
|
||||||
|
config.setIncludeWhichResults( Include::SuccessfulResults );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-b", "--break" ) ) {
|
||||||
|
if( cmd.argsCount() != 0 )
|
||||||
|
throw std::domain_error( cmd.name() + " does not accept arguments" );
|
||||||
|
config.setShouldDebugBreak( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-n", "--name" ) ) {
|
||||||
|
if( cmd.argsCount() != 1 )
|
||||||
|
throw std::domain_error( cmd.name() + " requires exactly one argument (a name)" );
|
||||||
|
config.setName( cmd[0] );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Command cmd = parser.find( "-h", "-?", "--help" ) ) {
|
||||||
|
if( cmd.argsCount() != 0 )
|
||||||
|
throw std::domain_error( cmd.name() + " does not accept arguments" );
|
||||||
|
config.setShowHelp( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( std::exception& ex ) {
|
||||||
|
config.setError( ex.what() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
// #included from: internal/catch_list.hpp
|
// #included from: internal/catch_list.hpp
|
||||||
@ -3573,7 +3583,7 @@ namespace Catch {
|
|||||||
inline int List( Config& config ) {
|
inline int List( Config& config ) {
|
||||||
|
|
||||||
IContext& context = getCurrentContext();
|
IContext& context = getCurrentContext();
|
||||||
if( config.listWhat() & Config::List::Reports ) {
|
if( config.listWhat() & List::Reports ) {
|
||||||
std::cout << "Available reports:\n";
|
std::cout << "Available reports:\n";
|
||||||
IReporterRegistry::FactoryMap::const_iterator it = context.getReporterRegistry().getFactories().begin();
|
IReporterRegistry::FactoryMap::const_iterator it = context.getReporterRegistry().getFactories().begin();
|
||||||
IReporterRegistry::FactoryMap::const_iterator itEnd = context.getReporterRegistry().getFactories().end();
|
IReporterRegistry::FactoryMap::const_iterator itEnd = context.getReporterRegistry().getFactories().end();
|
||||||
@ -3584,7 +3594,7 @@ namespace Catch {
|
|||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( config.listWhat() & Config::List::Tests ) {
|
if( config.listWhat() & List::Tests ) {
|
||||||
std::cout << "Available tests:\n";
|
std::cout << "Available tests:\n";
|
||||||
std::vector<TestCaseInfo>::const_iterator it = context.getTestCaseRegistry().getAllTests().begin();
|
std::vector<TestCaseInfo>::const_iterator it = context.getTestCaseRegistry().getAllTests().begin();
|
||||||
std::vector<TestCaseInfo>::const_iterator itEnd = context.getTestCaseRegistry().getAllTests().end();
|
std::vector<TestCaseInfo>::const_iterator itEnd = context.getTestCaseRegistry().getAllTests().end();
|
||||||
@ -3595,7 +3605,7 @@ namespace Catch {
|
|||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( config.listWhat() & Config::List::All ) == 0 ) {
|
if( ( config.listWhat() & List::All ) == 0 ) {
|
||||||
std::cerr << "Unknown list type" << std::endl;
|
std::cerr << "Unknown list type" << std::endl;
|
||||||
return (std::numeric_limits<int>::max)();
|
return (std::numeric_limits<int>::max)();
|
||||||
}
|
}
|
||||||
@ -3943,8 +3953,6 @@ namespace Catch {
|
|||||||
std::vector<SpanInfo> m_sectionSpans;
|
std::vector<SpanInfo> m_sectionSpans;
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
|
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
// #included from: reporters/catch_reporter_xml.hpp
|
// #included from: reporters/catch_reporter_xml.hpp
|
||||||
@ -4271,8 +4279,6 @@ namespace Catch {
|
|||||||
XmlWriter m_xml;
|
XmlWriter m_xml;
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
|
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
// #included from: reporters/catch_reporter_junit.hpp
|
// #included from: reporters/catch_reporter_junit.hpp
|
||||||
@ -4481,8 +4487,6 @@ namespace Catch {
|
|||||||
std::ostringstream m_stdErr;
|
std::ostringstream m_stdErr;
|
||||||
};
|
};
|
||||||
|
|
||||||
INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
|
|
||||||
|
|
||||||
} // end namespace Catch
|
} // end namespace Catch
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -4491,10 +4495,14 @@ namespace Catch {
|
|||||||
|
|
||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
|
INTERNAL_CATCH_REGISTER_REPORTER( "basic", BasicReporter )
|
||||||
|
INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
|
||||||
|
INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
|
||||||
|
|
||||||
inline int Main( Config& config ) {
|
inline int Main( Config& config ) {
|
||||||
|
|
||||||
// Handle list request
|
// Handle list request
|
||||||
if( config.listWhat() != Config::List::None )
|
if( config.listWhat() != List::None )
|
||||||
return List( config );
|
return List( config );
|
||||||
|
|
||||||
// Open output file, if specified
|
// Open output file, if specified
|
||||||
@ -4541,28 +4549,33 @@ namespace Catch {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void showUsage( std::ostream& os ) {
|
||||||
|
os << "\t-l, --list <tests | reporters> [xml]\n"
|
||||||
|
<< "\t-t, --test <testspec> [<testspec>...]\n"
|
||||||
|
<< "\t-r, --reporter <reporter name>\n"
|
||||||
|
<< "\t-o, --out <file name>|<%stream name>\n"
|
||||||
|
<< "\t-s, --success\n"
|
||||||
|
<< "\t-b, --break\n"
|
||||||
|
<< "\t-n, --name <name>\n\n"
|
||||||
|
<< "For more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line" << std::endl;
|
||||||
|
}
|
||||||
inline void showHelp( std::string exeName ) {
|
inline void showHelp( std::string exeName ) {
|
||||||
std::string::size_type pos = exeName.find_last_of( "/\\" );
|
std::string::size_type pos = exeName.find_last_of( "/\\" );
|
||||||
if( pos != std::string::npos ) {
|
if( pos != std::string::npos ) {
|
||||||
exeName = exeName.substr( pos+1 );
|
exeName = exeName.substr( pos+1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << exeName << " is a CATCH host application. Options are as follows:\n\n"
|
std::cout << exeName << " is a CATCH host application. Options are as follows:\n\n";
|
||||||
<< "\t-l, --list <tests | reporters> [xml]\n"
|
showUsage( std::cout );
|
||||||
<< "\t-t, --test <testspec> [<testspec>...]\n"
|
|
||||||
<< "\t-r, --reporter <reporter name>\n"
|
|
||||||
<< "\t-o, --out <file name>|<%stream name>\n"
|
|
||||||
<< "\t-s, --success\n"
|
|
||||||
<< "\t-b, --break\n"
|
|
||||||
<< "\t-n, --name <name>\n\n"
|
|
||||||
<< "For more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Main( int argc, char* const argv[], Config& config ) {
|
inline int Main( int argc, char* const argv[], Config& config ) {
|
||||||
ArgParser( argc, argv, config );
|
|
||||||
|
parseIntoConfig( CommandParser( argc, argv ), config );
|
||||||
|
|
||||||
if( !config.getMessage().empty() ) {
|
if( !config.getMessage().empty() ) {
|
||||||
std::cerr << config.getMessage() << std::endl;
|
std::cerr << config.getMessage() << + "\n\nUsage: ...\n\n";
|
||||||
|
showUsage( std::cerr );
|
||||||
Catch::Context::cleanUp();
|
Catch::Context::cleanUp();
|
||||||
return (std::numeric_limits<int>::max)();
|
return (std::numeric_limits<int>::max)();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user