about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/compiletest/src/common.rs40
-rw-r--r--src/tools/compiletest/src/main.rs18
-rw-r--r--src/tools/compiletest/src/runtest.rs46
3 files changed, 82 insertions, 22 deletions
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 1d8cef05b7d..41fc67a66f4 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -96,6 +96,26 @@ impl fmt::Display for Mode {
 }
 
 #[derive(Clone)]
+pub enum CompareMode {
+    Nll
+}
+
+impl CompareMode {
+    fn to_str(&self) -> &'static str {
+        match *self {
+            CompareMode::Nll => "nll"
+        }
+    }
+
+    pub fn parse(s: String) -> CompareMode {
+        match s.as_str() {
+            "nll" => CompareMode::Nll,
+            x => panic!("unknown --compare-mode option: {}", x),
+        }
+    }
+}
+
+#[derive(Clone)]
 pub struct Config {
     /// The library paths required for running the compiler
     pub compile_lib_path: PathBuf,
@@ -210,6 +230,9 @@ pub struct Config {
     /// where to find the remote test client process, if we're using it
     pub remote_test_client: Option<PathBuf>,
 
+    /// mode describing what file the actual ui output will be compared to
+    pub compare_mode: Option<CompareMode>,
+
     // Configuration for various run-make tests frobbing things like C compilers
     // or querying about various LLVM component information.
     pub cc: String,
@@ -230,12 +253,19 @@ pub struct TestPaths {
 }
 
 /// Used by `ui` tests to generate things like `foo.stderr` from `foo.rs`.
-pub fn expected_output_path(testpaths: &TestPaths, revision: Option<&str>, kind: &str) -> PathBuf {
+pub fn expected_output_path(testpaths: &TestPaths,
+                            revision: Option<&str>,
+                            compare_mode: &Option<CompareMode>,
+                            kind: &str) -> PathBuf {
+
     assert!(UI_EXTENSIONS.contains(&kind));
-    let extension = match revision {
-        Some(r) => format!("{}.{}", r, kind),
-        None => kind.to_string(),
-    };
+    let mut parts = Vec::new();
+
+    if let Some(x) = revision { parts.push(x); }
+    if let Some(ref x) = *compare_mode { parts.push(x.to_str()); }
+    parts.push(kind);
+
+    let extension = parts.join(".");
     testpaths.file.with_extension(extension)
 }
 
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index e65c03a6e57..80cab96434b 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -38,6 +38,7 @@ use getopts::Options;
 use common::{Config, TestPaths};
 use common::{DebugInfoGdb, DebugInfoLldb, Mode, Pretty};
 use common::{expected_output_path, UI_EXTENSIONS};
+use common::CompareMode;
 use test::ColorConfig;
 use util::logv;
 
@@ -227,6 +228,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
             "path to the remote test client",
             "PATH",
         )
+        .optopt(
+            "",
+            "compare-mode",
+            "mode describing what file the actual ui output will be compared to",
+            "COMPARE MODE"
+        )
         .optflag("h", "help", "show this message");
 
     let (argv0, args_) = args.split_first().unwrap();
@@ -320,6 +327,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
         quiet: matches.opt_present("quiet"),
         color,
         remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
+        compare_mode: matches.opt_str("compare-mode").map(CompareMode::parse),
 
         cc: matches.opt_str("cc").unwrap(),
         cxx: matches.opt_str("cxx").unwrap(),
@@ -615,7 +623,8 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn
     };
 
     // Debugging emscripten code doesn't make sense today
-    let ignore = early_props.ignore || !up_to_date(config, testpaths, &early_props)
+    let ignore = early_props.ignore
+        || (!up_to_date(config, testpaths, &early_props) && config.compare_mode.is_none())
         || (config.mode == DebugInfoGdb || config.mode == DebugInfoLldb)
             && config.target.contains("emscripten");
 
@@ -688,12 +697,15 @@ fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> boo
     // UI test files.
     for extension in UI_EXTENSIONS {
         for revision in &props.revisions {
-            let path = &expected_output_path(testpaths, Some(revision), extension);
+            let path = &expected_output_path(testpaths,
+                                             Some(revision),
+                                             &config.compare_mode,
+                                             extension);
             inputs.push(mtime(path));
         }
 
         if props.revisions.is_empty() {
-            let path = &expected_output_path(testpaths, None, extension);
+            let path = &expected_output_path(testpaths, None, &config.compare_mode, extension);
             inputs.push(mtime(path));
         }
     }
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index e826c5366a8..0081c0ae69d 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -13,6 +13,7 @@ use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
 use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc};
 use common::{Incremental, MirOpt, RunMake, Ui};
 use common::{expected_output_path, UI_STDERR, UI_STDOUT};
+use common::CompareMode;
 use diff;
 use errors::{self, Error, ErrorKind};
 use filetime::FileTime;
@@ -1683,6 +1684,13 @@ impl<'test> TestCx<'test> {
             }
         }
 
+        match self.config.compare_mode {
+            Some(CompareMode::Nll) => {
+                rustc.args(&["-Znll", "-Zborrowck=mir", "-Ztwo-phase-borrows"]);
+            },
+            None => {},
+        }
+
         if self.props.force_host {
             rustc.args(self.split_maybe_args(&self.config.host_rustcflags));
         } else {
@@ -2505,11 +2513,8 @@ impl<'test> TestCx<'test> {
         let proc_res = self.compile_test();
         self.check_if_test_should_compile(&proc_res);
 
-        let expected_stderr_path = self.expected_output_path(UI_STDERR);
-        let expected_stderr = self.load_expected_output(&expected_stderr_path);
-
-        let expected_stdout_path = self.expected_output_path(UI_STDOUT);
-        let expected_stdout = self.load_expected_output(&expected_stdout_path);
+        let expected_stderr = self.load_expected_output(UI_STDERR);
+        let expected_stdout = self.load_expected_output(UI_STDOUT);
 
         let normalized_stdout =
             self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout);
@@ -2552,7 +2557,7 @@ impl<'test> TestCx<'test> {
                 self.fatal_proc_rec("test run failed!", &proc_res);
             }
         }
-        if !explicit {
+        if !explicit && self.config.compare_mode.is_none() {
             if !expected_errors.is_empty() || !proc_res.status.success() {
                 // "// error-pattern" comments
                 self.check_expected_errors(expected_errors, &proc_res);
@@ -2795,19 +2800,32 @@ impl<'test> TestCx<'test> {
         normalized
     }
 
-    fn expected_output_path(&self, kind: &str) -> PathBuf {
-        expected_output_path(&self.testpaths, self.revision, kind)
-    }
+    fn load_expected_output(&self, kind: &str) -> String {
+        let mut path = expected_output_path(&self.testpaths,
+                                            self.revision,
+                                            &self.config.compare_mode,
+                                            kind);
 
-    fn load_expected_output(&self, path: &Path) -> String {
-        if !path.exists() {
-            return String::new();
+        if !path.exists() && self.config.compare_mode.is_some() {
+            // fallback!
+            path = expected_output_path(&self.testpaths, self.revision, &None, kind);
         }
 
+        if path.exists() {
+            match self.load_expected_output_from_path(&path) {
+                Ok(x) => x,
+                Err(x) => self.fatal(&x),
+            }
+        } else {
+            String::new()
+        }
+    }
+
+    fn load_expected_output_from_path(&self, path: &Path) -> Result<String, String> {
         let mut result = String::new();
         match File::open(path).and_then(|mut f| f.read_to_string(&mut result)) {
-            Ok(_) => result,
-            Err(e) => self.fatal(&format!(
+            Ok(_) => Ok(result),
+            Err(e) => Err(format!(
                 "failed to load expected output from `{}`: {}",
                 path.display(),
                 e