Skip to content

Commit 360186b

Browse files
committed
Auto merge of rust-lang#2166 - RalfJung:tests, r=oli-obk
ui_test tweaks - support multiple filters - make `./miri check` also cover ui_test - Run opt-level=4 tests again, but only the "run" tests r? `@oli-obk`
2 parents aa589d3 + 962957f commit 360186b

File tree

5 files changed

+72
-44
lines changed

5 files changed

+72
-44
lines changed

ci.sh

+1-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ function run_tests {
2626
# optimizations up all the way).
2727
# Optimizations change diagnostics (mostly backtraces), so we don't check them
2828
#FIXME(#2155): we want to only run the pass and panic tests here, not the fail tests.
29-
#MIRIFLAGS="-O -Zmir-opt-level=4" MIRI_SKIP_UI_CHECKS=1 ./miri test --locked
30-
true
29+
MIRIFLAGS="-O -Zmir-opt-level=4" MIRI_SKIP_UI_CHECKS=1 ./miri test --locked -- tests/{run-pass,run-fail}
3130
fi
3231

3332
# On Windows, there is always "python", not "python3" or "python2".

miri

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ install|install-debug)
115115
;;
116116
check|check-debug)
117117
# Check, and let caller control flags.
118-
cargo check $CARGO_BUILD_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml "$@"
118+
cargo check $CARGO_BUILD_FLAGS --manifest-path "$MIRIDIR"/Cargo.toml --all-targets "$@"
119119
cargo check $CARGO_BUILD_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml "$@"
120120
;;
121121
build|build-debug)

tests/compiletest.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ fn run_tests(mode: Mode, path: &str, target: Option<String>) {
4747
(true, true) => panic!("cannot use MIRI_BLESS and MIRI_SKIP_UI_CHECKS at the same time"),
4848
};
4949

50-
let path_filter = std::env::args().skip(1).next();
50+
// Pass on all arguments as filters.
51+
let path_filter = std::env::args().skip(1);
5152

5253
let config = Config {
5354
args: flags,
@@ -56,7 +57,7 @@ fn run_tests(mode: Mode, path: &str, target: Option<String>) {
5657
stdout_filters: STDOUT.clone(),
5758
root_dir: PathBuf::from(path),
5859
mode,
59-
path_filter,
60+
path_filter: path_filter.collect(),
6061
program: miri_path(),
6162
output_conflict_handling,
6263
};
@@ -105,8 +106,6 @@ regexes! {
105106
r"\\" => "/",
106107
// erase platform file paths
107108
"sys/[a-z]+/" => "sys/PLATFORM/",
108-
// erase error annotations in tests
109-
r"\s*//~.*" => "",
110109
}
111110

112111
fn ui(mode: Mode, path: &str) {

ui_test/src/lib.rs

+56-29
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ pub struct Config {
3030
pub mode: Mode,
3131
pub program: PathBuf,
3232
pub output_conflict_handling: OutputConflictHandling,
33-
/// Only run tests with this string in their path/name
34-
pub path_filter: Option<String>,
33+
/// Only run tests with one of these strings in their path/name
34+
pub path_filter: Vec<String>,
3535
}
3636

3737
#[derive(Debug)]
@@ -61,6 +61,7 @@ pub fn run_tests(config: Config) {
6161
let failures = Mutex::new(vec![]);
6262
let succeeded = AtomicUsize::default();
6363
let ignored = AtomicUsize::default();
64+
let filtered = AtomicUsize::default();
6465

6566
crossbeam::scope(|s| {
6667
for _ in 0..std::thread::available_parallelism().unwrap().get() {
@@ -77,22 +78,22 @@ pub fn run_tests(config: Config) {
7778
if !path.extension().map(|ext| ext == "rs").unwrap_or(false) {
7879
continue;
7980
}
80-
if let Some(path_filter) = &config.path_filter {
81-
if !path.display().to_string().contains(path_filter) {
82-
ignored.fetch_add(1, Ordering::Relaxed);
83-
eprintln!(
84-
"{} .. {}",
85-
path.display(),
86-
"ignored (command line filter)".yellow()
87-
);
81+
if !config.path_filter.is_empty() {
82+
let path_display = path.display().to_string();
83+
if !config.path_filter.iter().any(|filter| path_display.contains(filter)) {
84+
filtered.fetch_add(1, Ordering::Relaxed);
8885
continue;
8986
}
9087
}
9188
let comments = Comments::parse_file(&path);
9289
// Ignore file if only/ignore rules do (not) apply
9390
if ignore_file(&comments, &target) {
9491
ignored.fetch_add(1, Ordering::Relaxed);
95-
eprintln!("{} .. {}", path.display(), "ignored".yellow());
92+
eprintln!(
93+
"{} ... {}",
94+
path.display(),
95+
"ignored (in-test comment)".yellow()
96+
);
9697
continue;
9798
}
9899
// Run the test for all revisions
@@ -101,7 +102,7 @@ pub fn run_tests(config: Config) {
101102
{
102103
let (m, errors) = run_test(&path, &config, &target, &revision, &comments);
103104

104-
// Using `format` to prevent messages from threads from getting intermingled.
105+
// Using a single `eprintln!` to prevent messages from threads from getting intermingled.
105106
let mut msg = format!("{} ", path.display());
106107
if !revision.is_empty() {
107108
write!(msg, "(revision `{revision}`) ").unwrap();
@@ -125,6 +126,7 @@ pub fn run_tests(config: Config) {
125126
let failures = failures.into_inner().unwrap();
126127
let succeeded = succeeded.load(Ordering::Relaxed);
127128
let ignored = ignored.load(Ordering::Relaxed);
129+
let filtered = filtered.load(Ordering::Relaxed);
128130
if !failures.is_empty() {
129131
for (path, miri, revision, errors) in &failures {
130132
eprintln!();
@@ -168,19 +170,22 @@ pub fn run_tests(config: Config) {
168170
}
169171
}
170172
eprintln!(
171-
"{} tests failed, {} tests passed, {} ignored",
173+
"test result: {}. {} tests failed, {} tests passed, {} ignored, {} filtered out",
174+
"FAIL".red(),
172175
failures.len().to_string().red().bold(),
173176
succeeded.to_string().green(),
174-
ignored.to_string().yellow()
177+
ignored.to_string().yellow(),
178+
filtered.to_string().yellow(),
175179
);
176180
std::process::exit(1);
177181
}
178182
eprintln!();
179183
eprintln!(
180-
"test result: {}. {} tests passed, {} ignored",
184+
"test result: {}. {} tests passed, {} ignored, {} filtered out",
181185
"ok".green(),
182186
succeeded.to_string().green(),
183-
ignored.to_string().yellow()
187+
ignored.to_string().yellow(),
188+
filtered.to_string().yellow(),
184189
);
185190
eprintln!();
186191
}
@@ -230,6 +235,34 @@ fn run_test(
230235
}
231236
let output = miri.output().expect("could not execute miri");
232237
let mut errors = config.mode.ok(output.status);
238+
check_test_result(
239+
path,
240+
config,
241+
target,
242+
revision,
243+
comments,
244+
&mut errors,
245+
&output.stdout,
246+
&output.stderr,
247+
);
248+
(miri, errors)
249+
}
250+
251+
fn check_test_result(
252+
path: &Path,
253+
config: &Config,
254+
target: &str,
255+
revision: &str,
256+
comments: &Comments,
257+
errors: &mut Errors,
258+
stdout: &[u8],
259+
stderr: &[u8],
260+
) {
261+
// Always remove annotation comments from stderr.
262+
let annotations = Regex::new(r"\s*//~.*").unwrap();
263+
let stderr = std::str::from_utf8(stderr).unwrap();
264+
let stderr = annotations.replace_all(stderr, "");
265+
let stdout = std::str::from_utf8(stdout).unwrap();
233266
// Check output files (if any)
234267
let revised = |extension: &str| {
235268
if revision.is_empty() {
@@ -240,41 +273,36 @@ fn run_test(
240273
};
241274
// Check output files against actual output
242275
check_output(
243-
&output.stderr,
276+
&stderr,
244277
path,
245-
&mut errors,
278+
errors,
246279
revised("stderr"),
247280
target,
248281
&config.stderr_filters,
249282
&config,
250283
comments,
251284
);
252285
check_output(
253-
&output.stdout,
286+
&stdout,
254287
path,
255-
&mut errors,
288+
errors,
256289
revised("stdout"),
257290
target,
258291
&config.stdout_filters,
259292
&config,
260293
comments,
261294
);
262295
// Check error annotations in the source against output
263-
check_annotations(&output.stderr, &mut errors, config, revision, comments);
264-
(miri, errors)
296+
check_annotations(&stderr, errors, config, revision, comments);
265297
}
266298

267299
fn check_annotations(
268-
unnormalized_stderr: &[u8],
300+
unnormalized_stderr: &str,
269301
errors: &mut Errors,
270302
config: &Config,
271303
revision: &str,
272304
comments: &Comments,
273305
) {
274-
let unnormalized_stderr = std::str::from_utf8(unnormalized_stderr).unwrap();
275-
// erase annotations from the stderr so they don't match themselves
276-
let annotations = Regex::new(r"\s*//~.*").unwrap();
277-
let unnormalized_stderr = annotations.replace(unnormalized_stderr, "");
278306
let mut found_annotation = false;
279307
if let Some((ref error_pattern, definition_line)) = comments.error_pattern {
280308
if !unnormalized_stderr.contains(error_pattern) {
@@ -312,7 +340,7 @@ fn check_annotations(
312340
}
313341

314342
fn check_output(
315-
output: &[u8],
343+
output: &str,
316344
path: &Path,
317345
errors: &mut Errors,
318346
kind: String,
@@ -321,7 +349,6 @@ fn check_output(
321349
config: &Config,
322350
comments: &Comments,
323351
) {
324-
let output = std::str::from_utf8(&output).unwrap();
325352
let output = normalize(path, output, filters, comments);
326353
let path = output_path(path, comments, kind, target);
327354
match config.output_conflict_handling {

ui_test/src/tests.rs

+11-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
use std::path::{Path, PathBuf};
22

3-
use super::{check_annotations, Comments, Config, Error, Mode, OutputConflictHandling};
3+
use super::*;
44

55
fn config() -> Config {
66
Config {
77
args: vec![],
88
target: None,
99
stderr_filters: vec![],
1010
stdout_filters: vec![],
11-
root_dir: PathBuf::from("."),
11+
root_dir: PathBuf::from("$RUSTROOT"),
1212
mode: Mode::Fail,
13-
path_filter: None,
13+
path_filter: vec![],
1414
program: PathBuf::from("cake"),
1515
output_conflict_handling: OutputConflictHandling::Error,
1616
}
@@ -25,10 +25,12 @@ fn main() {
2525
let _x: &i32 = unsafe { mem::transmute(16usize) }; //~ ERROR encountered a dangling reference (address $HEX is unallocated)
2626
}
2727
";
28-
let comments = Comments::parse(Path::new("<dummy>"), s);
28+
let path = Path::new("$DIR/<dummy>");
29+
let comments = Comments::parse(&path, s);
2930
let mut errors = vec![];
3031
let config = config();
31-
let unnormalized_stderr = r"
32+
// Crucially, the intended error string *does* appear in this output, as a quote of the comment itself.
33+
let stderr = br"
3234
error: Undefined Behavior: type validation failed: encountered a dangling reference (address 0x10 is unallocated)
3335
--> tests/compile-fail/validity/dangling_ref1.rs:6:29
3436
|
@@ -42,9 +44,10 @@ LL | let _x: &i32 = unsafe { mem::transmute(16usize) }; //~ ERROR encountere
4244
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
4345
error: aborting due to previous error
4446
";
45-
check_annotations(unnormalized_stderr.as_bytes(), &mut errors, &config, "", &comments);
47+
check_test_result(&path, &config, "", "", &comments, &mut errors, /*stdout*/ br"", stderr);
48+
// The "OutputDiffers" is because we cannot open the .rs file
4649
match &errors[..] {
47-
[Error::PatternNotFound { .. }] => {}
48-
_ => panic!("{:#?}", errors),
50+
[Error::OutputDiffers { .. }, Error::PatternNotFound { .. }] => {}
51+
_ => panic!("not the expected error: {:#?}", errors),
4952
}
5053
}

0 commit comments

Comments
 (0)