about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-03-27 12:58:34 +0000
committerbors <bors@rust-lang.org>2020-03-27 12:58:34 +0000
commit0a2df620735134d5907e4d4e25241a64cec2ceac (patch)
treef2b2003d172a1b7b290c69afd98c378be34cfd64 /src/tools
parent697d6b3f3fa1f163acb5ae0911d7df7f02a54444 (diff)
parentc9a5a03ffda14aaf505015b3b866c5a9f3cc6bf4 (diff)
downloadrust-0a2df620735134d5907e4d4e25241a64cec2ceac.tar.gz
rust-0a2df620735134d5907e4d4e25241a64cec2ceac.zip
Auto merge of #69916 - oli-obk:mir_bless, r=eddyb
Enable blessing of mir opt tests

cc @rust-lang/wg-mir-opt
cc @RalfJung

Long overdue, but now you can finally just add a

```rust
// EMIT_MIR rustc.function_name.MirPassName.before.mir
```

(or `after.mir` since most of the time you want to know the MIR after a pass). A `--bless` invocation will automatically create the files for you.

I suggest we do this for all mir opt tests that have all of the MIR in their source anyway

If you use `rustc.function.MirPass.diff` you only get the diff that the MIR pass causes on the MIR.

Fixes #67865
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/compiletest/src/main.rs21
-rw-r--r--src/tools/compiletest/src/runtest.rs139
2 files changed, 117 insertions, 43 deletions
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index a61b9403987..028483b7d95 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -449,15 +449,8 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
 pub fn make_tests(config: &Config, tests: &mut Vec<test::TestDescAndFn>) {
     debug!("making tests from {:?}", config.src_base.display());
     let inputs = common_inputs_stamp(config);
-    collect_tests_from_dir(
-        config,
-        &config.src_base,
-        &config.src_base,
-        &PathBuf::new(),
-        &inputs,
-        tests,
-    )
-    .expect(&format!("Could not read tests from {}", config.src_base.display()));
+    collect_tests_from_dir(config, &config.src_base, &PathBuf::new(), &inputs, tests)
+        .expect(&format!("Could not read tests from {}", config.src_base.display()));
 }
 
 /// Returns a stamp constructed from input files common to all test cases.
@@ -494,7 +487,6 @@ fn common_inputs_stamp(config: &Config) -> Stamp {
 
 fn collect_tests_from_dir(
     config: &Config,
-    base: &Path,
     dir: &Path,
     relative_dir_path: &Path,
     inputs: &Stamp,
@@ -538,14 +530,7 @@ fn collect_tests_from_dir(
             let relative_file_path = relative_dir_path.join(file.file_name());
             if &file_name != "auxiliary" {
                 debug!("found directory: {:?}", file_path.display());
-                collect_tests_from_dir(
-                    config,
-                    base,
-                    &file_path,
-                    &relative_file_path,
-                    inputs,
-                    tests,
-                )?;
+                collect_tests_from_dir(config, &file_path, &relative_file_path, inputs, tests)?;
             }
         } else {
             debug!("found other file/directory: {:?}", file_path.display());
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 4508f5b7f95..0ee016f33dd 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -11,6 +11,7 @@ use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT};
 use crate::errors::{self, Error, ErrorKind};
 use crate::header::TestProps;
 use crate::json;
+use crate::util::get_pointer_width;
 use crate::util::{logv, PathBufExt};
 use diff;
 use regex::{Captures, Regex};
@@ -178,6 +179,33 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Misma
     results
 }
 
+fn print_diff(expected: &str, actual: &str, context_size: usize) {
+    write_diff(expected, actual, context_size, std::io::stdout());
+}
+
+fn write_diff(expected: &str, actual: &str, context_size: usize, mut dest: impl io::Write) {
+    let diff_results = make_diff(expected, actual, context_size);
+    for result in diff_results {
+        let mut line_number = result.line_number;
+        for line in result.lines {
+            match line {
+                DiffLine::Expected(e) => {
+                    writeln!(dest, "-\t{}", e).unwrap();
+                    line_number += 1;
+                }
+                DiffLine::Context(c) => {
+                    writeln!(dest, "{}\t{}", line_number, c).unwrap();
+                    line_number += 1;
+                }
+                DiffLine::Resulting(r) => {
+                    writeln!(dest, "+\t{}", r).unwrap();
+                }
+            }
+        }
+        writeln!(dest).unwrap();
+    }
+}
+
 pub fn run(config: Config, testpaths: &TestPaths, revision: Option<&str>) {
     match &*config.target {
         "arm-linux-androideabi"
@@ -3040,6 +3068,89 @@ impl<'test> TestCx<'test> {
 
     fn check_mir_dump(&self) {
         let test_file_contents = fs::read_to_string(&self.testpaths.file).unwrap();
+
+        let mut test_dir = self.testpaths.file.with_extension("");
+
+        if test_file_contents.lines().any(|l| l == "// EMIT_MIR_FOR_EACH_BIT_WIDTH") {
+            test_dir.push(get_pointer_width(&self.config.target))
+        }
+
+        if self.config.bless {
+            let _ = std::fs::remove_dir_all(&test_dir);
+        }
+        for l in test_file_contents.lines() {
+            if l.starts_with("// EMIT_MIR ") {
+                let test_name = l.trim_start_matches("// EMIT_MIR ");
+                let expected_file = test_dir.join(test_name);
+
+                let dumped_string = if test_name.ends_with(".diff") {
+                    let test_name = test_name.trim_end_matches(".diff");
+                    let before = format!("{}.before.mir", test_name);
+                    let after = format!("{}.after.mir", test_name);
+                    let before = self.get_mir_dump_dir().join(before);
+                    let after = self.get_mir_dump_dir().join(after);
+                    debug!(
+                        "comparing the contents of: {} with {}",
+                        before.display(),
+                        after.display()
+                    );
+                    let before = fs::read_to_string(before).unwrap();
+                    let after = fs::read_to_string(after).unwrap();
+                    let before = self.normalize_output(&before, &[]);
+                    let after = self.normalize_output(&after, &[]);
+                    let mut dumped_string = String::new();
+                    for result in diff::lines(&before, &after) {
+                        use std::fmt::Write;
+                        match result {
+                            diff::Result::Left(s) => writeln!(dumped_string, "- {}", s).unwrap(),
+                            diff::Result::Right(s) => writeln!(dumped_string, "+ {}", s).unwrap(),
+                            diff::Result::Both(s, _) => writeln!(dumped_string, "  {}", s).unwrap(),
+                        }
+                    }
+                    dumped_string
+                } else {
+                    let mut output_file = PathBuf::new();
+                    output_file.push(self.get_mir_dump_dir());
+                    output_file.push(test_name);
+                    debug!(
+                        "comparing the contents of: {} with {}",
+                        output_file.display(),
+                        expected_file.display()
+                    );
+                    if !output_file.exists() {
+                        panic!(
+                            "Output file `{}` from test does not exist, available files are in `{}`",
+                            output_file.display(),
+                            output_file.parent().unwrap().display()
+                        );
+                    }
+                    self.check_mir_test_timestamp(test_name, &output_file);
+                    let dumped_string = fs::read_to_string(&output_file).unwrap();
+                    self.normalize_output(&dumped_string, &[])
+                };
+                if self.config.bless {
+                    let _ = std::fs::create_dir_all(&test_dir);
+                    let _ = std::fs::remove_file(&expected_file);
+                    std::fs::write(expected_file, dumped_string.as_bytes()).unwrap();
+                } else {
+                    if !expected_file.exists() {
+                        panic!(
+                            "Output file `{}` from test does not exist",
+                            expected_file.display()
+                        );
+                    }
+                    let expected_string = fs::read_to_string(&expected_file).unwrap();
+                    if dumped_string != expected_string {
+                        print_diff(&dumped_string, &expected_string, 3);
+                        panic!(
+                            "Actual MIR output differs from expected MIR output {}",
+                            expected_file.display()
+                        );
+                    }
+                }
+            }
+        }
+
         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);
@@ -3090,13 +3201,10 @@ impl<'test> TestCx<'test> {
         let mut output_file = PathBuf::new();
         output_file.push(self.get_mir_dump_dir());
         output_file.push(test_name);
-        debug!("comparing the contests of: {:?}", output_file);
+        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.into_os_string().to_string_lossy()
-            );
+            panic!("Output file `{}` from test does not exist", output_file.display());
         }
         self.check_mir_test_timestamp(test_name, &output_file);
 
@@ -3356,26 +3464,7 @@ impl<'test> TestCx<'test> {
                 println!("normalized {}:\n{}\n", kind, actual);
             } else {
                 println!("diff of {}:\n", kind);
-                let diff_results = make_diff(expected, actual, 3);
-                for result in diff_results {
-                    let mut line_number = result.line_number;
-                    for line in result.lines {
-                        match line {
-                            DiffLine::Expected(e) => {
-                                println!("-\t{}", e);
-                                line_number += 1;
-                            }
-                            DiffLine::Context(c) => {
-                                println!("{}\t{}", line_number, c);
-                                line_number += 1;
-                            }
-                            DiffLine::Resulting(r) => {
-                                println!("+\t{}", r);
-                            }
-                        }
-                    }
-                    println!();
-                }
+                print_diff(expected, actual, 3);
             }
         }