Remove old mir-opt test format.

This commit is contained in:
Ana-Maria Mihalache 2020-04-07 17:47:58 +00:00
parent ea4aca19c1
commit d0e0f4021d
2 changed files with 2 additions and 244 deletions

View File

@ -1,9 +1,7 @@
This folder contains tests for MIR optimizations.
There are two test formats. One allows specifying a pattern to look for in the MIR, which also
permits leaving placeholders, but requires you to manually change the pattern if anything changes.
The other emits MIR to extra files that you can automatically update by specifying `--bless` on
the command line (just like `ui` tests updating `.stderr` files).
The `mir-opt` test format emits MIR to extra files that you can automatically update by specifying
`--bless` on the command line (just like `ui` tests updating `.stderr` files).
# `--bless`able test format
@ -39,79 +37,3 @@ This exists mainly for completeness and is rarely useful.
```
// EMIT_MIR $file_name_of_some_mir_dump.before.mir
```
# Inline test format
```
(arbitrary rust code)
// END RUST SOURCE
// START $file_name_of_some_mir_dump_0
// $expected_line_0
// (lines or elision)
// $expected_line_N
// END $file_name_of_some_mir_dump_0
// (lines or elision)
// START $file_name_of_some_mir_dump_N
// $expected_line_0
// (lines or elision)
// $expected_line_N
// END $file_name_of_some_mir_dump_N
```
All the test information is in comments so the test is runnable.
For each $file_name, compiletest expects [$expected_line_0, ...,
$expected_line_N] to appear in the dumped MIR in order. Currently it allows
other non-matched lines before and after, but not between $expected_lines,
should you want to skip lines, you must include an elision comment, of the form
(as a regex) `//\s*...\s*`. The lines will be skipped lazily, that is, if there
are two identical lines in the output that match the line after the elision
comment, the first one will be matched.
Examples:
The following blocks will not match the one after it.
```
bb0: {
StorageLive(_1);
_1 = const true;
StorageDead(_1);
}
```
```
bb0: {
StorageLive(_1);
_1 = const true;
goto -> bb1
}
bb1: {
StorageDead(_1);
return;
}
```
But this will match the one above,
```
bb0: {
StorageLive(_1);
_1 = const true;
...
StorageDead(_1);
...
}
```
Lines match ignoring whitespace, and the prefix "//" is removed.
It also currently strips trailing comments -- partly because the full file path
in "scope comments" is unpredictable and partly because tidy complains about
the lines being too long.
compiletest handles dumping the MIR before and after every pass for you. The
test writer only has to specify the file names of the dumped files (not the
full path to the file) and what lines to expect. There is an option to rustc
that tells it to dump the mir into some directly (rather then always dumping to
the current directory).

View File

@ -21,7 +21,6 @@ use std::collections::hash_map::DefaultHasher;
use std::collections::{HashMap, HashSet, VecDeque};
use std::env;
use std::ffi::{OsStr, OsString};
use std::fmt;
use std::fs::{self, create_dir_all, File, OpenOptions};
use std::hash::{Hash, Hasher};
use std::io::prelude::*;
@ -3156,36 +3155,6 @@ impl<'test> TestCx<'test> {
}
}
}
if let Some(idx) = test_file_contents.find("// END RUST SOURCE") {
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![ExpectedLine::Elision];
for l in tests_text_str.lines() {
debug!("line: {:?}", l);
if l.starts_with("// START ") {
let (_, t) = l.split_at("// START ".len());
curr_test = Some(t);
} else if l.starts_with("// END") {
let (_, t) = l.split_at("// END ".len());
if Some(t) != curr_test {
panic!("mismatched START END test name");
}
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(ExpectedLine::Text(test_content));
}
}
}
}
fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Path) {
@ -3203,107 +3172,6 @@ impl<'test> TestCx<'test> {
}
}
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);
debug!("comparing the contents of: {:?}", output_file);
debug!("with: {:?}", expected_content);
if !output_file.exists() {
panic!("Output file `{}` from test does not exist", output_file.display());
}
self.check_mir_test_timestamp(test_name, &output_file);
let dumped_string = fs::read_to_string(&output_file).unwrap();
let mut dumped_lines =
dumped_string.lines().map(|l| nocomment_mir_line(l)).filter(|l| !l.is_empty());
let mut expected_lines = expected_content
.iter()
.filter(|&l| if let &ExpectedLine::Text(l) = l { !l.is_empty() } else { true })
.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\
Expected Line: {:?}\n\
Test Name: {}\n\
Expected:\n{}\n\
Actual:\n{}",
extra_msg, expected_line, test_name, expected_content, normalize_all
);
};
// We expect each non-empty line to appear consecutively, non-consecutive lines
// must be separated by at least one Elision
let mut start_block_line = None;
while let Some(dumped_line) = dumped_lines.next() {
match expected_lines.next() {
Some(&ExpectedLine::Text(expected_line)) => {
let normalized_expected_line = normalize_mir_line(expected_line);
if normalized_expected_line.contains(":{") {
start_block_line = Some(expected_line);
}
if !compare(expected_line, dumped_line) {
error!("{:?}", start_block_line);
error(
expected_line,
format!(
"Mismatch in lines\n\
Current block: {}\n\
Actual Line: {:?}",
start_block_line.unwrap_or("None"),
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 => {}
}
}
}
fn get_mir_dump_dir(&self) -> PathBuf {
let mut mir_dump_dir = PathBuf::from(self.config.build_base.as_path());
debug!("input_file: {:?}", self.testpaths.file);
@ -3589,43 +3457,11 @@ enum TargetLocation {
ThisDirectory(PathBuf),
}
#[derive(Clone, PartialEq, Eq)]
enum ExpectedLine<T: AsRef<str>> {
Elision,
Text(T),
}
enum AllowUnused {
Yes,
No,
}
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, "")
}
fn nocomment_mir_line(line: &str) -> &str {
if let Some(idx) = line.find("//") {
let (l, _) = line.split_at(idx);
l.trim_end()
} else {
line
}
}
fn read2_abbreviated(mut child: Child) -> io::Result<Output> {
use crate::read2::read2;
use std::mem::replace;