mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-30 19:57:10 +01:00 
			
		
		
		
	Now fully switched over to Clara-based command line with modified args
This commit is contained in:
		| @@ -131,61 +131,36 @@ namespace Catch { | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     inline void showUsage( std::ostream& os ) { | ||||
|         AllOptions options; | ||||
|     inline void showHelp( Clara::CommandLine<ConfigData> const& cli, std::string const& processName ) { | ||||
|  | ||||
|         for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) { | ||||
|             OptionParser& opt = **it; | ||||
|             os << "  " << opt.optionNames() << " " << opt.argsSynopsis() << "\n"; | ||||
|         } | ||||
|         os << "\nFor more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line\n" << std::endl; | ||||
|     } | ||||
|         std::cout << "\nCatch v"    << libraryVersion.majorVersion << "." | ||||
|                                     << libraryVersion.minorVersion << " build " | ||||
|                                     << libraryVersion.buildNumber; | ||||
|         if( libraryVersion.branchName != "master" ) | ||||
|             std::cout << " (" << libraryVersion.branchName << " branch)"; | ||||
|         std::cout << "\n"; | ||||
|  | ||||
|     inline void showHelp( const CommandParser& parser ) { | ||||
|         AllOptions options; | ||||
|         Options::HelpOptionParser helpOpt; | ||||
|         bool displayedSpecificOption = false; | ||||
|         for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) { | ||||
|             OptionParser& opt = **it; | ||||
|             if( opt.find( parser ) && opt.optionNames() != helpOpt.optionNames() ) { | ||||
|                 displayedSpecificOption = true; | ||||
|                 std::cout   << "\n" << opt.optionNames() << " " << opt.argsSynopsis() << "\n\n" | ||||
|                             << opt.optionSummary() << "\n\n" | ||||
|                             << Text( opt.optionDescription(), TextAttributes().setIndent( 2 ) ) << "\n" << std::endl; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if( !displayedSpecificOption ) { | ||||
|             std::cout   << "\nCATCH v"  << libraryVersion.majorVersion << "." | ||||
|                                         << libraryVersion.minorVersion << " build " | ||||
|                                         << libraryVersion.buildNumber; | ||||
|             if( libraryVersion.branchName != "master" ) | ||||
|                 std::cout << " (" << libraryVersion.branchName << " branch)"; | ||||
|  | ||||
|             std::cout << "\n\n" << parser.exeName() << " is a CATCH host application. Options are as follows:\n\n"; | ||||
|             showUsage( std::cout ); | ||||
|         } | ||||
|         cli.usage( std::cout, processName ); | ||||
|         std::cout << "\nFor more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line\n" << std::endl; | ||||
|     } | ||||
|  | ||||
|     inline int Main( int argc, char* const argv[], ConfigData configData = ConfigData() ) { | ||||
|  | ||||
|         Clara::CommandLine<ConfigData> cli = makeCommandLineParser(); | ||||
|  | ||||
|         try { | ||||
|             CommandParser parser( argc, argv ); | ||||
|             cli.parseInto( argc, argv, configData ); | ||||
|  | ||||
|             if( Command cmd = Options::HelpOptionParser().find( parser ) ) { | ||||
|                 if( cmd.argsCount() != 0 ) | ||||
|                     cmd.raiseError( "Does not accept arguments" ); | ||||
|  | ||||
|                 showHelp( parser ); | ||||
|             if( configData.showHelp ) { | ||||
|                 showHelp( cli, argv[0] ); | ||||
|                 Catch::cleanUp();         | ||||
|                 return 0; | ||||
|             } | ||||
|  | ||||
|             parseCommandLine( argc, argv, configData ); | ||||
|         } | ||||
|         catch( std::exception& ex ) { | ||||
|             std::cerr << ex.what() << "\n\nUsage: ...\n\n"; | ||||
|             showUsage( std::cerr ); | ||||
|             std::cerr   << "\nError in input:\n" | ||||
|                         << "  " << ex.what() << "\n\n"; | ||||
|             cli.usage( std::cout, argv[0] ); | ||||
|             Catch::cleanUp(); | ||||
|             return (std::numeric_limits<int>::max)(); | ||||
|         } | ||||
|   | ||||
| @@ -655,7 +655,11 @@ namespace Catch { | ||||
|     }; | ||||
|      | ||||
|     inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } | ||||
|     inline void abortAfterX( ConfigData& config, int x ) { config.abortAfter = x; } | ||||
|     inline void abortAfterX( ConfigData& config, int x ) { | ||||
|         if( x < 1 ) | ||||
|             throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); | ||||
|         config.abortAfter = x; | ||||
|     } | ||||
|     inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } | ||||
|  | ||||
|     inline void addWarning( ConfigData& config, std::string const& _warning ) { | ||||
| @@ -670,10 +674,12 @@ namespace Catch { | ||||
|         config.verbosity = (ConfigData::Verbosity::Level)level; | ||||
|     } | ||||
|      | ||||
|     inline void parseCommandLine( int argc, char* const argv[], ConfigData& config ) { | ||||
|     inline Clara::CommandLine<ConfigData> makeCommandLineParser() { | ||||
|  | ||||
|         Clara::CommandLine<ConfigData> cli; | ||||
|  | ||||
|         cli.bindProcessName( &ConfigData::processName ); | ||||
|  | ||||
|         cli.bind( &ConfigData::showHelp ) | ||||
|             .describe( "display usage information" ) | ||||
|             .shortOpt( "?") | ||||
| @@ -690,7 +696,7 @@ namespace Catch { | ||||
|             .shortOpt( "t") | ||||
|             .longOpt( "list-tags" ); | ||||
|  | ||||
|         cli.bind( &ConfigData::listTags ) | ||||
|         cli.bind( &ConfigData::listReporters ) | ||||
|             .describe( "list all reporters" ) | ||||
|             .longOpt( "list-reporters" ); | ||||
|  | ||||
| @@ -754,12 +760,7 @@ namespace Catch { | ||||
|             .describe( "which test or tests to use" ) | ||||
|             .argName( "test name, pattern or tags" ); | ||||
|  | ||||
| //        cli.parseInto( argc, argv, config ); | ||||
|  | ||||
|         // Legacy way | ||||
|         CommandParser parser( argc, argv ); | ||||
|         AllOptions options; | ||||
|         options.parseIntoConfig( parser, config ); | ||||
|         return cli; | ||||
|     } | ||||
|          | ||||
| } // end namespace Catch | ||||
|   | ||||
| @@ -67,6 +67,7 @@ namespace Catch { | ||||
|         std::string reporterName; | ||||
|         std::string outputFilename; | ||||
|         std::string name; | ||||
|         std::string processName; | ||||
|  | ||||
|         std::vector<std::string> testsOrTags; | ||||
|     }; | ||||
|   | ||||
| @@ -64,7 +64,7 @@ namespace Clara { | ||||
|             BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {} | ||||
|             BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj->clone() ) {} | ||||
|             BoundArgFunction& operator = ( BoundArgFunction const& other ) { | ||||
|                 IArgFunction<ConfigT> newFunctionObj = other.clone(); | ||||
|                 IArgFunction<ConfigT>* newFunctionObj = other.functionObj->clone(); | ||||
|                 delete functionObj; | ||||
|                 functionObj = newFunctionObj; | ||||
|                 return *this; | ||||
| @@ -83,6 +83,14 @@ namespace Clara { | ||||
|         }; | ||||
|  | ||||
|  | ||||
|         template<typename C> | ||||
|         struct NullBinder : IArgFunction<C>{ | ||||
|             virtual void set( C&, std::string const& ) const {} | ||||
|             virtual void setFlag( C& ) const {} | ||||
|             virtual bool takesArg() const { return true; } | ||||
|             virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); } | ||||
|         }; | ||||
|  | ||||
|         template<typename C, typename M> | ||||
|         struct BoundDataMember : IArgFunction<C>{ | ||||
|             BoundDataMember( M C::* _member ) : member( _member ) {} | ||||
| @@ -354,13 +362,29 @@ namespace Clara { | ||||
|  | ||||
|     public: | ||||
|      | ||||
|         CommandLine() : m_highestSpecifiedArgPosition( 0 ) {} | ||||
|         CommandLine() | ||||
|         :   m_boundProcessName( new Detail::NullBinder<ConfigT>() ), | ||||
|             m_highestSpecifiedArgPosition( 0 ) | ||||
|         {} | ||||
|         CommandLine( CommandLine const& other ) | ||||
|         :   m_boundProcessName( other.m_boundProcessName ), | ||||
|             m_options ( other.m_options ), | ||||
|             m_positionalArgs( other.m_positionalArgs ), | ||||
|             m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ) | ||||
|         { | ||||
|             if( other.m_arg.get() ) | ||||
|                 m_arg = std::auto_ptr<Arg>( new Arg( *other.m_arg ) ); | ||||
|         } | ||||
|  | ||||
|         template<typename F> | ||||
|         ArgBinder bind( F f ) { | ||||
|             ArgBinder binder( this, f ); | ||||
|             return binder; | ||||
|         } | ||||
|         template<typename F> | ||||
|         void bindProcessName( F f ) { | ||||
|             m_boundProcessName = Detail::makeBoundField( f ); | ||||
|         } | ||||
|  | ||||
|         void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = CATCH_CONFIG_CONSOLE_WIDTH ) const { | ||||
|             typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; | ||||
| @@ -418,7 +442,6 @@ namespace Clara { | ||||
|             return oss.str(); | ||||
|         } | ||||
|          | ||||
|  | ||||
|         void usage( std::ostream& os, std::string const& procName ) const { | ||||
|             os << "usage:\n  " << procName << " "; | ||||
|             argSynopsis( os ); | ||||
| @@ -435,6 +458,7 @@ namespace Clara { | ||||
|         }         | ||||
|          | ||||
|         std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const { | ||||
|             m_boundProcessName.set( config, argv[0] ); | ||||
|             std::vector<Parser::Token> tokens; | ||||
|             Parser parser; | ||||
|             parser.parseIntoTokens( argc, argv, tokens ); | ||||
| @@ -458,18 +482,23 @@ namespace Clara { | ||||
|                 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end(); | ||||
|                 for(; it != itEnd; ++it ) { | ||||
|                     Arg const& arg = *it; | ||||
|                      | ||||
|                     if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || | ||||
|                         ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { | ||||
|                         if( arg.takesArg() ) { | ||||
|                             if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) | ||||
|                                 throw std::domain_error( "Expected argument to option " + token.data ); | ||||
|                             arg.boundField.set( config, tokens[++i].data ); | ||||
|                          | ||||
|                     try { | ||||
|                         if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || | ||||
|                             ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { | ||||
|                             if( arg.takesArg() ) { | ||||
|                                 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) | ||||
|                                     throw std::domain_error( "Expected argument to option " + token.data ); | ||||
|                                 arg.boundField.set( config, tokens[++i].data ); | ||||
|                             } | ||||
|                             else { | ||||
|                                 arg.boundField.setFlag( config ); | ||||
|                             } | ||||
|                             break; | ||||
|                         } | ||||
|                         else { | ||||
|                             arg.boundField.setFlag( config ); | ||||
|                         } | ||||
|                         break; | ||||
|                     } | ||||
|                     catch( std::exception& ex ) { | ||||
|                         throw std::runtime_error( std::string( ex.what() ) + " while parsing: (" + arg.commands() + ")" ); | ||||
|                     } | ||||
|                 } | ||||
|                 if( it == itEnd ) | ||||
| @@ -507,6 +536,7 @@ namespace Clara { | ||||
|         } | ||||
|          | ||||
|     private: | ||||
|         Detail::BoundArgFunction<ConfigT> m_boundProcessName; | ||||
|         std::vector<Arg> m_options; | ||||
|         std::map<int, Arg> m_positionalArgs; | ||||
|         std::auto_ptr<Arg> m_arg; | ||||
|   | ||||
| @@ -24,6 +24,7 @@ std::vector<Clara::Parser::Token> parseInto( Clara::CommandLine<ConfigT>& cli, c | ||||
| struct TestOpt { | ||||
|     TestOpt() : number( 0 ), index( 0 ), flag( false ) {} | ||||
|  | ||||
|     std::string processName; | ||||
|     std::string fileName; | ||||
|     int number; | ||||
|     int index; | ||||
| @@ -49,12 +50,19 @@ TEST_CASE( "cmdline" ) { | ||||
|  | ||||
|     TestOpt config; | ||||
|     Clara::CommandLine<TestOpt> cli; | ||||
|     cli.bindProcessName( &TestOpt::processName ); | ||||
|     cli.bind( &TestOpt::fileName ) | ||||
|         .describe( "specifies output file" ) | ||||
|         .shortOpt( "o" ) | ||||
|         .longOpt( "output" ) | ||||
|         .argName( "filename" ); | ||||
|  | ||||
|     SECTION( "process name" ) { | ||||
|         char const * argv[] = { "test", "-o filename.ext" }; | ||||
|         parseInto( cli, argv, config ); | ||||
|          | ||||
|         CHECK( config.processName == "test" ); | ||||
|     } | ||||
|     SECTION( "arg separated by spaces" ) { | ||||
|         char const * argv[] = { "test", "-o filename.ext" }; | ||||
|         parseInto( cli, argv, config ); | ||||
| @@ -169,7 +177,7 @@ TEST_CASE( "cmdline" ) { | ||||
|             .argName( "first arg" ) | ||||
|             .position( 1 ); | ||||
|  | ||||
|         std::cout << cli.usage( "testApp" ) << std::endl; | ||||
| //        std::cout << cli.usage( "testApp" ) << std::endl; | ||||
|  | ||||
|         const char* argv[] = { "test", "-f", "1st", "-o", "filename", "2nd", "3rd" }; | ||||
|         parseInto( cli, argv, config ); | ||||
| @@ -180,205 +188,4 @@ TEST_CASE( "cmdline" ) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| struct Config { | ||||
|  | ||||
|     struct Verbosity { enum Level { NoOutput = 0, Quiet, Normal }; }; | ||||
|     struct Warning { enum Types { Nothing = 0x00, NoAssertions = 0x01 }; }; | ||||
|  | ||||
|     Config() | ||||
|     :   listTests( false ), | ||||
|         listTags( false ), | ||||
|         listReporters( false ), | ||||
|         showSuccessfulTests( false ), | ||||
|         breakIntoDebugger( false ), | ||||
|         noThrow( false ), | ||||
|         showHelp( false ), | ||||
|         abortAfter( 0 ), | ||||
|         verbosity( Verbosity::Normal ), | ||||
|         warnings( Warning::Nothing ) | ||||
|     {} | ||||
|  | ||||
|     bool listTests; | ||||
|     bool listTags; | ||||
|     bool listReporters; | ||||
|  | ||||
|     bool showSuccessfulTests; | ||||
|     bool breakIntoDebugger; | ||||
|     bool noThrow; | ||||
|     bool showHelp; | ||||
|  | ||||
|     int abortAfter; | ||||
|  | ||||
|     Verbosity::Level verbosity; | ||||
|     Warning::Types warnings; | ||||
|  | ||||
|     std::string reporterName; | ||||
|     std::string fileName; | ||||
|     std::string suiteName; | ||||
|  | ||||
|     std::vector<std::string> testsOrTags; | ||||
| }; | ||||
|  | ||||
| inline void abortAfterFirst( Config& config ) { config.abortAfter = 1; } | ||||
| inline void abortAfterX( Config& config, int x ) { config.abortAfter = x; } | ||||
| inline void addTestOrTags( Config& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } | ||||
|  | ||||
| inline void addWarning( Config& config, std::string const& _warning ) { | ||||
|     if( _warning == "NoAssertions" ) | ||||
|         config.warnings = (Config::Warning::Types)( config.warnings | Config::Warning::NoAssertions ); | ||||
|     else | ||||
|         throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); | ||||
|  | ||||
| } | ||||
| inline void setVerbosity( Config& config, int level ) { | ||||
|     // !TBD: accept strings? | ||||
|     config.verbosity = (Config::Verbosity::Level)level; | ||||
| } | ||||
|  | ||||
|  | ||||
| SCENARIO( "New Catch commandline interface", "[cli]" ) { | ||||
|  | ||||
|     GIVEN( "A built cli parser for Catch" ) { | ||||
|         Clara::CommandLine<Config> cli; | ||||
|  | ||||
|         cli.bind( &Config::showHelp ) | ||||
|             .describe( "display usage information" ) | ||||
|             .shortOpt( "?") | ||||
|             .shortOpt( "h") | ||||
|             .longOpt( "help" ); | ||||
|  | ||||
|         cli.bind( &Config::listTests ) | ||||
|             .describe( "list all (or matching) test cases" ) | ||||
|             .shortOpt( "l") | ||||
|             .longOpt( "list-tests" ); | ||||
|  | ||||
|         cli.bind( &Config::listTags ) | ||||
|             .describe( "list all (or matching) tags" ) | ||||
|             .shortOpt( "t") | ||||
|             .longOpt( "list-tags" ); | ||||
|  | ||||
|         cli.bind( &Config::listTags ) | ||||
|             .describe( "list all reporters" ) | ||||
|             .longOpt( "list-reporters" ); | ||||
|  | ||||
|         cli.bind( &Config::showSuccessfulTests ) | ||||
|             .describe( "include successful tests in output" ) | ||||
|             .shortOpt( "s") | ||||
|             .longOpt( "success" ); | ||||
|  | ||||
|         cli.bind( &Config::breakIntoDebugger ) | ||||
|             .describe( "break into debugger on failure" ) | ||||
|             .shortOpt( "b") | ||||
|             .longOpt( "break" ); | ||||
|  | ||||
|         cli.bind( &Config::noThrow ) | ||||
|             .describe( "Skip exception tests" ) | ||||
|             .shortOpt( "e") | ||||
|             .longOpt( "nothrow" ); | ||||
|  | ||||
|         cli.bind( &Config::fileName ) | ||||
|             .describe( "output filename" ) | ||||
|             .shortOpt( "o") | ||||
|             .longOpt( "out" ) | ||||
|             .argName( "filename" ); | ||||
|  | ||||
|         cli.bind( &Config::reporterName ) | ||||
|             .describe( "reporter to use - defaults to console" ) | ||||
|             .shortOpt( "r") | ||||
|             .longOpt( "reporter" ) | ||||
|             .argName( "name[:filename]" ); | ||||
|  | ||||
|         cli.bind( &Config::suiteName ) | ||||
|             .describe( "suite name" ) | ||||
|             .shortOpt( "n") | ||||
|             .longOpt( "name" ) | ||||
|             .argName( "name" ); | ||||
|  | ||||
|         cli.bind( &abortAfterFirst ) | ||||
|             .describe( "abort at first failure" ) | ||||
|             .shortOpt( "a") | ||||
|             .longOpt( "abort" ); | ||||
|  | ||||
|         cli.bind( &abortAfterX ) | ||||
|             .describe( "abort after x failures" ) | ||||
|             .shortOpt( "x") | ||||
|             .longOpt( "abortx" ) | ||||
|             .argName( "number of failures" ); | ||||
|  | ||||
|         cli.bind( &addWarning ) | ||||
|             .describe( "enable warnings" ) | ||||
|             .shortOpt( "w") | ||||
|             .longOpt( "warn" ) | ||||
|             .argName( "warning name" ); | ||||
|  | ||||
|         cli.bind( &setVerbosity ) | ||||
|             .describe( "level of verbosity (0=no output)" ) | ||||
|             .shortOpt( "v") | ||||
|             .longOpt( "verbosity" ) | ||||
|             .argName( "level" ); | ||||
|  | ||||
|         cli.bind( &addTestOrTags ) | ||||
|             .describe( "which test or tests to use" ) | ||||
|             .argName( "test name, pattern or tags" ); | ||||
|  | ||||
|         WHEN( "We ask for usage strings" ) | ||||
|         THEN( "It prints the usage strings" ) | ||||
|             std::cout << cli.usage( "CatchTestApp" ) << std::endl; | ||||
|          | ||||
|         Config config; | ||||
|  | ||||
|         WHEN( "Multiple flags are combined" ) { | ||||
|  | ||||
|             CHECK_FALSE( config.showSuccessfulTests ); | ||||
|             CHECK_FALSE( config.noThrow ); | ||||
|             CHECK_FALSE( config.breakIntoDebugger ); | ||||
|  | ||||
|             const char* argv[] = { "test", "-seb" }; | ||||
|             parseInto( cli, argv, config ); | ||||
|              | ||||
|             THEN( "All the flags are set" ) { | ||||
|                 CHECK( config.showSuccessfulTests ); | ||||
|                 CHECK( config.noThrow ); | ||||
|                 CHECK( config.breakIntoDebugger ); | ||||
|             } | ||||
|         } | ||||
|         WHEN( "A flag is set via a nullary method" ) { | ||||
|             CHECK( config.abortAfter == 0 ); | ||||
|  | ||||
|             const char* argv[] = { "test", "-a" }; | ||||
|             parseInto( cli, argv, config ); | ||||
|              | ||||
|             THEN( "The flag is set" ) | ||||
|                 REQUIRE( config.abortAfter == 1 ); | ||||
|         } | ||||
|         WHEN( "A flag is set via a unary method" ) { | ||||
|             CHECK( config.abortAfter == 0 ); | ||||
|  | ||||
|             const char* argv[] = { "test", "-x", "2" }; | ||||
|             parseInto( cli, argv, config ); | ||||
|              | ||||
|             THEN( "The flag is set" ) | ||||
|                 REQUIRE( config.abortAfter == 2 ); | ||||
|         } | ||||
|         WHEN( "A positional argument is supplied" ) { | ||||
|  | ||||
|             const char* argv[] = { "test", "[hello]" }; | ||||
|             parseInto( cli, argv, config ); | ||||
|              | ||||
|             THEN( "The argument is in the testOrTags collection" ) { | ||||
|                 REQUIRE( config.testsOrTags.size() == 1 ); | ||||
|                 REQUIRE( config.testsOrTags[0] == "[hello]" ); | ||||
|             } | ||||
|         } | ||||
|         WHEN( "And enum opt is set by numeric value" ) { | ||||
|             CHECK( config.verbosity == Config::Verbosity::Normal ); | ||||
|  | ||||
|             const char* argv[] = { "test", "-v 0" }; | ||||
|             parseInto( cli, argv, config ); | ||||
|              | ||||
|             THEN( "The member is set to the enum value" ) | ||||
|                 REQUIRE( config.verbosity == Config::Verbosity::NoOutput ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| #endif | ||||
|   | ||||
| @@ -260,8 +260,7 @@ inline unsigned int Factorial( unsigned int 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" ) | ||||
| { | ||||
| TEST_CASE( "Factorials are computed", "[factorial]" ) { | ||||
|   REQUIRE( Factorial(0) == 1 ); | ||||
|   REQUIRE( Factorial(1) == 1 ); | ||||
|   REQUIRE( Factorial(2) == 2 ); | ||||
|   | ||||
| @@ -71,8 +71,8 @@ TEST_CASE( "meta/Misc/Sections", "looped tests" ) { | ||||
|  | ||||
| template<size_t size> | ||||
| void parseIntoConfig( const char * (&argv)[size], Catch::ConfigData& config ) { | ||||
|     static Catch::AllOptions options; | ||||
|     options.parseIntoConfig( Catch::CommandParser( size, argv ), config ); | ||||
|     Clara::CommandLine<Catch::ConfigData> parser = Catch::makeCommandLineParser(); | ||||
|     parser.parseInto( size, argv, config ); | ||||
| } | ||||
|  | ||||
| template<size_t size> | ||||
| @@ -89,11 +89,11 @@ std::string parseIntoConfigAndReturnError( const char * (&argv)[size], Catch::Co | ||||
|  | ||||
| inline Catch::TestCase fakeTestCase( const char* name ){ return Catch::makeTestCase( NULL, "", name, "", CATCH_INTERNAL_LINEINFO ); } | ||||
|  | ||||
| TEST_CASE( "selftest/parser/2", "ConfigData" ) { | ||||
| TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) { | ||||
|  | ||||
|     Catch::ConfigData config; | ||||
|  | ||||
|     SECTION( "default", "" ) { | ||||
|     SECTION( "default - no arguments", "" ) { | ||||
|         const char* argv[] = { "test" }; | ||||
|         CHECK_NOTHROW( parseIntoConfig( argv, config ) ); | ||||
|          | ||||
| @@ -104,8 +104,8 @@ TEST_CASE( "selftest/parser/2", "ConfigData" ) { | ||||
|     } | ||||
|      | ||||
|     SECTION( "test lists", "" ) { | ||||
|         SECTION( "-t/1", "Specify one test case using -t" ) { | ||||
|             const char* argv[] = { "test", "-t", "test1" }; | ||||
|         SECTION( "1 test", "Specify one test case using" ) { | ||||
|             const char* argv[] = { "test", "test1" }; | ||||
|             CHECK_NOTHROW( parseIntoConfig( argv, config ) ); | ||||
|  | ||||
|             Catch::Config cfg( config ); | ||||
| @@ -113,8 +113,8 @@ TEST_CASE( "selftest/parser/2", "ConfigData" ) { | ||||
|             REQUIRE( cfg.filters()[0].shouldInclude( fakeTestCase( "notIncluded" ) ) == false ); | ||||
|             REQUIRE( cfg.filters()[0].shouldInclude( fakeTestCase( "test1" ) ) ); | ||||
|         } | ||||
|         SECTION( "-t/exclude:1", "Specify one test case exclusion using -t exclude:" ) { | ||||
|             const char* argv[] = { "test", "-t", "exclude:test1" }; | ||||
|         SECTION( "Specify one test case exclusion using exclude:", "" ) { | ||||
|             const char* argv[] = { "test", "exclude:test1" }; | ||||
|             CHECK_NOTHROW( parseIntoConfig( argv, config ) ); | ||||
|  | ||||
|             Catch::Config cfg( config ); | ||||
| @@ -123,28 +123,8 @@ TEST_CASE( "selftest/parser/2", "ConfigData" ) { | ||||
|             REQUIRE( cfg.filters()[0].shouldInclude( fakeTestCase( "alwaysIncluded" ) ) ); | ||||
|         } | ||||
|  | ||||
|         SECTION( "--test/1", "Specify one test case using --test" ) { | ||||
|             const char* argv[] = { "test", "--test", "test1" }; | ||||
|             CHECK_NOTHROW( parseIntoConfig( argv, config ) ); | ||||
|              | ||||
|             Catch::Config cfg( config ); | ||||
|             REQUIRE( cfg.filters().size() == 1 ); | ||||
|             REQUIRE( cfg.filters()[0].shouldInclude( fakeTestCase( "notIncluded" ) ) == false ); | ||||
|             REQUIRE( cfg.filters()[0].shouldInclude( fakeTestCase( "test1" ) ) ); | ||||
|         } | ||||
|  | ||||
|         SECTION( "--test/exclude:1", "Specify one test case exclusion using --test exclude:" ) { | ||||
|             const char* argv[] = { "test", "--test", "exclude:test1" }; | ||||
|             CHECK_NOTHROW( parseIntoConfig( argv, config ) ); | ||||
|  | ||||
|             Catch::Config cfg( config ); | ||||
|             REQUIRE( cfg.filters().size() == 1 ); | ||||
|             REQUIRE( cfg.filters()[0].shouldInclude( fakeTestCase( "test1" ) ) == false ); | ||||
|             REQUIRE( cfg.filters()[0].shouldInclude( fakeTestCase( "alwaysIncluded" ) ) ); | ||||
|         } | ||||
|  | ||||
|         SECTION( "--test/exclude:2", "Specify one test case exclusion using --test ~" ) { | ||||
|             const char* argv[] = { "test", "--test", "~test1" }; | ||||
|         SECTION( "Specify one test case exclusion using ~", "" ) { | ||||
|             const char* argv[] = { "test", "~test1" }; | ||||
|             CHECK_NOTHROW( parseIntoConfig( argv, config ) ); | ||||
|  | ||||
|             Catch::Config cfg( config ); | ||||
| @@ -153,7 +133,7 @@ TEST_CASE( "selftest/parser/2", "ConfigData" ) { | ||||
|             REQUIRE( cfg.filters()[0].shouldInclude( fakeTestCase( "alwaysIncluded" ) ) ); | ||||
|         } | ||||
|          | ||||
|         SECTION( "-t/2", "Specify two test cases using -t" ) { | ||||
|         SECTION( "Specify two test cases using -t", "" ) { | ||||
|             const char* argv[] = { "test", "-t", "test1", "test2" }; | ||||
|             CHECK_NOTHROW( parseIntoConfig( argv, config ) ); | ||||
|  | ||||
| @@ -163,11 +143,6 @@ TEST_CASE( "selftest/parser/2", "ConfigData" ) { | ||||
|             REQUIRE( cfg.filters()[0].shouldInclude( fakeTestCase( "test1" ) ) ); | ||||
|             REQUIRE( cfg.filters()[0].shouldInclude( fakeTestCase( "test2" ) ) ); | ||||
|         } | ||||
|  | ||||
|         SECTION( "-t/0", "When no test names are supplied it is an error" ) { | ||||
|             const char* argv[] = { "test", "-t" }; | ||||
|             REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "at least 1" ) ); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     SECTION( "reporter", "" ) { | ||||
| @@ -189,10 +164,6 @@ TEST_CASE( "selftest/parser/2", "ConfigData" ) { | ||||
|              | ||||
|             REQUIRE( config.reporterName == "junit" ); | ||||
|         } | ||||
|         SECTION( "-r/error", "reporter config only accepts one argument" ) { | ||||
|             const char* argv[] = { "test", "-r", "one", "two" }; | ||||
|             REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "1 argument" ) ); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     SECTION( "debugger", "" ) { | ||||
| @@ -208,42 +179,34 @@ TEST_CASE( "selftest/parser/2", "ConfigData" ) { | ||||
|              | ||||
|             REQUIRE( config.shouldDebugBreak ); | ||||
|         } | ||||
|         SECTION( "-b", "break option has no arguments" ) { | ||||
|             const char* argv[] = { "test", "-b", "unexpected" }; | ||||
|             REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "0 arguments" ) ); | ||||
|         } | ||||
|     } | ||||
|          | ||||
|     SECTION( "abort", "" ) { | ||||
|         SECTION( "-a", "" ) { | ||||
|         SECTION( "-a aborts after first failure", "" ) { | ||||
|             const char* argv[] = { "test", "-a" }; | ||||
|             CHECK_NOTHROW( parseIntoConfig( argv, config ) ); | ||||
|  | ||||
|             REQUIRE( config.abortAfter == 1 ); | ||||
|         } | ||||
|         SECTION( "-a/2", "" ) { | ||||
|             const char* argv[] = { "test", "-a", "2" }; | ||||
|         SECTION( "-x 2 aborts after two failures", "" ) { | ||||
|             const char* argv[] = { "test", "-x", "2" }; | ||||
|             CHECK_NOTHROW( parseIntoConfig( argv, config ) ); | ||||
|  | ||||
|             REQUIRE( config.abortAfter == 2 ); | ||||
|         } | ||||
|         SECTION( "-a/error/0", "" ) { | ||||
|             const char* argv[] = { "test", "-a", "0" }; | ||||
|         SECTION( "-x must be greater than zero", "" ) { | ||||
|             const char* argv[] = { "test", "-x", "0" }; | ||||
|             REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "greater than zero" ) ); | ||||
|         } | ||||
|         SECTION( "-a/error/non numeric", "" ) { | ||||
|             const char* argv[] = { "test", "-a", "oops" }; | ||||
|             REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "greater than zero" ) ); | ||||
|         } | ||||
|         SECTION( "-a/error/two args", "abortAfter only takes one argument" ) { | ||||
|             const char* argv[] = { "test", "-a", "1", "2" }; | ||||
|             REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "0 and 1 argument" ) ); | ||||
|         SECTION( "-x must be numeric", "" ) { | ||||
|             const char* argv[] = { "test", "-x", "oops" }; | ||||
|             REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "-x" ) ); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     SECTION( "nothrow", "" ) { | ||||
|         SECTION( "-nt", "" ) { | ||||
|             const char* argv[] = { "test", "-nt" }; | ||||
|         SECTION( "-e", "" ) { | ||||
|             const char* argv[] = { "test", "-e" }; | ||||
|             CHECK_NOTHROW( parseIntoConfig( argv, config ) ); | ||||
|  | ||||
|             REQUIRE( config.noThrow == true ); | ||||
| @@ -272,8 +235,8 @@ TEST_CASE( "selftest/parser/2", "ConfigData" ) { | ||||
|     } | ||||
|  | ||||
|     SECTION( "combinations", "" ) { | ||||
|         SECTION( "-a -b", "" ) { | ||||
|             const char* argv[] = { "test", "-a", "-b", "-nt" }; | ||||
|         SECTION( "Single character flags can be combined", "" ) { | ||||
|             const char* argv[] = { "test", "-abe" }; | ||||
|             CHECK_NOTHROW( parseIntoConfig( argv, config ) ); | ||||
|  | ||||
|             CHECK( config.abortAfter == 1 ); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash