Skip to content

Commit a5e8a0e

Browse files
committed
Modify MIR testing to require continuous lines
Mir testing now requires that lines be continuous. To achive this, instead of collecting the expected mir as a string, it is now wrapped in an `ExpectedLine` enum, that is either `Elision` or `Text(T)` where `T: AsRef<str>`. `Text` lines must be matched in order, unless separated by `Elision` lines. Matches occur greedily, that is, an Elision will skip as few lines as possible. To add a new elision marker. Put a comment containing only "..." and whitespace in any MIR testing block. Like so: ``` // fn write_42(_1: *mut i32) -> bool { // ... // bb0: { // Validate(Acquire, [_1: *mut i32]); // Validate(Release, [_1: *mut i32]); // ... // return; // } // } ``` Right now, all input before the line right after `// START` is elided, and all input after the line right before `// END` is also not tested. Many tests need to be updated. That will follow in the next commit. cc #45153
1 parent 692b94a commit a5e8a0e

File tree

1 file changed

+94
-32
lines changed

1 file changed

+94
-32
lines changed

Diff for: src/tools/compiletest/src/runtest.rs

+94-32
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use std::collections::HashSet;
2525
use std::env;
2626
use std::ffi::OsString;
2727
use std::fs::{self, File, create_dir_all};
28+
use std::fmt;
2829
use std::io::prelude::*;
2930
use std::io::{self, BufReader};
3031
use std::path::{Path, PathBuf};
@@ -2237,7 +2238,7 @@ actual:\n\
22372238
let (_, tests_text) = test_file_contents.split_at(idx + "// END_RUST SOURCE".len());
22382239
let tests_text_str = String::from(tests_text);
22392240
let mut curr_test : Option<&str> = None;
2240-
let mut curr_test_contents = Vec::new();
2241+
let mut curr_test_contents = vec![ExpectedLine::Elision];
22412242
for l in tests_text_str.lines() {
22422243
debug!("line: {:?}", l);
22432244
if l.starts_with("// START ") {
@@ -2251,11 +2252,14 @@ actual:\n\
22512252
self.compare_mir_test_output(curr_test.unwrap(), &curr_test_contents);
22522253
curr_test = None;
22532254
curr_test_contents.clear();
2255+
curr_test_contents.push(ExpectedLine::Elision);
22542256
} else if l.is_empty() {
22552257
// ignore
2258+
} else if l.starts_with("//") && l.split_at("//".len()).1.trim() == "..." {
2259+
curr_test_contents.push(ExpectedLine::Elision)
22562260
} else if l.starts_with("// ") {
22572261
let (_, test_content) = l.split_at("// ".len());
2258-
curr_test_contents.push(test_content);
2262+
curr_test_contents.push(ExpectedLine::Text(test_content));
22592263
}
22602264
}
22612265
}
@@ -2273,7 +2277,7 @@ actual:\n\
22732277
}
22742278
}
22752279

2276-
fn compare_mir_test_output(&self, test_name: &str, expected_content: &[&str]) {
2280+
fn compare_mir_test_output(&self, test_name: &str, expected_content: &[ExpectedLine<&str>]) {
22772281
let mut output_file = PathBuf::new();
22782282
output_file.push(self.get_mir_dump_dir());
22792283
output_file.push(test_name);
@@ -2285,38 +2289,77 @@ actual:\n\
22852289
let mut dumped_string = String::new();
22862290
dumped_file.read_to_string(&mut dumped_string).unwrap();
22872291
let mut dumped_lines = dumped_string.lines().filter(|l| !l.is_empty());
2288-
let mut expected_lines = expected_content.iter().filter(|l| !l.is_empty());
2292+
let mut expected_lines = expected_content.iter().filter(|&l| {
2293+
if let &ExpectedLine::Text(l) = l {
2294+
!l.is_empty()
2295+
} else {
2296+
true
2297+
}
2298+
}).peekable();
22892299

2290-
// We expect each non-empty line from expected_content to appear
2291-
// in the dump in order, but there may be extra lines interleaved
2292-
while let Some(expected_line) = expected_lines.next() {
2300+
let compare = |expected_line, dumped_line| {
22932301
let e_norm = normalize_mir_line(expected_line);
2294-
if e_norm.is_empty() {
2295-
continue;
2302+
let d_norm = normalize_mir_line(dumped_line);
2303+
debug!("found: {:?}", d_norm);
2304+
debug!("expected: {:?}", e_norm);
2305+
e_norm == d_norm
2306+
};
2307+
2308+
let error = |expected_line, extra_msg| {
2309+
let normalize_all = dumped_string.lines()
2310+
.map(nocomment_mir_line)
2311+
.filter(|l| !l.is_empty())
2312+
.collect::<Vec<_>>()
2313+
.join("\n");
2314+
let f = |l: &ExpectedLine<_>| match l {
2315+
&ExpectedLine::Elision => "... (elided)".into(),
2316+
&ExpectedLine::Text(t) => t
22962317
};
2297-
let mut found = false;
2298-
while let Some(dumped_line) = dumped_lines.next() {
2299-
let d_norm = normalize_mir_line(dumped_line);
2300-
debug!("found: {:?}", d_norm);
2301-
debug!("expected: {:?}", e_norm);
2302-
if e_norm == d_norm {
2303-
found = true;
2304-
break;
2305-
};
2306-
}
2307-
if !found {
2308-
let normalize_all = dumped_string.lines()
2309-
.map(nocomment_mir_line)
2310-
.filter(|l| !l.is_empty())
2311-
.collect::<Vec<_>>()
2312-
.join("\n");
2313-
panic!("ran out of mir dump output to match against.\n\
2314-
Did not find expected line: {:?}\n\
2315-
Expected:\n{}\n\
2316-
Actual:\n{}",
2317-
expected_line,
2318-
expected_content.join("\n"),
2319-
normalize_all);
2318+
let expected_content = expected_content.iter()
2319+
.map(|l| f(l))
2320+
.collect::<Vec<_>>()
2321+
.join("\n");
2322+
panic!("Did not find expected line, error: {}\n\
2323+
Actual Line: {:?}\n\
2324+
Expected:\n{}\n\
2325+
Actual:\n{}",
2326+
extra_msg,
2327+
expected_line,
2328+
expected_content,
2329+
normalize_all);
2330+
};
2331+
2332+
// We expect each non-empty line to appear consecutively, non-consecutive lines
2333+
// must be separated by at least one Elision
2334+
while let Some(dumped_line) = dumped_lines.next() {
2335+
match expected_lines.next() {
2336+
Some(&ExpectedLine::Text(expected_line)) =>
2337+
if !compare(expected_line, dumped_line) {
2338+
error(expected_line,
2339+
format!("Mismatch in lines\nExpected Line: {:?}", dumped_line));
2340+
},
2341+
Some(&ExpectedLine::Elision) => {
2342+
// skip any number of elisions in a row.
2343+
while let Some(&&ExpectedLine::Elision) = expected_lines.peek() {
2344+
expected_lines.next();
2345+
}
2346+
if let Some(&ExpectedLine::Text(expected_line)) = expected_lines.next() {
2347+
let mut found = compare(expected_line, dumped_line);
2348+
if found {
2349+
continue;
2350+
}
2351+
while let Some(dumped_line) = dumped_lines.next() {
2352+
found = compare(expected_line, dumped_line);
2353+
if found {
2354+
break;
2355+
}
2356+
}
2357+
if !found {
2358+
error(expected_line, "ran out of mir dump to match against".into());
2359+
}
2360+
}
2361+
},
2362+
None => {},
23202363
}
23212364
}
23222365
}
@@ -2439,6 +2482,25 @@ enum TargetLocation {
24392482
ThisDirectory(PathBuf),
24402483
}
24412484

2485+
#[derive(Clone, PartialEq, Eq)]
2486+
enum ExpectedLine<T: AsRef<str>> {
2487+
Elision,
2488+
Text(T)
2489+
}
2490+
2491+
impl<T> fmt::Debug for ExpectedLine<T>
2492+
where
2493+
T: AsRef<str> + fmt::Debug
2494+
{
2495+
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2496+
if let &ExpectedLine::Text(ref t) = self {
2497+
write!(formatter, "{:?}", t)
2498+
} else {
2499+
write!(formatter, "\"...\" (Elision)")
2500+
}
2501+
}
2502+
}
2503+
24422504
fn normalize_mir_line(line: &str) -> String {
24432505
nocomment_mir_line(line).replace(char::is_whitespace, "")
24442506
}

0 commit comments

Comments
 (0)