mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-30 09:13:29 +01:00
e340ab8db6
* Units from <ratio> are no longer redeclared in our own namespace * The default clock is `steady_clock`, not `high_resolution_clock`, because, as HH says "high_resolution_clock is useless. If you want measure the passing of time, use steady_clock. If you want user friendly time, use system_clock". * Benchmarking support is opt-in, not opt-out, to avoid the large (~10%) compile time penalty. * Benchmarking-related options in CLI are always present, to decrease the amount of code that is only compiled conditionally and making the whole shebang more maintainble.
218 lines
9.8 KiB
C++
218 lines
9.8 KiB
C++
/*
|
|
* 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.benchmarkSamples, "samples" )
|
|
["--benchmark-samples"]
|
|
( "number of samples to collect (default: 100)" )
|
|
| Opt( config.benchmarkResamples, "resamples" )
|
|
["--benchmark-resamples"]
|
|
( "number of resamples for the bootstrap (default: 100000)" )
|
|
| Opt( config.benchmarkConfidenceInterval, "confidence interval" )
|
|
["--benchmark-confidence-interval"]
|
|
( "confidence interval for the bootstrap (between 0 and 1, default: 0.95)" )
|
|
| Opt( config.benchmarkNoAnalysis )
|
|
["--benchmark-no-analysis"]
|
|
( "perform only measurements; do not perform any analysis" )
|
|
| Arg( config.testsOrTags, "test name|pattern|tags" )
|
|
( "which test or tests to use" );
|
|
|
|
return cli;
|
|
}
|
|
|
|
} // end namespace Catch
|