diff options
| author | Jeremy Fitzhardinge <jsgf@fb.com> | 2016-12-05 13:12:00 -0800 |
|---|---|---|
| committer | Jeremy Fitzhardinge <jsgf@fb.com> | 2016-12-05 14:36:58 -0800 |
| commit | 5bf4d6fbc0ca467f16537a5e440fda35d0e2780b (patch) | |
| tree | c0e9cfbac0e9fccd987b51be08f1da4af3c6a215 /src/libtest | |
| parent | d346dbc938da2f8d1bd13492331d9ec1b15bdac7 (diff) | |
| download | rust-5bf4d6fbc0ca467f16537a5e440fda35d0e2780b.tar.gz rust-5bf4d6fbc0ca467f16537a5e440fda35d0e2780b.zip | |
libtest: add --exact to make filter matching exact
Filter matching is by substring by default. This makes it impossible to run a single test if its name is a substring of some other test. For example, its not possible to run just "mymod::test" with these tests: mymod::test mymod::test1 mymod::test_module::moretests You could declare by convention that no test has a name that's a substring of another test, but that's not really practical. This PR adds the "--exact" flag, to make filter matching exactly match the complete name.
Diffstat (limited to 'src/libtest')
| -rw-r--r-- | src/libtest/lib.rs | 92 |
1 files changed, 90 insertions, 2 deletions
diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 142ae86c6a3..5749459a054 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -301,6 +301,7 @@ pub enum ColorConfig { pub struct TestOpts { pub filter: Option<String>, + pub filter_exact: bool, pub run_ignored: bool, pub run_tests: bool, pub bench_benchmarks: bool, @@ -317,6 +318,7 @@ impl TestOpts { fn new() -> TestOpts { TestOpts { filter: None, + filter_exact: false, run_ignored: false, run_tests: false, bench_benchmarks: false, @@ -348,6 +350,7 @@ fn optgroups() -> Vec<getopts::OptGroup> { getopts::optmulti("", "skip", "Skip tests whose names contain FILTER (this flag can \ be used multiple times)","FILTER"), getopts::optflag("q", "quiet", "Display one character per test instead of one line"), + getopts::optflag("", "exact", "Exactly match filters rather than by substring"), getopts::optopt("", "color", "Configure coloring of output: auto = colorize if stdout is a tty and tests are run on serially (default); always = always colorize output; @@ -407,6 +410,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> { let run_ignored = matches.opt_present("ignored"); let quiet = matches.opt_present("quiet"); + let exact = matches.opt_present("exact"); let logfile = matches.opt_str("logfile"); let logfile = logfile.map(|s| PathBuf::from(&s)); @@ -448,6 +452,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> { let test_opts = TestOpts { filter: filter, + filter_exact: exact, run_ignored: run_ignored, run_tests: run_tests, bench_benchmarks: bench_benchmarks, @@ -1118,14 +1123,26 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA None => filtered, Some(ref filter) => { filtered.into_iter() - .filter(|test| test.desc.name.as_slice().contains(&filter[..])) + .filter(|test| { + if opts.filter_exact { + test.desc.name.as_slice() == &filter[..] + } else { + test.desc.name.as_slice().contains(&filter[..]) + } + }) .collect() } }; // Skip tests that match any of the skip filters filtered = filtered.into_iter() - .filter(|t| !opts.skip.iter().any(|sf| t.desc.name.as_slice().contains(&sf[..]))) + .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(); // Maybe pull out the ignored test and unignore them @@ -1655,6 +1672,77 @@ mod tests { } #[test] + pub fn exact_filter_match() { + fn tests() -> Vec<TestDescAndFn> { + vec!["base", + "base::test", + "base::test1", + "base::test2", + ].into_iter() + .map(|name| TestDescAndFn { + desc: TestDesc { + name: StaticTestName(name), + ignore: false, + should_panic: ShouldPanic::No, + }, + testfn: DynTestFn(Box::new(move |()| {})) + }) + .collect() + } + + let substr = filter_tests(&TestOpts { + filter: Some("base".into()), + ..TestOpts::new() + }, tests()); + assert_eq!(substr.len(), 4); + + let substr = filter_tests(&TestOpts { + filter: Some("bas".into()), + ..TestOpts::new() + }, tests()); + assert_eq!(substr.len(), 4); + + let substr = filter_tests(&TestOpts { + filter: Some("::test".into()), + ..TestOpts::new() + }, tests()); + assert_eq!(substr.len(), 3); + + let substr = filter_tests(&TestOpts { + filter: Some("base::test".into()), + ..TestOpts::new() + }, tests()); + assert_eq!(substr.len(), 3); + + let exact = filter_tests(&TestOpts { + filter: Some("base".into()), + filter_exact: true, ..TestOpts::new() + }, tests()); + assert_eq!(exact.len(), 1); + + let exact = filter_tests(&TestOpts { + filter: Some("bas".into()), + filter_exact: true, + ..TestOpts::new() + }, tests()); + assert_eq!(exact.len(), 0); + + let exact = filter_tests(&TestOpts { + filter: Some("::test".into()), + filter_exact: true, + ..TestOpts::new() + }, tests()); + assert_eq!(exact.len(), 0); + + let exact = filter_tests(&TestOpts { + filter: Some("base::test".into()), + filter_exact: true, + ..TestOpts::new() + }, tests()); + assert_eq!(exact.len(), 1); + } + + #[test] pub fn sort_tests() { let mut opts = TestOpts::new(); opts.run_tests = true; |
