/* * 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 #include 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( 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( 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