From 435b0abd49f3b0146b7c8710a26411be88d4a844 Mon Sep 17 00:00:00 2001 From: Emerentius Date: Mon, 20 Aug 2018 13:26:57 +0200 Subject: [PATCH 1/3] refactor filter_tests same behaviour, just shorter --- src/libtest/lib.rs | 66 ++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 43 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 060ea1ea9b132..5a0663f776b78 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1296,54 +1296,34 @@ fn get_concurrency() -> usize { pub fn filter_tests(opts: &TestOpts, tests: Vec) -> Vec { let mut filtered = tests; - // Remove tests that don't match the test filter - filtered = match opts.filter { - None => filtered, - Some(ref filter) => filtered - .into_iter() - .filter(|test| { - if opts.filter_exact { - test.desc.name.as_slice() == &filter[..] - } else { - test.desc.name.as_slice().contains(&filter[..]) - } - }) - .collect(), + let matches_filter = |test: &TestDescAndFn, filter: &str| { + let test_name = test.desc.name.as_slice(); + + match opts.filter_exact { + true => test_name == filter, + false => test_name.contains(filter), + } }; + // Remove tests that don't match the test filter + if let Some(ref filter) = opts.filter { + filtered.retain(|test| matches_filter(test, filter)); + } + // Skip tests that match any of the skip filters - filtered = filtered - .into_iter() - .filter(|t| { - !opts.skip.iter().any(|sf| { - if opts.filter_exact { - t.desc.name.as_slice() == &sf[..] - } else { - t.desc.name.as_slice().contains(&sf[..]) - } - }) - }) - .collect(); + filtered.retain(|test| { + !opts.skip.iter().any(|sf| matches_filter(test, sf)) + }); // Maybe pull out the ignored test and unignore them - filtered = if !opts.run_ignored { - filtered - } else { - fn filter(test: TestDescAndFn) -> Option { - if test.desc.ignore { - let TestDescAndFn { desc, testfn } = test; - Some(TestDescAndFn { - desc: TestDesc { - ignore: false, - ..desc - }, - testfn, - }) - } else { - None - } - } - filtered.into_iter().filter_map(filter).collect() + if opts.run_ignored { + filtered = filtered.into_iter() + .filter(|test| test.desc.ignore) + .map(|mut test| { + test.desc.ignore = false; + test + }) + .collect(); }; // Sort the tests alphabetically From 9adf26a5d09fcdbc423c2134fc0ef20dc3375f2e Mon Sep 17 00:00:00 2001 From: Emerentius Date: Mon, 20 Aug 2018 13:57:10 +0200 Subject: [PATCH 2/3] add option to run all tests add --all flag to libtest that runs ignored and not ignored tests --- src/libtest/lib.rs | 142 ++++++++++++++++++++++++++++++--------------- 1 file changed, 96 insertions(+), 46 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 5a0663f776b78..71207e8e408d1 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -80,7 +80,7 @@ const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in qu // to be used by rustc to compile tests in libtest pub mod test { pub use {assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static, - Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, ShouldPanic, + Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, ShouldPanic, StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, TestOpts, TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk}; } @@ -348,12 +348,19 @@ pub enum OutputFormat { Json, } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum RunIgnored { + Yes, + No, + Only, +} + #[derive(Debug)] pub struct TestOpts { pub list: bool, pub filter: Option, pub filter_exact: bool, - pub run_ignored: bool, + pub run_ignored: RunIgnored, pub run_tests: bool, pub bench_benchmarks: bool, pub logfile: Option, @@ -372,7 +379,7 @@ impl TestOpts { list: false, filter: None, filter_exact: false, - run_ignored: false, + run_ignored: RunIgnored::No, run_tests: false, bench_benchmarks: false, logfile: None, @@ -391,7 +398,8 @@ pub type OptRes = Result; fn optgroups() -> getopts::Options { let mut opts = getopts::Options::new(); - opts.optflag("", "ignored", "Run ignored tests") + opts.optflag("", "all", "Run ignored and not ignored tests") + .optflag("", "ignored", "Run only ignored tests") .optflag("", "test", "Run tests and not benchmarks") .optflag("", "bench", "Run benchmarks instead of tests") .optflag("", "list", "List all tests and benchmarks") @@ -490,8 +498,8 @@ Test Attributes: contain: #[should_panic(expected = "foo")]. #[ignore] - When applied to a function which is already attributed as a test, then the test runner will ignore these tests during - normal test runs. Running with --ignored will run these - tests."#, + normal test runs. Running with --ignored or --all will run + these tests."#, usage = options.usage(&message) ); } @@ -544,7 +552,14 @@ pub fn parse_opts(args: &[String]) -> Option { None }; - let run_ignored = matches.opt_present("ignored"); + let run_ignored = match (matches.opt_present("all"), matches.opt_present("ignored")) { + (true, true) => return Some(Err( + "the options --all and --ignored are mutually exclusive".into() + )), + (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"); @@ -1315,16 +1330,17 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec) -> Vec { + filtered.iter_mut().for_each(|test| test.desc.ignore = false); + }, + RunIgnored::Only => { + filtered.retain(|test| test.desc.ignore); + filtered.iter_mut().for_each(|test| test.desc.ignore = false); + } + RunIgnored::No => {} + } // Sort the tests alphabetically filtered.sort_by(|t1, t2| t1.desc.name.as_slice().cmp(t2.desc.name.as_slice())); @@ -1713,13 +1729,37 @@ pub mod bench { #[cfg(test)] mod tests { - use test::{filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, ShouldPanic, - StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg, - TrIgnored, TrOk}; + use test::{filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, + ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, + TrFailedMsg, TrIgnored, TrOk}; use std::sync::mpsc::channel; use bench; use Bencher; + + fn one_ignored_one_unignored_test() -> Vec { + vec![ + TestDescAndFn { + desc: TestDesc { + name: StaticTestName("1"), + ignore: true, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }, + TestDescAndFn { + desc: TestDesc { + name: StaticTestName("2"), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(move || {})), + }, + ] + } + #[test] pub fn do_not_run_ignored_tests() { fn f() { @@ -1845,11 +1885,19 @@ mod tests { "filter".to_string(), "--ignored".to_string(), ]; - let opts = match parse_opts(&args) { - Some(Ok(o)) => o, - _ => panic!("Malformed arg in parse_ignored_flag"), - }; - assert!((opts.run_ignored)); + let opts = parse_opts(&args).unwrap().unwrap(); + assert_eq!(opts.run_ignored, RunIgnored::Only); + } + + #[test] + fn parse_all_flag() { + let args = vec![ + "progname".to_string(), + "filter".to_string(), + "--all".to_string(), + ]; + let opts = parse_opts(&args).unwrap().unwrap(); + assert_eq!(opts.run_ignored, RunIgnored::Yes); } #[test] @@ -1859,28 +1907,9 @@ mod tests { let mut opts = TestOpts::new(); opts.run_tests = true; - opts.run_ignored = true; + opts.run_ignored = RunIgnored::Only; - let tests = vec![ - TestDescAndFn { - desc: TestDesc { - name: StaticTestName("1"), - ignore: true, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})), - }, - TestDescAndFn { - desc: TestDesc { - name: StaticTestName("2"), - ignore: false, - should_panic: ShouldPanic::No, - allow_fail: false, - }, - testfn: DynTestFn(Box::new(move || {})), - }, - ]; + let tests = one_ignored_one_unignored_test(); let filtered = filter_tests(&opts, tests); assert_eq!(filtered.len(), 1); @@ -1888,6 +1917,23 @@ mod tests { assert!(!filtered[0].desc.ignore); } + #[test] + pub fn run_all_option() { + // When we run "--all" tests, the ignore flag should be set to false on + // all tests and no test filtered out + + let mut opts = TestOpts::new(); + opts.run_tests = true; + opts.run_ignored = RunIgnored::Yes; + + let tests = one_ignored_one_unignored_test(); + let filtered = filter_tests(&opts, tests); + + assert_eq!(filtered.len(), 2); + assert!(!filtered[0].desc.ignore); + assert!(!filtered[1].desc.ignore); + } + #[test] pub fn exact_filter_match() { fn tests() -> Vec { @@ -1995,7 +2041,9 @@ mod tests { "test::ignored_tests_result_in_ignored".to_string(), "test::first_free_arg_should_be_a_filter".to_string(), "test::parse_ignored_flag".to_string(), + "test::parse_all_flag".to_string(), "test::filter_for_ignored_option".to_string(), + "test::run_all_option".to_string(), "test::sort_tests".to_string(), ]; let tests = { @@ -2025,7 +2073,9 @@ mod tests { "test::filter_for_ignored_option".to_string(), "test::first_free_arg_should_be_a_filter".to_string(), "test::ignored_tests_result_in_ignored".to_string(), + "test::parse_all_flag".to_string(), "test::parse_ignored_flag".to_string(), + "test::run_all_option".to_string(), "test::sort_tests".to_string(), ]; From f6f3228c5f284cfba89b6a70e0116f89663d0219 Mon Sep 17 00:00:00 2001 From: Emerentius Date: Wed, 5 Sep 2018 15:00:17 +0200 Subject: [PATCH 3/3] rename option to run all tests and make it unstable new name: --include-ignored requires -Zunstable-options --- src/libtest/lib.rs | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 71207e8e408d1..b18a7f4de31ee 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -398,7 +398,7 @@ pub type OptRes = Result; fn optgroups() -> getopts::Options { let mut opts = getopts::Options::new(); - opts.optflag("", "all", "Run ignored and not ignored tests") + opts.optflag("", "include-ignored", "Run ignored and not ignored tests") .optflag("", "ignored", "Run only ignored tests") .optflag("", "test", "Run tests and not benchmarks") .optflag("", "bench", "Run benchmarks instead of tests") @@ -498,7 +498,7 @@ Test Attributes: contain: #[should_panic(expected = "foo")]. #[ignore] - When applied to a function which is already attributed as a test, then the test runner will ignore these tests during - normal test runs. Running with --ignored or --all will run + normal test runs. Running with --ignored or --include-ignored will run these tests."#, usage = options.usage(&message) ); @@ -552,9 +552,16 @@ pub fn parse_opts(args: &[String]) -> Option { None }; - let run_ignored = match (matches.opt_present("all"), matches.opt_present("ignored")) { + let include_ignored = matches.opt_present("include-ignored"); + if !allow_unstable && include_ignored { + return Some(Err( + "The \"include-ignored\" flag is only accepted on the nightly compiler".into() + )); + } + + let run_ignored = match (include_ignored, matches.opt_present("ignored")) { (true, true) => return Some(Err( - "the options --all and --ignored are mutually exclusive".into() + "the options --include-ignored and --ignored are mutually exclusive".into() )), (true, false) => RunIgnored::Yes, (false, true) => RunIgnored::Only, @@ -1890,11 +1897,12 @@ mod tests { } #[test] - fn parse_all_flag() { + fn parse_include_ignored_flag() { let args = vec![ "progname".to_string(), "filter".to_string(), - "--all".to_string(), + "-Zunstable-options".to_string(), + "--include-ignored".to_string(), ]; let opts = parse_opts(&args).unwrap().unwrap(); assert_eq!(opts.run_ignored, RunIgnored::Yes); @@ -1918,8 +1926,8 @@ mod tests { } #[test] - pub fn run_all_option() { - // When we run "--all" tests, the ignore flag should be set to false on + pub fn run_include_ignored_option() { + // When we "--include-ignored" tests, the ignore flag should be set to false on // all tests and no test filtered out let mut opts = TestOpts::new(); @@ -2041,9 +2049,9 @@ mod tests { "test::ignored_tests_result_in_ignored".to_string(), "test::first_free_arg_should_be_a_filter".to_string(), "test::parse_ignored_flag".to_string(), - "test::parse_all_flag".to_string(), + "test::parse_include_ignored_flag".to_string(), "test::filter_for_ignored_option".to_string(), - "test::run_all_option".to_string(), + "test::run_include_ignored_option".to_string(), "test::sort_tests".to_string(), ]; let tests = { @@ -2073,9 +2081,9 @@ mod tests { "test::filter_for_ignored_option".to_string(), "test::first_free_arg_should_be_a_filter".to_string(), "test::ignored_tests_result_in_ignored".to_string(), - "test::parse_all_flag".to_string(), "test::parse_ignored_flag".to_string(), - "test::run_all_option".to_string(), + "test::parse_include_ignored_flag".to_string(), + "test::run_include_ignored_option".to_string(), "test::sort_tests".to_string(), ];