diff options
| author | Igor Aleksanov <popzxc@yandex.ru> | 2019-10-17 19:10:17 +0300 |
|---|---|---|
| committer | Igor Aleksanov <popzxc@yandex.ru> | 2019-10-17 19:10:17 +0300 |
| commit | ddc6a5fd0e3e56f2ccbc576fdeed149579f141de (patch) | |
| tree | e12a83fca9664444d8952e13dcb64b6a84712e9e /src/libtest | |
| parent | 12397e9dd5a97460d76c884d449ca1c2d26da8ed (diff) | |
| download | rust-ddc6a5fd0e3e56f2ccbc576fdeed149579f141de.tar.gz rust-ddc6a5fd0e3e56f2ccbc576fdeed149579f141de.zip | |
Split options parsing into several functions
Diffstat (limited to 'src/libtest')
| -rw-r--r-- | src/libtest/cli.rs | 302 |
1 files changed, 179 insertions, 123 deletions
diff --git a/src/libtest/cli.rs b/src/libtest/cli.rs index b35193701d6..0c47bc8ae94 100644 --- a/src/libtest/cli.rs +++ b/src/libtest/cli.rs @@ -40,7 +40,7 @@ impl TestOpts { /// Result of parsing the options. pub type OptRes = Result<TestOpts, String>; /// Result of parsing the option part. -type OptPartRes<T> = Result<Option<T>, String>; +type OptPartRes<T> = Result<T, String>; fn optgroups() -> getopts::Options { let mut opts = getopts::Options::new(); @@ -186,14 +186,30 @@ Test Attributes: ); } -// FIXME: Copied from libsyntax until linkage errors are resolved. Issue #47566 -fn is_nightly() -> bool { - // Whether this is a feature-staged build, i.e., on the beta or stable channel - let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); - // Whether we should enable unstable features for bootstrapping - let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok(); +/// Parses command line arguments into test options. +/// Returns `None` if help was requested (since we only show help message and don't run tests), +/// returns `Some(Err(..))` if provided arguments are incorrect, +/// otherwise creates a `TestOpts` object and returns it. +pub fn parse_opts(args: &[String]) -> Option<OptRes> { + // Parse matches. + let opts = optgroups(); + let args = args.get(1..).unwrap_or(args); + let matches = match opts.parse(args) { + Ok(m) => m, + Err(f) => return Some(Err(f.to_string())), + }; - bootstrap || !disable_unstable_features + // Check if help was requested. + if matches.opt_present("h") { + // Show help and do nothing more. + usage(&args[0], &opts); + return None; + } + + // Actually parse the opts. + let opts_result = parse_opts_impl(matches); + + Some(opts_result) } // Gets the option value and checks if unstable features are enabled. @@ -201,21 +217,80 @@ macro_rules! unstable_optflag { ($matches:ident, $allow_unstable:ident, $option_name:literal) => {{ let opt = $matches.opt_present($option_name); if !$allow_unstable && opt { - return Some(Err(format!( + return Err(format!( "The \"{}\" flag is only accepted on the nightly compiler", $option_name - ))); + )); } opt }}; } +// Implementation of `parse_opts` that doesn't care about help message +// and returns a `Result`. +fn parse_opts_impl(matches: getopts::Matches) -> OptRes { + let allow_unstable = get_allow_unstable(&matches)?; + + // Unstable flags + let exclude_should_panic = unstable_optflag!(matches, allow_unstable, "exclude-should-panic"); + let include_ignored = unstable_optflag!(matches, allow_unstable, "include-ignored"); + let time_options = get_time_options(&matches, allow_unstable)?; + + let quiet = matches.opt_present("quiet"); + let exact = matches.opt_present("exact"); + let list = matches.opt_present("list"); + let skip = matches.opt_strs("skip"); + + let bench_benchmarks = matches.opt_present("bench"); + let run_tests = !bench_benchmarks || matches.opt_present("test"); + + let logfile = get_log_file(&matches)?; + let run_ignored = get_run_ignored(&matches, include_ignored)?; + let filter = get_filter(&matches)?; + let nocapture = get_nocapture(&matches)?; + let test_threads = get_test_threads(&matches)?; + let color = get_color_config(&matches)?; + let format = get_format(&matches, quiet, allow_unstable)?; + + let options = Options::new().display_output(matches.opt_present("show-output")); + + let test_opts = TestOpts { + list, + filter, + filter_exact: exact, + exclude_should_panic, + run_ignored, + run_tests, + bench_benchmarks, + logfile, + nocapture, + color, + format, + test_threads, + skip, + time_options, + options, + }; + + Ok(test_opts) +} + +// FIXME: Copied from libsyntax until linkage errors are resolved. Issue #47566 +fn is_nightly() -> bool { + // Whether this is a feature-staged build, i.e., on the beta or stable channel + let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); + // Whether we should enable unstable features for bootstrapping + let bootstrap = env::var("RUSTC_BOOTSTRAP").is_ok(); + + bootstrap || !disable_unstable_features +} + // Gets the CLI options assotiated with `report-time` feature. fn get_time_options( matches: &getopts::Matches, allow_unstable: bool) --> Option<OptPartRes<TestTimeOptions>> { +-> OptPartRes<Option<TestTimeOptions>> { let report_time = unstable_optflag!(matches, allow_unstable, "report-time"); let colored_opt_str = matches.opt_str("report-time"); let mut report_time_colored = report_time && colored_opt_str == Some("colored".into()); @@ -232,71 +307,73 @@ fn get_time_options( None }; - Some(Ok(options)) + Ok(options) } -// Parses command line arguments into test options -pub fn parse_opts(args: &[String]) -> Option<OptRes> { - let mut allow_unstable = false; - let opts = optgroups(); - let args = args.get(1..).unwrap_or(args); - let matches = match opts.parse(args) { - Ok(m) => m, - Err(f) => return Some(Err(f.to_string())), +fn get_test_threads(matches: &getopts::Matches) -> OptPartRes<Option<usize>> { + let test_threads = match matches.opt_str("test-threads") { + Some(n_str) => match n_str.parse::<usize>() { + Ok(0) => return Err("argument for --test-threads must not be 0".to_string()), + Ok(n) => Some(n), + Err(e) => { + return Err(format!( + "argument for --test-threads must be a number > 0 \ + (error: {})", + e + )); + } + }, + None => None, }; - if let Some(opt) = matches.opt_str("Z") { - if !is_nightly() { - return Some(Err( - "the option `Z` is only accepted on the nightly compiler".into(), - )); - } + Ok(test_threads) +} - match &*opt { - "unstable-options" => { - allow_unstable = true; - } - _ => { - return Some(Err("Unrecognized option to `Z`".into())); +fn get_format(matches: &getopts::Matches, quiet: bool, allow_unstable: bool) -> OptPartRes<OutputFormat> { + let format = match matches.opt_str("format").as_ref().map(|s| &**s) { + None if quiet => OutputFormat::Terse, + Some("pretty") | None => OutputFormat::Pretty, + Some("terse") => OutputFormat::Terse, + Some("json") => { + if !allow_unstable { + return Err( + "The \"json\" format is only accepted on the nightly compiler".into(), + ); } + OutputFormat::Json } - }; - if matches.opt_present("h") { - usage(&args[0], &opts); - return None; - } - - let filter = if !matches.free.is_empty() { - Some(matches.free[0].clone()) - } else { - None + Some(v) => { + return Err(format!( + "argument for --format must be pretty, terse, or json (was \ + {})", + v + )); + } }; - let exclude_should_panic = unstable_optflag!(matches, allow_unstable, "exclude-should-panic"); + Ok(format) +} - let include_ignored = unstable_optflag!(matches, allow_unstable, "include-ignored"); +fn get_color_config(matches: &getopts::Matches) -> OptPartRes<ColorConfig> { + let color = match matches.opt_str("color").as_ref().map(|s| &**s) { + Some("auto") | None => ColorConfig::AutoColor, + Some("always") => ColorConfig::AlwaysColor, + Some("never") => ColorConfig::NeverColor, - let run_ignored = match (include_ignored, matches.opt_present("ignored")) { - (true, true) => { - return Some(Err( - "the options --include-ignored and --ignored are mutually exclusive".into(), + Some(v) => { + return Err(format!( + "argument for --color must be auto, always, or never (was \ + {})", + v )); } - (true, false) => RunIgnored::Yes, - (false, true) => RunIgnored::Only, - (false, false) => RunIgnored::No, }; - let quiet = matches.opt_present("quiet"); - let exact = matches.opt_present("exact"); - let list = matches.opt_present("list"); - let logfile = matches.opt_str("logfile"); - let logfile = logfile.map(|s| PathBuf::from(&s)); - - let bench_benchmarks = matches.opt_present("bench"); - let run_tests = !bench_benchmarks || matches.opt_present("test"); + Ok(color) +} +fn get_nocapture(matches: &getopts::Matches) -> OptPartRes<bool> { let mut nocapture = matches.opt_present("nocapture"); if !nocapture { nocapture = match env::var("RUST_TEST_NOCAPTURE") { @@ -305,80 +382,59 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> { }; } - let time_options = match get_time_options(&matches, allow_unstable) { - Some(Ok(val)) => val, - Some(Err(e)) => return Some(Err(e)), - None => panic!("Unexpected output from `get_time_options`"), - }; + Ok(nocapture) +} - let test_threads = match matches.opt_str("test-threads") { - Some(n_str) => match n_str.parse::<usize>() { - Ok(0) => return Some(Err("argument for --test-threads must not be 0".to_string())), - Ok(n) => Some(n), - Err(e) => { - return Some(Err(format!( - "argument for --test-threads must be a number > 0 \ - (error: {})", - e - ))); - } - }, - None => None, +fn get_run_ignored(matches: &getopts::Matches, include_ignored: bool) -> OptPartRes<RunIgnored> { + let run_ignored = match (include_ignored, matches.opt_present("ignored")) { + (true, true) => { + return Err( + "the options --include-ignored and --ignored are mutually exclusive".into(), + ); + } + (true, false) => RunIgnored::Yes, + (false, true) => RunIgnored::Only, + (false, false) => RunIgnored::No, }; - let color = match matches.opt_str("color").as_ref().map(|s| &**s) { - Some("auto") | None => ColorConfig::AutoColor, - Some("always") => ColorConfig::AlwaysColor, - Some("never") => ColorConfig::NeverColor, + Ok(run_ignored) +} - Some(v) => { - return Some(Err(format!( - "argument for --color must be auto, always, or never (was \ - {})", - v - ))); - } +fn get_filter(matches: &getopts::Matches) -> OptPartRes<Option<String>> { + let filter = if !matches.free.is_empty() { + Some(matches.free[0].clone()) + } else { + None }; - let format = match matches.opt_str("format").as_ref().map(|s| &**s) { - None if quiet => OutputFormat::Terse, - Some("pretty") | None => OutputFormat::Pretty, - Some("terse") => OutputFormat::Terse, - Some("json") => { - if !allow_unstable { - return Some(Err( - "The \"json\" format is only accepted on the nightly compiler".into(), - )); - } - OutputFormat::Json + Ok(filter) +} + +fn get_allow_unstable(matches: &getopts::Matches) -> OptPartRes<bool> { + let mut allow_unstable = false; + + if let Some(opt) = matches.opt_str("Z") { + if !is_nightly() { + return Err( + "the option `Z` is only accepted on the nightly compiler".into(), + ); } - Some(v) => { - return Some(Err(format!( - "argument for --format must be pretty, terse, or json (was \ - {})", - v - ))); + match &*opt { + "unstable-options" => { + allow_unstable = true; + } + _ => { + return Err("Unrecognized option to `Z`".into()); + } } }; - let test_opts = TestOpts { - list, - filter, - filter_exact: exact, - exclude_should_panic, - run_ignored, - run_tests, - bench_benchmarks, - logfile, - nocapture, - color, - format, - test_threads, - skip: matches.opt_strs("skip"), - time_options, - options: Options::new().display_output(matches.opt_present("show-output")), - }; + Ok(allow_unstable) +} + +fn get_log_file(matches: &getopts::Matches) -> OptPartRes<Option<PathBuf>> { + let logfile = matches.opt_str("logfile").map(|s| PathBuf::from(&s)); - Some(Ok(test_opts)) + Ok(logfile) } |
