Skip to content

Commit 42c11de

Browse files
committed
Auto merge of #55053 - Emerentius:test_all_again, r=alexcrichton
Add option to run all tests, again This is a repeat of #53527, which had to be reverted to land #54116. It will break clippy until `compiletest-rs` can be updated and I believe we're closing on a new release date, so this may need to be delayed again until after 1.30 is out (?) Closes #50363 again
2 parents 10f42cb + 420541b commit 42c11de

File tree

1 file changed

+119
-81
lines changed

1 file changed

+119
-81
lines changed

Diff for: src/libtest/lib.rs

+119-81
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ const QUIET_MODE_MAX_COLUMN: usize = 100; // insert a '\n' after 100 tests in qu
8989
// to be used by rustc to compile tests in libtest
9090
pub mod test {
9191
pub use {assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static,
92-
Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, ShouldPanic,
92+
Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, ShouldPanic,
9393
StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName,
9494
TestOpts, TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk};
9595
}
@@ -357,12 +357,19 @@ pub enum OutputFormat {
357357
Json,
358358
}
359359

360+
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
361+
pub enum RunIgnored {
362+
Yes,
363+
No,
364+
Only,
365+
}
366+
360367
#[derive(Debug)]
361368
pub struct TestOpts {
362369
pub list: bool,
363370
pub filter: Option<String>,
364371
pub filter_exact: bool,
365-
pub run_ignored: bool,
372+
pub run_ignored: RunIgnored,
366373
pub run_tests: bool,
367374
pub bench_benchmarks: bool,
368375
pub logfile: Option<PathBuf>,
@@ -381,7 +388,7 @@ impl TestOpts {
381388
list: false,
382389
filter: None,
383390
filter_exact: false,
384-
run_ignored: false,
391+
run_ignored: RunIgnored::No,
385392
run_tests: false,
386393
bench_benchmarks: false,
387394
logfile: None,
@@ -400,7 +407,8 @@ pub type OptRes = Result<TestOpts, String>;
400407

401408
fn optgroups() -> getopts::Options {
402409
let mut opts = getopts::Options::new();
403-
opts.optflag("", "ignored", "Run ignored tests")
410+
opts.optflag("", "include-ignored", "Run ignored and not ignored tests")
411+
.optflag("", "ignored", "Run only ignored tests")
404412
.optflag("", "test", "Run tests and not benchmarks")
405413
.optflag("", "bench", "Run benchmarks instead of tests")
406414
.optflag("", "list", "List all tests and benchmarks")
@@ -499,8 +507,8 @@ Test Attributes:
499507
contain: #[should_panic(expected = "foo")].
500508
#[ignore] - When applied to a function which is already attributed as a
501509
test, then the test runner will ignore these tests during
502-
normal test runs. Running with --ignored will run these
503-
tests."#,
510+
normal test runs. Running with --ignored or --include-ignored will run
511+
these tests."#,
504512
usage = options.usage(&message)
505513
);
506514
}
@@ -553,7 +561,21 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
553561
None
554562
};
555563

556-
let run_ignored = matches.opt_present("ignored");
564+
let include_ignored = matches.opt_present("include-ignored");
565+
if !allow_unstable && include_ignored {
566+
return Some(Err(
567+
"The \"include-ignored\" flag is only accepted on the nightly compiler".into()
568+
));
569+
}
570+
571+
let run_ignored = match (include_ignored, matches.opt_present("ignored")) {
572+
(true, true) => return Some(Err(
573+
"the options --include-ignored and --ignored are mutually exclusive".into()
574+
)),
575+
(true, false) => RunIgnored::Yes,
576+
(false, true) => RunIgnored::Only,
577+
(false, false) => RunIgnored::No,
578+
};
557579
let quiet = matches.opt_present("quiet");
558580
let exact = matches.opt_present("exact");
559581
let list = matches.opt_present("list");
@@ -1305,55 +1327,36 @@ fn get_concurrency() -> usize {
13051327

13061328
pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
13071329
let mut filtered = tests;
1308-
// Remove tests that don't match the test filter
1309-
filtered = match opts.filter {
1310-
None => filtered,
1311-
Some(ref filter) => filtered
1312-
.into_iter()
1313-
.filter(|test| {
1314-
if opts.filter_exact {
1315-
test.desc.name.as_slice() == &filter[..]
1316-
} else {
1317-
test.desc.name.as_slice().contains(&filter[..])
1318-
}
1319-
})
1320-
.collect(),
1330+
let matches_filter = |test: &TestDescAndFn, filter: &str| {
1331+
let test_name = test.desc.name.as_slice();
1332+
1333+
match opts.filter_exact {
1334+
true => test_name == filter,
1335+
false => test_name.contains(filter),
1336+
}
13211337
};
13221338

1323-
// Skip tests that match any of the skip filters
1324-
filtered = filtered
1325-
.into_iter()
1326-
.filter(|t| {
1327-
!opts.skip.iter().any(|sf| {
1328-
if opts.filter_exact {
1329-
t.desc.name.as_slice() == &sf[..]
1330-
} else {
1331-
t.desc.name.as_slice().contains(&sf[..])
1332-
}
1333-
})
1334-
})
1335-
.collect();
1339+
// Remove tests that don't match the test filter
1340+
if let Some(ref filter) = opts.filter {
1341+
filtered.retain(|test| matches_filter(test, filter));
1342+
}
13361343

1337-
// Maybe pull out the ignored test and unignore them
1338-
filtered = if !opts.run_ignored {
1339-
filtered
1340-
} else {
1341-
fn filter(test: TestDescAndFn) -> Option<TestDescAndFn> {
1342-
if test.desc.ignore {
1343-
let TestDescAndFn { desc, testfn } = test;
1344-
Some(TestDescAndFn {
1345-
desc: TestDesc {
1346-
ignore: false,
1347-
..desc
1348-
},
1349-
testfn,
1350-
})
1351-
} else {
1352-
None
1353-
}
1344+
// Skip tests that match any of the skip filters
1345+
filtered.retain(|test| {
1346+
!opts.skip.iter().any(|sf| matches_filter(test, sf))
1347+
});
1348+
1349+
// maybe unignore tests
1350+
match opts.run_ignored {
1351+
RunIgnored::Yes => {
1352+
filtered.iter_mut().for_each(|test| test.desc.ignore = false);
1353+
},
1354+
RunIgnored::Only => {
1355+
filtered.retain(|test| test.desc.ignore);
1356+
filtered.iter_mut().for_each(|test| test.desc.ignore = false);
13541357
}
1355-
filtered.into_iter().filter_map(filter).collect()
1356-
};
1358+
RunIgnored::No => {}
1359+
}
13571360

13581361
// Sort the tests alphabetically
13591362
filtered.sort_by(|t1, t2| t1.desc.name.as_slice().cmp(t2.desc.name.as_slice()));
@@ -1742,13 +1745,37 @@ pub mod bench {
17421745

17431746
#[cfg(test)]
17441747
mod tests {
1745-
use test::{filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, ShouldPanic,
1746-
StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed, TrFailedMsg,
1747-
TrIgnored, TrOk};
1748+
use test::{filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored,
1749+
ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailed,
1750+
TrFailedMsg, TrIgnored, TrOk};
17481751
use std::sync::mpsc::channel;
17491752
use bench;
17501753
use Bencher;
17511754

1755+
1756+
fn one_ignored_one_unignored_test() -> Vec<TestDescAndFn> {
1757+
vec![
1758+
TestDescAndFn {
1759+
desc: TestDesc {
1760+
name: StaticTestName("1"),
1761+
ignore: true,
1762+
should_panic: ShouldPanic::No,
1763+
allow_fail: false,
1764+
},
1765+
testfn: DynTestFn(Box::new(move || {})),
1766+
},
1767+
TestDescAndFn {
1768+
desc: TestDesc {
1769+
name: StaticTestName("2"),
1770+
ignore: false,
1771+
should_panic: ShouldPanic::No,
1772+
allow_fail: false,
1773+
},
1774+
testfn: DynTestFn(Box::new(move || {})),
1775+
},
1776+
]
1777+
}
1778+
17521779
#[test]
17531780
pub fn do_not_run_ignored_tests() {
17541781
fn f() {
@@ -1874,11 +1901,20 @@ mod tests {
18741901
"filter".to_string(),
18751902
"--ignored".to_string(),
18761903
];
1877-
let opts = match parse_opts(&args) {
1878-
Some(Ok(o)) => o,
1879-
_ => panic!("Malformed arg in parse_ignored_flag"),
1880-
};
1881-
assert!((opts.run_ignored));
1904+
let opts = parse_opts(&args).unwrap().unwrap();
1905+
assert_eq!(opts.run_ignored, RunIgnored::Only);
1906+
}
1907+
1908+
#[test]
1909+
fn parse_include_ignored_flag() {
1910+
let args = vec![
1911+
"progname".to_string(),
1912+
"filter".to_string(),
1913+
"-Zunstable-options".to_string(),
1914+
"--include-ignored".to_string(),
1915+
];
1916+
let opts = parse_opts(&args).unwrap().unwrap();
1917+
assert_eq!(opts.run_ignored, RunIgnored::Yes);
18821918
}
18831919

18841920
#[test]
@@ -1888,35 +1924,33 @@ mod tests {
18881924

18891925
let mut opts = TestOpts::new();
18901926
opts.run_tests = true;
1891-
opts.run_ignored = true;
1927+
opts.run_ignored = RunIgnored::Only;
18921928

1893-
let tests = vec![
1894-
TestDescAndFn {
1895-
desc: TestDesc {
1896-
name: StaticTestName("1"),
1897-
ignore: true,
1898-
should_panic: ShouldPanic::No,
1899-
allow_fail: false,
1900-
},
1901-
testfn: DynTestFn(Box::new(move || {})),
1902-
},
1903-
TestDescAndFn {
1904-
desc: TestDesc {
1905-
name: StaticTestName("2"),
1906-
ignore: false,
1907-
should_panic: ShouldPanic::No,
1908-
allow_fail: false,
1909-
},
1910-
testfn: DynTestFn(Box::new(move || {})),
1911-
},
1912-
];
1929+
let tests = one_ignored_one_unignored_test();
19131930
let filtered = filter_tests(&opts, tests);
19141931

19151932
assert_eq!(filtered.len(), 1);
19161933
assert_eq!(filtered[0].desc.name.to_string(), "1");
19171934
assert!(!filtered[0].desc.ignore);
19181935
}
19191936

1937+
#[test]
1938+
pub fn run_include_ignored_option() {
1939+
// When we "--include-ignored" tests, the ignore flag should be set to false on
1940+
// all tests and no test filtered out
1941+
1942+
let mut opts = TestOpts::new();
1943+
opts.run_tests = true;
1944+
opts.run_ignored = RunIgnored::Yes;
1945+
1946+
let tests = one_ignored_one_unignored_test();
1947+
let filtered = filter_tests(&opts, tests);
1948+
1949+
assert_eq!(filtered.len(), 2);
1950+
assert!(!filtered[0].desc.ignore);
1951+
assert!(!filtered[1].desc.ignore);
1952+
}
1953+
19201954
#[test]
19211955
pub fn exact_filter_match() {
19221956
fn tests() -> Vec<TestDescAndFn> {
@@ -2024,7 +2058,9 @@ mod tests {
20242058
"test::ignored_tests_result_in_ignored".to_string(),
20252059
"test::first_free_arg_should_be_a_filter".to_string(),
20262060
"test::parse_ignored_flag".to_string(),
2061+
"test::parse_include_ignored_flag".to_string(),
20272062
"test::filter_for_ignored_option".to_string(),
2063+
"test::run_include_ignored_option".to_string(),
20282064
"test::sort_tests".to_string(),
20292065
];
20302066
let tests = {
@@ -2055,6 +2091,8 @@ mod tests {
20552091
"test::first_free_arg_should_be_a_filter".to_string(),
20562092
"test::ignored_tests_result_in_ignored".to_string(),
20572093
"test::parse_ignored_flag".to_string(),
2094+
"test::parse_include_ignored_flag".to_string(),
2095+
"test::run_include_ignored_option".to_string(),
20582096
"test::sort_tests".to_string(),
20592097
];
20602098

0 commit comments

Comments
 (0)