Skip to content

Commit 2c8db37

Browse files
committed
compiletest: Fix --exact test filtering
This fix only changes the behavior when using `--exact` test filtering, which was quite broken. Before this fix, the following runs 0 tests: $ ./x test tests/run-make/crate-loading -- --exact running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 431 filtered out; finished in 24.95µs With the fix the desired test is run: $ ./x test tests/run-make/crate-loading -- --exact running 1 tests test [run-make] tests/run-make/crate-loading ... ok Without `--exact` the set of tests run tests is unchanged. This still runs "too many" tests $ ./x test tests/run-make/crate-loading running 3 tests test [run-make] tests/run-make/crate-loading-crate-depends-on-itself ... ok test [run-make] tests/run-make/crate-loading-multiple-candidates ... ok test [run-make] tests/run-make/crate-loading ... ok This still runs the one and only right test: $ ./x test tests/ui/lint/unused/unused-allocation.rs running 1 tests test [ui] tests/ui/lint/unused/unused-allocation.rs ... ok
1 parent 7ad23f4 commit 2c8db37

File tree

3 files changed

+43
-8
lines changed

3 files changed

+43
-8
lines changed

src/tools/compiletest/src/directives.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,7 @@ pub(crate) fn make_test_description<R: Read>(
14461446
cache: &DirectivesCache,
14471447
name: String,
14481448
path: &Utf8Path,
1449+
filterable_path: Utf8PathBuf,
14491450
src: R,
14501451
test_revision: Option<&str>,
14511452
poisoned: &mut bool,
@@ -1520,7 +1521,7 @@ pub(crate) fn make_test_description<R: Read>(
15201521
_ => ShouldPanic::No,
15211522
};
15221523

1523-
CollectedTestDesc { name, ignore, ignore_message, should_panic }
1524+
CollectedTestDesc { name, filterable_path, ignore, ignore_message, should_panic }
15241525
}
15251526

15261527
fn ignore_cdb(config: &Config, line: &str) -> IgnoreDecision {

src/tools/compiletest/src/executor.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use std::num::NonZero;
1212
use std::sync::{Arc, Mutex, mpsc};
1313
use std::{env, hint, io, mem, panic, thread};
1414

15+
use camino::Utf8PathBuf;
16+
1517
use crate::common::{Config, TestPaths};
1618
use crate::output_capture::{self, ConsoleOut};
1719
use crate::panic_hook;
@@ -293,8 +295,12 @@ fn filter_tests(opts: &Config, tests: Vec<CollectedTest>) -> Vec<CollectedTest>
293295
let mut filtered = tests;
294296

295297
let matches_filter = |test: &CollectedTest, filter_str: &str| {
296-
let test_name = &test.desc.name;
297-
if opts.filter_exact { test_name == filter_str } else { test_name.contains(filter_str) }
298+
let filterable_path = test.desc.filterable_path.as_str();
299+
if opts.filter_exact {
300+
filterable_path == filter_str
301+
} else {
302+
filterable_path.contains(filter_str)
303+
}
298304
};
299305

300306
// Remove tests that don't match the test filter
@@ -339,6 +345,7 @@ pub(crate) struct CollectedTest {
339345
/// Information that was historically needed to create a libtest `TestDesc`.
340346
pub(crate) struct CollectedTestDesc {
341347
pub(crate) name: String,
348+
pub(crate) filterable_path: Utf8PathBuf,
342349
pub(crate) ignore: bool,
343350
pub(crate) ignore_message: Option<Cow<'static, str>>,
344351
pub(crate) should_panic: ShouldPanic,

src/tools/compiletest/src/lib.rs

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -317,18 +317,30 @@ pub fn parse_config(args: Vec<String>) -> Config {
317317
.free
318318
.iter()
319319
.map(|f| {
320+
// Here `f` is relative to `./tests/run-make`. So if you run
321+
//
322+
// ./x test tests/run-make/crate-loading
323+
//
324+
// then `f` is "crate-loading".
320325
let path = Utf8Path::new(f);
321326
let mut iter = path.iter().skip(1);
322327

323-
// We skip the test folder and check if the user passed `rmake.rs`.
324328
if iter.next().is_some_and(|s| s == "rmake.rs") && iter.next().is_none() {
329+
// Strip the "rmake.rs" suffix. For example, if `f` is
330+
// "crate-loading/rmake.rs" then this gives us "crate-loading".
325331
path.parent().unwrap().to_string()
326332
} else {
327333
f.to_string()
328334
}
329335
})
330336
.collect::<Vec<_>>()
331337
} else {
338+
// Note that the filters are relative to the root dir of the different test
339+
// suites. For example, with:
340+
//
341+
// ./x test tests/ui/lint/unused
342+
//
343+
// the filter is "lint/unused".
332344
matches.free.clone()
333345
};
334346
let compare_mode = matches.opt_str("compare-mode").map(|s| {
@@ -911,7 +923,8 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
911923
collector.tests.extend(revisions.into_iter().map(|revision| {
912924
// Create a test name and description to hand over to the executor.
913925
let src_file = fs::File::open(&test_path).expect("open test file to parse ignores");
914-
let test_name = make_test_name(&cx.config, testpaths, revision);
926+
let (test_name, filterable_path) =
927+
make_test_name_and_filterable_path(&cx.config, testpaths, revision);
915928
// Create a description struct for the test/revision.
916929
// This is where `ignore-*`/`only-*`/`needs-*` directives are handled,
917930
// because they historically needed to set the libtest ignored flag.
@@ -920,6 +933,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
920933
&cx.cache,
921934
test_name,
922935
&test_path,
936+
filterable_path,
923937
src_file,
924938
revision,
925939
&mut collector.poisoned,
@@ -1072,7 +1086,11 @@ impl Stamp {
10721086
}
10731087

10741088
/// Creates a name for this test/revision that can be handed over to the executor.
1075-
fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> String {
1089+
fn make_test_name_and_filterable_path(
1090+
config: &Config,
1091+
testpaths: &TestPaths,
1092+
revision: Option<&str>,
1093+
) -> (String, Utf8PathBuf) {
10761094
// Print the name of the file, relative to the sources root.
10771095
let path = testpaths.file.strip_prefix(&config.src_root).unwrap();
10781096
let debugger = match config.debugger {
@@ -1084,14 +1102,23 @@ fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>
10841102
None => String::new(),
10851103
};
10861104

1087-
format!(
1105+
let name = format!(
10881106
"[{}{}{}] {}{}",
10891107
config.mode,
10901108
debugger,
10911109
mode_suffix,
10921110
path,
10931111
revision.map_or("".to_string(), |rev| format!("#{}", rev))
1094-
)
1112+
);
1113+
1114+
// `path` is the full path from the repo root like, `tests/ui/foo/bar.rs`.
1115+
// Filtering is applied without the `tests/ui/` part, so strip that off.
1116+
// First strip of "tests" to make sure we don't have some unexpected path.
1117+
let mut filterable_path = path.strip_prefix("tests").unwrap().to_owned();
1118+
// Now strip of e.g. "ui" or "run-make" component.
1119+
filterable_path = filterable_path.components().skip(1).collect();
1120+
1121+
(name, filterable_path)
10951122
}
10961123

10971124
/// Checks that test discovery didn't find any tests whose name stem is a prefix

0 commit comments

Comments
 (0)