catch2/include/internal/catch_commandline.hpp

394 lines
14 KiB
C++
Raw Normal View History

2010-11-10 00:24:00 +01:00
/*
* Created by Phil on 02/11/2010.
* Copyright 2010 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2011-01-01 01:29:58 +01:00
#include "catch_config.hpp"
2012-08-23 21:08:50 +02:00
#include "catch_common.h"
2010-11-10 00:24:00 +01:00
2012-05-16 00:58:23 +02:00
namespace Catch {
class Command {
2010-11-10 00:24:00 +01:00
public:
Command(){}
2010-11-10 00:24:00 +01:00
2012-06-03 00:08:07 +02:00
explicit Command( const std::string& name ) : m_name( name ) {}
Command& operator += ( const std::string& arg ) {
m_args.push_back( arg );
return *this;
}
Command& operator += ( const Command& other ) {
std::copy( other.m_args.begin(), other.m_args.end(), std::back_inserter( m_args ) );
if( m_name.empty() )
m_name = other.m_name;
return *this;
}
Command operator + ( const Command& other ) {
Command newCommand( *this );
newCommand += other;
return newCommand;
2010-11-10 00:24:00 +01:00
}
operator SafeBool::type() const {
return SafeBool::makeSafe( !m_name.empty() || !m_args.empty() );
2010-11-10 00:24:00 +01:00
}
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(); }
CATCH_ATTRIBUTE_NORETURN
void raiseError( const std::string& message ) const {
std::ostringstream oss;
oss << "Error while parsing " << m_name << ". " << message << ".";
if( m_args.size() > 0 )
oss << " Arguments where:";
for( std::size_t i = 0; i < m_args.size(); ++i )
oss << " " << m_args[i];
throw std::domain_error( oss.str() );
2010-11-10 00:24:00 +01:00
}
private:
std::string m_name;
2010-11-10 00:24:00 +01:00
std::vector<std::string> m_args;
};
class CommandParser {
public:
2012-06-03 00:08:07 +02:00
CommandParser( int argc, char const * const * argv ) : m_argc( static_cast<std::size_t>( 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 {
if( arg.empty() )
return getArgs( "", 1 );
else
for( std::size_t i = 1; i < m_argc; ++i )
if( m_argv[i] == arg )
return getArgs( m_argv[i], i+1 );
return Command();
}
Command getDefaultArgs() const {
return getArgs( "", 1 );
}
private:
Command getArgs( const std::string& cmdName, std::size_t from ) const {
Command command( cmdName );
for( std::size_t i = from; i < m_argc && m_argv[i][0] != '-'; ++i )
command += m_argv[i];
return command;
}
2012-06-03 00:08:07 +02:00
std::size_t m_argc;
char const * const * m_argv;
};
class OptionParser : public IShared {
public:
virtual ~OptionParser() {}
void parseIntoConfig( CommandParser parser, ConfigData& config ) {
Command cmd;
for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
it != m_optionNames.end();
++it )
cmd += parser.find( *it );
if( cmd )
parseIntoConfig( cmd, config );
}
virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) = 0;
virtual std::string argsSynopsis() const = 0;
virtual std::string optionSummary() const = 0;
2012-06-08 09:22:56 +02:00
protected:
std::vector<std::string> m_optionNames;
};
namespace Options {
class TestCaseOptionParser : public OptionParser {
public:
TestCaseOptionParser() {
m_optionNames.push_back( "-t" );
m_optionNames.push_back( "--test" );
m_optionNames.push_back( "" ); // default option
}
virtual std::string argsSynopsis() const {
return "<testspec> [<testspec>...]";
}
virtual std::string optionSummary() const {
return "Specify which test case or cases to run";
}
virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
if( cmd.argsCount() == 0 )
cmd.raiseError( "Expected at least one argument" );
std::string groupName;
for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
if( i != 0 )
groupName += " ";
groupName += cmd[i];
}
TestCaseFilters filters( groupName );
for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
if( startsWith( cmd[i], "exclude:" ) )
filters.addFilter( TestCaseFilter( cmd[i].substr( 8 ), IfFilterMatches::ExcludeTests ) );
else if( startsWith( cmd[i], "~" ) )
filters.addFilter( TestCaseFilter( cmd[i].substr( 1 ), IfFilterMatches::ExcludeTests ) );
else
filters.addFilter( TestCaseFilter( cmd[i] ) );
}
config.filters.push_back( filters );
}
};
class ListOptionParser : public OptionParser {
public:
ListOptionParser() {
m_optionNames.push_back( "-l" );
m_optionNames.push_back( "--list" );
}
virtual std::string argsSynopsis() const {
return "!TBD";
}
virtual std::string optionSummary() const {
return "!TBD";
}
virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
if( cmd.argsCount() > 2 )
cmd.raiseError( "Expected upto 2 arguments" );
config.listSpec = List::TestNames;
if( cmd.argsCount() >= 1 ) {
if( cmd[0] == "all" )
config.listSpec = List::All;
else if( cmd[0] == "tests" )
config.listSpec = List::Tests;
else if( cmd[0] == "reporters" )
config.listSpec = List::Reports;
else
cmd.raiseError( "Expected [tests] or [reporters]" );
}
if( cmd.argsCount() >= 2 ) {
if( cmd[1] == "xml" )
config.listSpec = static_cast<List::What>( config.listSpec | List::AsXml );
else if( cmd[1] == "text" )
config.listSpec = static_cast<List::What>( config.listSpec | List::AsText );
else
cmd.raiseError( "Expected [xml] or [text]" );
}
}
};
class ReporterOptionParser : public OptionParser {
public:
ReporterOptionParser() {
m_optionNames.push_back( "-r" );
m_optionNames.push_back( "--reporter" );
}
virtual std::string argsSynopsis() const {
return "!TBD";
}
virtual std::string optionSummary() const {
return "!TBD";
}
virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
if( cmd.argsCount() != 1 )
cmd.raiseError( "Expected one argument" );
config.reporter = cmd[0];
}
};
class OutputOptionParser : public OptionParser {
public:
OutputOptionParser() {
m_optionNames.push_back( "-o" );
m_optionNames.push_back( "--out" );
}
virtual std::string argsSynopsis() const {
return "!TBD";
}
virtual std::string optionSummary() const {
return "!TBD";
}
virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
if( cmd.argsCount() == 0 )
cmd.raiseError( "Expected filename" );
if( cmd[0][0] == '%' )
config.stream = cmd[0].substr( 1 );
2012-08-23 21:08:50 +02:00
else
config.outputFilename = cmd[0];
}
};
class SuccesssOptionParser : public OptionParser {
public:
SuccesssOptionParser() {
m_optionNames.push_back( "-s" );
m_optionNames.push_back( "--success" );
}
virtual std::string argsSynopsis() const {
return "!TBD";
}
virtual std::string optionSummary() const {
return "!TBD";
2012-08-23 21:08:50 +02:00
}
virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
if( cmd.argsCount() != 0 )
cmd.raiseError( "Does not accept arguments" );
config.includeWhichResults = Include::SuccessfulResults;
}
};
2012-06-08 09:22:56 +02:00
class DebugBreakOptionParser : public OptionParser {
public:
DebugBreakOptionParser() {
m_optionNames.push_back( "-b" );
m_optionNames.push_back( "--break" );
}
virtual std::string argsSynopsis() const {
return "!TBD";
}
virtual std::string optionSummary() const {
return "!TBD";
}
virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
if( cmd.argsCount() != 0 )
cmd.raiseError( "Does not accept arguments" );
config.shouldDebugBreak = true;
}
};
2012-06-08 09:22:56 +02:00
class NameOptionParser : public OptionParser {
public:
NameOptionParser() {
m_optionNames.push_back( "-n" );
m_optionNames.push_back( "--name" );
}
virtual std::string argsSynopsis() const {
return "!TBD";
}
virtual std::string optionSummary() const {
return "!TBD";
}
virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
if( cmd.argsCount() != 1 )
cmd.raiseError( "Expected a name" );
config.name = cmd[0];
}
};
class AbortOptionParser : public OptionParser {
public:
AbortOptionParser() {
m_optionNames.push_back( "-a" );
m_optionNames.push_back( "--abort" );
}
virtual std::string argsSynopsis() const {
return "!TBD";
}
virtual std::string optionSummary() const {
return "!TBD";
}
virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
if( cmd.argsCount() > 1 )
cmd.raiseError( "Only accepts 0-1 arguments" );
int threshold = 1;
if( cmd.argsCount() == 1 ) {
std::stringstream ss;
ss << cmd[0];
ss >> threshold;
if( ss.fail() || threshold <= 0 )
cmd.raiseError( "threshold must be a number greater than zero" );
}
config.cutoff = threshold;
}
};
class NoThrowOptionParser : public OptionParser {
public:
NoThrowOptionParser() {
m_optionNames.push_back( "-nt" );
m_optionNames.push_back( "--nothrow" );
}
virtual std::string argsSynopsis() const {
return "!TBD";
}
virtual std::string optionSummary() const {
return "!TBD";
}
virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) {
if( cmd.argsCount() != 0 )
cmd.raiseError( "Does not accept arguments" );
config.allowThrows = false;
}
};
}
class AllOptions
{
public:
typedef std::vector<Ptr<OptionParser> > Parsers;
typedef Parsers::const_iterator const_iterator;
typedef Parsers::const_iterator iterator;
AllOptions() {
add<Options::AbortOptionParser>();
add<Options::DebugBreakOptionParser>();
add<Options::ListOptionParser>();
add<Options::NameOptionParser>();
add<Options::NoThrowOptionParser>();
add<Options::OutputOptionParser>();
add<Options::ReporterOptionParser>();
add<Options::SuccesssOptionParser>();
add<Options::TestCaseOptionParser>();
2012-06-08 09:22:56 +02:00
}
void parseIntoConfig( const CommandParser& parser, ConfigData& config ) {
for( const_iterator it = m_parsers.begin(); it != m_parsers.end(); ++it )
(*it)->parseIntoConfig( parser, config );
2012-06-08 09:22:56 +02:00
}
const_iterator begin() const {
return m_parsers.begin();
2012-06-08 09:22:56 +02:00
}
const_iterator end() const {
return m_parsers.end();
}
private:
template<typename T>
void add() {
m_parsers.push_back( new SharedImpl<T>() );
}
Parsers m_parsers;
2012-06-08 09:22:56 +02:00
};
2012-06-08 09:22:56 +02:00
2010-11-10 00:24:00 +01:00
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED