catch2/include/internal/catch_commandline.hpp

227 lines
8.7 KiB
C++
Raw Normal View History

2010-11-10 00:24:00 +01:00
/*
* catch_commandline.hpp
* Catch
*
* 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"
2010-11-10 00:24:00 +01:00
#include "catch_runner_impl.hpp"
namespace Catch
{
// !TBD: This could be refactored to be more "declarative"
// have a table up front that relates the mode, option strings, # arguments, names of arguments
// - may not be worth it at this scale
2010-12-30 19:24:22 +01:00
// -l, --list tests [xml] lists available tests (optionally in xml)
2010-12-30 19:51:02 +01:00
// -l, --list reporters [xml] lists available reports (optionally in xml)
2010-12-30 19:24:22 +01:00
// -l, --list all [xml] lists available tests and reports (optionally in xml)
// -t, --test "testspec" ["testspec", ...]
2010-12-30 19:51:02 +01:00
// -r, --reporter <type>
2010-12-30 19:24:22 +01:00
// -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
2010-11-10 00:24:00 +01:00
{
enum Mode
{
modeNone,
modeList,
modeTest,
modeReport,
modeOutput,
modeSuccess,
modeBreak,
modeName,
2010-12-30 19:51:02 +01:00
modeHelp,
2010-11-10 00:24:00 +01:00
modeError
};
public:
///////////////////////////////////////////////////////////////////////
ArgParser
(
int argc,
char * const argv[],
Config& config
)
2010-11-10 00:24:00 +01:00
: m_mode( modeNone ),
m_config( config )
{
for( int i=1; i < argc; ++i )
2010-11-10 00:24:00 +01:00
{
if( argv[i][0] == '-' )
{
std::string cmd = ( argv[i] );
if( cmd == "-l" || cmd == "--list" )
changeMode( cmd, modeList );
else if( cmd == "-t" || cmd == "--test" )
changeMode( cmd, modeTest );
2010-12-30 19:51:02 +01:00
else if( cmd == "-r" || cmd == "--reporter" )
2010-11-10 00:24:00 +01:00
changeMode( cmd, modeReport );
2010-12-30 19:24:22 +01:00
else if( cmd == "-o" || cmd == "--out" )
2010-11-10 00:24:00 +01:00
changeMode( cmd, modeOutput );
else if( cmd == "-s" || cmd == "--success" )
changeMode( cmd, modeSuccess );
else if( cmd == "-b" || cmd == "--break" )
changeMode( cmd, modeBreak );
else if( cmd == "-n" || cmd == "--name" )
changeMode( cmd, modeName );
2010-12-30 19:51:02 +01:00
else if( cmd == "-h" || cmd == "-?" || cmd == "--help" )
changeMode( cmd, modeHelp );
2010-11-10 00:24:00 +01:00
}
else
{
m_args.push_back( argv[i] );
}
if( m_mode == modeError )
return;
}
changeMode( "", modeNone );
}
private:
///////////////////////////////////////////////////////////////////////
std::string argsAsString
()
2010-11-10 00:24:00 +01:00
{
std::ostringstream oss;
std::vector<std::string>::const_iterator it = m_args.begin();
std::vector<std::string>::const_iterator itEnd = m_args.end();
for( bool first = true; it != itEnd; ++it, first = false )
{
if( !first )
oss << " ";
oss << *it;
}
return oss.str();
}
///////////////////////////////////////////////////////////////////////
void changeMode
(
const std::string& cmd,
Mode mode
)
2010-11-10 00:24:00 +01:00
{
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
{
2011-01-01 01:37:49 +01:00
Config::List::What listSpec = Config::List::All;
2010-11-10 00:24:00 +01:00
if( m_args.size() >= 1 )
{
if( m_args[0] == "tests" )
2011-01-01 01:37:49 +01:00
listSpec = Config::List::Tests;
2010-12-30 19:28:56 +01:00
else if( m_args[0] == "reporters" )
2011-01-01 01:37:49 +01:00
listSpec = Config::List::Reports;
2010-11-10 00:24:00 +01:00
else
2010-12-30 19:28:56 +01:00
return setErrorMode( m_command + " expected [tests] or [reporters] but recieved: [" + m_args[0] + "]" );
2010-11-10 00:24:00 +01:00
}
if( m_args.size() >= 2 )
{
if( m_args[1] == "xml" )
2011-01-31 11:10:20 +01:00
listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsXml );
2010-11-10 00:24:00 +01:00
else if( m_args[1] == "text" )
2011-01-31 11:10:20 +01:00
listSpec = static_cast<Config::List::What>( listSpec | Config::List::AsText );
2010-11-10 00:24:00 +01:00
else
return setErrorMode( m_command + " expected [xml] or [text] but recieved: [" + m_args[1] + "]" );
}
2011-01-31 11:10:20 +01:00
m_config.setListSpec( static_cast<Config::List::What>( m_config.getListSpec() | listSpec ) );
2010-11-10 00:24:00 +01:00
}
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] );
2010-11-10 00:24:00 +01:00
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] );
2010-11-10 00:24:00 +01:00
break;
case modeSuccess:
if( m_args.size() != 0 )
return setErrorMode( m_command + " does not accept arguments" );
m_config.setIncludeWhat( Config::Include::SuccessfulResults );
2010-11-10 00:24:00 +01:00
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;
2010-12-30 19:51:02 +01:00
case modeHelp:
if( m_args.size() != 0 )
return setErrorMode( m_command + " does not accept arguments" );
m_config.setShowHelp( true );
break;
default:
break;
2010-11-10 00:24:00 +01:00
}
m_args.clear();
m_mode = mode;
}
///////////////////////////////////////////////////////////////////////
void setErrorMode
(
const std::string& errorMessage
)
2010-11-10 00:24:00 +01:00
{
m_mode = modeError;
m_command = "";
m_config.setError( errorMessage );
}
private:
Mode m_mode;
std::string m_command;
std::vector<std::string> m_args;
Config& m_config;
2010-11-10 00:24:00 +01:00
};
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED