| /* |
| * 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) |
| */ |
| |
| #include "catch_commandline.h" |
| |
| #include "catch_string_manip.h" |
| |
| #include "catch_interfaces_registry_hub.h" |
| #include "catch_interfaces_reporter.h" |
| |
| #include <fstream> |
| #include <ctime> |
| |
| namespace Catch { |
| |
| clara::Parser makeCommandLineParser( ConfigData& config ) { |
| |
| using namespace clara; |
| |
| auto const setWarning = [&]( std::string const& warning ) { |
| auto warningSet = [&]() { |
| if( warning == "NoAssertions" ) |
| return WarnAbout::NoAssertions; |
| |
| if ( warning == "NoTests" ) |
| return WarnAbout::NoTests; |
| |
| return WarnAbout::Nothing; |
| }(); |
| |
| if (warningSet == WarnAbout::Nothing) |
| return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); |
| config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet ); |
| return ParserResult::ok( ParseResultType::Matched ); |
| }; |
| auto const loadTestNamesFromFile = [&]( std::string const& filename ) { |
| std::ifstream f( filename.c_str() ); |
| if( !f.is_open() ) |
| return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); |
| |
| std::string line; |
| while( std::getline( f, line ) ) { |
| line = trim(line); |
| if( !line.empty() && !startsWith( line, '#' ) ) { |
| if( !startsWith( line, '"' ) ) |
| line = '"' + line + '"'; |
| config.testsOrTags.push_back( line + ',' ); |
| } |
| } |
| return ParserResult::ok( ParseResultType::Matched ); |
| }; |
| auto const setTestOrder = [&]( std::string const& order ) { |
| if( startsWith( "declared", order ) ) |
| config.runOrder = RunTests::InDeclarationOrder; |
| else if( startsWith( "lexical", order ) ) |
| config.runOrder = RunTests::InLexicographicalOrder; |
| else if( startsWith( "random", order ) ) |
| config.runOrder = RunTests::InRandomOrder; |
| else |
| return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); |
| return ParserResult::ok( ParseResultType::Matched ); |
| }; |
| auto const setRngSeed = [&]( std::string const& seed ) { |
| if( seed != "time" ) |
| return clara::detail::convertInto( seed, config.rngSeed ); |
| config.rngSeed = static_cast<unsigned int>( std::time(nullptr) ); |
| return ParserResult::ok( ParseResultType::Matched ); |
| }; |
| auto const setColourUsage = [&]( std::string const& useColour ) { |
| auto mode = toLower( useColour ); |
| |
| if( mode == "yes" ) |
| config.useColour = UseColour::Yes; |
| else if( mode == "no" ) |
| config.useColour = UseColour::No; |
| else if( mode == "auto" ) |
| config.useColour = UseColour::Auto; |
| else |
| return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); |
| return ParserResult::ok( ParseResultType::Matched ); |
| }; |
| auto const setWaitForKeypress = [&]( std::string const& keypress ) { |
| auto keypressLc = toLower( keypress ); |
| if( keypressLc == "start" ) |
| config.waitForKeypress = WaitForKeypress::BeforeStart; |
| else if( keypressLc == "exit" ) |
| config.waitForKeypress = WaitForKeypress::BeforeExit; |
| else if( keypressLc == "both" ) |
| config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; |
| else |
| return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" ); |
| return ParserResult::ok( ParseResultType::Matched ); |
| }; |
| auto const setVerbosity = [&]( std::string const& verbosity ) { |
| auto lcVerbosity = toLower( verbosity ); |
| if( lcVerbosity == "quiet" ) |
| config.verbosity = Verbosity::Quiet; |
| else if( lcVerbosity == "normal" ) |
| config.verbosity = Verbosity::Normal; |
| else if( lcVerbosity == "high" ) |
| config.verbosity = Verbosity::High; |
| else |
| return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); |
| return ParserResult::ok( ParseResultType::Matched ); |
| }; |
| auto const setReporter = [&]( std::string const& reporter ) { |
| IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); |
| |
| auto lcReporter = toLower( reporter ); |
| auto result = factories.find( lcReporter ); |
| |
| if( factories.end() != result ) |
| config.reporterName = lcReporter; |
| else |
| return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" ); |
| return ParserResult::ok( ParseResultType::Matched ); |
| }; |
| |
| auto cli |
| = ExeName( config.processName ) |
| | Help( config.showHelp ) |
| | Opt( config.listTests ) |
| ["-l"]["--list-tests"] |
| ( "list all/matching test cases" ) |
| | Opt( config.listTags ) |
| ["-t"]["--list-tags"] |
| ( "list all/matching tags" ) |
| | Opt( config.showSuccessfulTests ) |
| ["-s"]["--success"] |
| ( "include successful tests in output" ) |
| | Opt( config.shouldDebugBreak ) |
| ["-b"]["--break"] |
| ( "break into debugger on failure" ) |
| | Opt( config.noThrow ) |
| ["-e"]["--nothrow"] |
| ( "skip exception tests" ) |
| | Opt( config.showInvisibles ) |
| ["-i"]["--invisibles"] |
| ( "show invisibles (tabs, newlines)" ) |
| | Opt( config.outputFilename, "filename" ) |
| ["-o"]["--out"] |
| ( "output filename" ) |
| | Opt( setReporter, "name" ) |
| ["-r"]["--reporter"] |
| ( "reporter to use (defaults to console)" ) |
| | Opt( config.name, "name" ) |
| ["-n"]["--name"] |
| ( "suite name" ) |
| | Opt( [&]( bool ){ config.abortAfter = 1; } ) |
| ["-a"]["--abort"] |
| ( "abort at first failure" ) |
| | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) |
| ["-x"]["--abortx"] |
| ( "abort after x failures" ) |
| | Opt( setWarning, "warning name" ) |
| ["-w"]["--warn"] |
| ( "enable warnings" ) |
| | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) |
| ["-d"]["--durations"] |
| ( "show test durations" ) |
| | Opt( loadTestNamesFromFile, "filename" ) |
| ["-f"]["--input-file"] |
| ( "load test names to run from a file" ) |
| | Opt( config.filenamesAsTags ) |
| ["-#"]["--filenames-as-tags"] |
| ( "adds a tag for the filename" ) |
| | Opt( config.sectionsToRun, "section name" ) |
| ["-c"]["--section"] |
| ( "specify section to run" ) |
| | Opt( setVerbosity, "quiet|normal|high" ) |
| ["-v"]["--verbosity"] |
| ( "set output verbosity" ) |
| | Opt( config.listTestNamesOnly ) |
| ["--list-test-names-only"] |
| ( "list all/matching test cases names only" ) |
| | Opt( config.listReporters ) |
| ["--list-reporters"] |
| ( "list all reporters" ) |
| | Opt( setTestOrder, "decl|lex|rand" ) |
| ["--order"] |
| ( "test case order (defaults to decl)" ) |
| | Opt( setRngSeed, "'time'|number" ) |
| ["--rng-seed"] |
| ( "set a specific seed for random numbers" ) |
| | Opt( setColourUsage, "yes|no" ) |
| ["--use-colour"] |
| ( "should output be colourised" ) |
| | Opt( config.libIdentify ) |
| ["--libidentify"] |
| ( "report name and version according to libidentify standard" ) |
| | Opt( setWaitForKeypress, "start|exit|both" ) |
| ["--wait-for-keypress"] |
| ( "waits for a keypress before exiting" ) |
| | Opt( config.benchmarkResolutionMultiple, "multiplier" ) |
| ["--benchmark-resolution-multiple"] |
| ( "multiple of clock resolution to run benchmarks" ) |
| |
| | Arg( config.testsOrTags, "test name|pattern|tags" ) |
| ( "which test or tests to use" ); |
| |
| return cli; |
| } |
| |
| } // end namespace Catch |