mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-29 16:13:40 +00:00
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
This commit is contained in:
parent
692b94ae25
commit
a5e8a0ea7c
@ -25,6 +25,7 @@ use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::fs::{self, File, create_dir_all};
|
||||
use std::fmt;
|
||||
use std::io::prelude::*;
|
||||
use std::io::{self, BufReader};
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -2237,7 +2238,7 @@ actual:\n\
|
||||
let (_, tests_text) = test_file_contents.split_at(idx + "// END_RUST SOURCE".len());
|
||||
let tests_text_str = String::from(tests_text);
|
||||
let mut curr_test : Option<&str> = None;
|
||||
let mut curr_test_contents = Vec::new();
|
||||
let mut curr_test_contents = vec![ExpectedLine::Elision];
|
||||
for l in tests_text_str.lines() {
|
||||
debug!("line: {:?}", l);
|
||||
if l.starts_with("// START ") {
|
||||
@ -2251,11 +2252,14 @@ actual:\n\
|
||||
self.compare_mir_test_output(curr_test.unwrap(), &curr_test_contents);
|
||||
curr_test = None;
|
||||
curr_test_contents.clear();
|
||||
curr_test_contents.push(ExpectedLine::Elision);
|
||||
} else if l.is_empty() {
|
||||
// ignore
|
||||
} else if l.starts_with("//") && l.split_at("//".len()).1.trim() == "..." {
|
||||
curr_test_contents.push(ExpectedLine::Elision)
|
||||
} else if l.starts_with("// ") {
|
||||
let (_, test_content) = l.split_at("// ".len());
|
||||
curr_test_contents.push(test_content);
|
||||
curr_test_contents.push(ExpectedLine::Text(test_content));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2273,7 +2277,7 @@ actual:\n\
|
||||
}
|
||||
}
|
||||
|
||||
fn compare_mir_test_output(&self, test_name: &str, expected_content: &[&str]) {
|
||||
fn compare_mir_test_output(&self, test_name: &str, expected_content: &[ExpectedLine<&str>]) {
|
||||
let mut output_file = PathBuf::new();
|
||||
output_file.push(self.get_mir_dump_dir());
|
||||
output_file.push(test_name);
|
||||
@ -2285,38 +2289,77 @@ actual:\n\
|
||||
let mut dumped_string = String::new();
|
||||
dumped_file.read_to_string(&mut dumped_string).unwrap();
|
||||
let mut dumped_lines = dumped_string.lines().filter(|l| !l.is_empty());
|
||||
let mut expected_lines = expected_content.iter().filter(|l| !l.is_empty());
|
||||
|
||||
// We expect each non-empty line from expected_content to appear
|
||||
// in the dump in order, but there may be extra lines interleaved
|
||||
while let Some(expected_line) = expected_lines.next() {
|
||||
let e_norm = normalize_mir_line(expected_line);
|
||||
if e_norm.is_empty() {
|
||||
continue;
|
||||
};
|
||||
let mut found = false;
|
||||
while let Some(dumped_line) = dumped_lines.next() {
|
||||
let d_norm = normalize_mir_line(dumped_line);
|
||||
debug!("found: {:?}", d_norm);
|
||||
debug!("expected: {:?}", e_norm);
|
||||
if e_norm == d_norm {
|
||||
found = true;
|
||||
break;
|
||||
};
|
||||
let mut expected_lines = expected_content.iter().filter(|&l| {
|
||||
if let &ExpectedLine::Text(l) = l {
|
||||
!l.is_empty()
|
||||
} else {
|
||||
true
|
||||
}
|
||||
if !found {
|
||||
let normalize_all = dumped_string.lines()
|
||||
.map(nocomment_mir_line)
|
||||
.filter(|l| !l.is_empty())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
panic!("ran out of mir dump output to match against.\n\
|
||||
Did not find expected line: {:?}\n\
|
||||
Expected:\n{}\n\
|
||||
Actual:\n{}",
|
||||
expected_line,
|
||||
expected_content.join("\n"),
|
||||
normalize_all);
|
||||
}).peekable();
|
||||
|
||||
let compare = |expected_line, dumped_line| {
|
||||
let e_norm = normalize_mir_line(expected_line);
|
||||
let d_norm = normalize_mir_line(dumped_line);
|
||||
debug!("found: {:?}", d_norm);
|
||||
debug!("expected: {:?}", e_norm);
|
||||
e_norm == d_norm
|
||||
};
|
||||
|
||||
let error = |expected_line, extra_msg| {
|
||||
let normalize_all = dumped_string.lines()
|
||||
.map(nocomment_mir_line)
|
||||
.filter(|l| !l.is_empty())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
let f = |l: &ExpectedLine<_>| match l {
|
||||
&ExpectedLine::Elision => "... (elided)".into(),
|
||||
&ExpectedLine::Text(t) => t
|
||||
};
|
||||
let expected_content = expected_content.iter()
|
||||
.map(|l| f(l))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
panic!("Did not find expected line, error: {}\n\
|
||||
Actual Line: {:?}\n\
|
||||
Expected:\n{}\n\
|
||||
Actual:\n{}",
|
||||
extra_msg,
|
||||
expected_line,
|
||||
expected_content,
|
||||
normalize_all);
|
||||
};
|
||||
|
||||
// We expect each non-empty line to appear consecutively, non-consecutive lines
|
||||
// must be separated by at least one Elision
|
||||
while let Some(dumped_line) = dumped_lines.next() {
|
||||
match expected_lines.next() {
|
||||
Some(&ExpectedLine::Text(expected_line)) =>
|
||||
if !compare(expected_line, dumped_line) {
|
||||
error(expected_line,
|
||||
format!("Mismatch in lines\nExpected Line: {:?}", dumped_line));
|
||||
},
|
||||
Some(&ExpectedLine::Elision) => {
|
||||
// skip any number of elisions in a row.
|
||||
while let Some(&&ExpectedLine::Elision) = expected_lines.peek() {
|
||||
expected_lines.next();
|
||||
}
|
||||
if let Some(&ExpectedLine::Text(expected_line)) = expected_lines.next() {
|
||||
let mut found = compare(expected_line, dumped_line);
|
||||
if found {
|
||||
continue;
|
||||
}
|
||||
while let Some(dumped_line) = dumped_lines.next() {
|
||||
found = compare(expected_line, dumped_line);
|
||||
if found {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
error(expected_line, "ran out of mir dump to match against".into());
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2439,6 +2482,25 @@ enum TargetLocation {
|
||||
ThisDirectory(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
enum ExpectedLine<T: AsRef<str>> {
|
||||
Elision,
|
||||
Text(T)
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for ExpectedLine<T>
|
||||
where
|
||||
T: AsRef<str> + fmt::Debug
|
||||
{
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
if let &ExpectedLine::Text(ref t) = self {
|
||||
write!(formatter, "{:?}", t)
|
||||
} else {
|
||||
write!(formatter, "\"...\" (Elision)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn normalize_mir_line(line: &str) -> String {
|
||||
nocomment_mir_line(line).replace(char::is_whitespace, "")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user