From 79db5fe593262611ab26c0f551190f61e3314cd8 Mon Sep 17 00:00:00 2001 From: memoryleak47 Date: Fri, 23 Mar 2018 03:31:43 +0100 Subject: [PATCH 1/6] add --compare-mode option to compiletest --- src/tools/compiletest/src/common.rs | 29 +++++++++++++++---- src/tools/compiletest/src/main.rs | 12 ++++++-- src/tools/compiletest/src/runtest.rs | 43 +++++++++++++++++++--------- 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 1d8cef05b7dd3..4a1c7b499538f 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -95,6 +95,19 @@ impl fmt::Display for Mode { } } +#[derive(Clone)] +pub enum CompareMode { + Nll +} + +impl CompareMode { + fn to_str(&self) -> &'static str { + match *self { + CompareMode::Nll => "nll" + } + } +} + #[derive(Clone)] pub struct Config { /// The library paths required for running the compiler @@ -210,6 +223,9 @@ pub struct Config { /// where to find the remote test client process, if we're using it pub remote_test_client: Option, + /// mode describing what file the actual ui output will be compared to + pub compare_mode: Option, + // Configuration for various run-make tests frobbing things like C compilers // or querying about various LLVM component information. pub cc: String, @@ -230,12 +246,15 @@ 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, 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 e65c03a6e571c..7c676fe939dff 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) -> 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) -> 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").and_then(|x| if x == "nll" { Some(CompareMode::Nll) } else { panic!("Unknown compare-mode {}", x) }), cc: matches.opt_str("cc").unwrap(), cxx: matches.opt_str("cxx").unwrap(), @@ -688,12 +696,12 @@ 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 953a13a3f5820..8caa52719008e 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; @@ -1681,6 +1682,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 { @@ -2507,11 +2515,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); @@ -2797,19 +2802,31 @@ impl<'test> TestCx<'test> { normalized } - fn expected_output_path(&self, kind: &str) -> PathBuf { - expected_output_path(&self.testpaths, self.revision, kind) - } + fn expected_output_path(&self, kind: &str) -> Result { + let mut path = expected_output_path(&self.testpaths, self.revision, &self.config.compare_mode, kind); + if !path.exists() && self.config.compare_mode.is_some() { + // fallback! + path = expected_output_path(&self.testpaths, self.revision, &None, kind); + } - fn load_expected_output(&self, path: &Path) -> String { - if !path.exists() { - return String::new(); + if path.exists() { + Ok(path) + } else { + Err(String::from("no existing output_path found")) } + } + fn load_expected_output(&self, kind: &str) -> String { + self.expected_output_path(kind) + .and_then(|x| self.load_expected_output_from_path(&x)) + .unwrap_or_else(|x| self.fatal(&x)) + } + + fn load_expected_output_from_path(&self, path: &Path) -> Result { 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 From 4023f054b1830f22459b882271a8e0430da2fcb5 Mon Sep 17 00:00:00 2001 From: memoryleak47 Date: Fri, 23 Mar 2018 03:56:44 +0100 Subject: [PATCH 2/6] compiletest ui does not check for //~ comments, when --compare-mode is active --- src/tools/compiletest/src/runtest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 8caa52719008e..8d15ba06e0a0d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2559,7 +2559,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); From bb7ab5c85db7954f2662e84a88610b8b39b501c7 Mon Sep 17 00:00:00 2001 From: memoryleak47 Date: Fri, 23 Mar 2018 06:10:03 +0100 Subject: [PATCH 3/6] some tidy fixes --- src/tools/compiletest/src/common.rs | 13 ++++++++++++- src/tools/compiletest/src/main.rs | 7 +++++-- src/tools/compiletest/src/runtest.rs | 6 +++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 4a1c7b499538f..41fc67a66f47d 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -106,6 +106,13 @@ impl CompareMode { 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)] @@ -246,7 +253,11 @@ 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>, compare_mode: &Option, kind: &str) -> PathBuf { +pub fn expected_output_path(testpaths: &TestPaths, + revision: Option<&str>, + compare_mode: &Option, + kind: &str) -> PathBuf { + assert!(UI_EXTENSIONS.contains(&kind)); let mut parts = Vec::new(); diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 7c676fe939dff..795ad0c74b7c2 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -327,7 +327,7 @@ pub fn parse_config(args: Vec) -> 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").and_then(|x| if x == "nll" { Some(CompareMode::Nll) } else { panic!("Unknown compare-mode {}", x) }), + compare_mode: matches.opt_str("compare-mode").map(CompareMode::parse), cc: matches.opt_str("cc").unwrap(), cxx: matches.opt_str("cxx").unwrap(), @@ -696,7 +696,10 @@ 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), &config.compare_mode, extension); + let path = &expected_output_path(testpaths, + Some(revision), + &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 8d15ba06e0a0d..540ff13eae550 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2803,7 +2803,11 @@ impl<'test> TestCx<'test> { } fn expected_output_path(&self, kind: &str) -> Result { - let mut path = expected_output_path(&self.testpaths, self.revision, &self.config.compare_mode, kind); + let mut path = expected_output_path(&self.testpaths, + self.revision, + &self.config.compare_mode, + kind); + if !path.exists() && self.config.compare_mode.is_some() { // fallback! path = expected_output_path(&self.testpaths, self.revision, &None, kind); From da1febff1eb29172f8f464360d0358ef66414488 Mon Sep 17 00:00:00 2001 From: memoryleak47 Date: Fri, 23 Mar 2018 15:31:05 +0100 Subject: [PATCH 4/6] the expected ui output is now the empty String if the corresponding files are missing --- src/tools/compiletest/src/runtest.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 540ff13eae550..320bca7bb6473 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2802,7 +2802,7 @@ impl<'test> TestCx<'test> { normalized } - fn expected_output_path(&self, kind: &str) -> Result { + fn load_expected_output(&self, kind: &str) -> String { let mut path = expected_output_path(&self.testpaths, self.revision, &self.config.compare_mode, @@ -2814,18 +2814,15 @@ impl<'test> TestCx<'test> { } if path.exists() { - Ok(path) + match self.load_expected_output_from_path(&path) { + Ok(x) => x, + Err(x) => self.fatal(&x), + } } else { - Err(String::from("no existing output_path found")) + String::new() } } - fn load_expected_output(&self, kind: &str) -> String { - self.expected_output_path(kind) - .and_then(|x| self.load_expected_output_from_path(&x)) - .unwrap_or_else(|x| self.fatal(&x)) - } - fn load_expected_output_from_path(&self, path: &Path) -> Result { let mut result = String::new(); match File::open(path).and_then(|mut f| f.read_to_string(&mut result)) { From da4bf140576125c322ba7dafcb1f8585931ab812 Mon Sep 17 00:00:00 2001 From: memoryleak47 Date: Tue, 3 Apr 2018 22:22:58 +0200 Subject: [PATCH 5/6] running compiletest with --compare-mode will now run, even if the stamp is up to date --- src/tools/compiletest/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 795ad0c74b7c2..727d669339673 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -623,7 +623,7 @@ 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"); From 03e1509f577c2a474ade1d286210fbf1142d4103 Mon Sep 17 00:00:00 2001 From: memoryleak47 Date: Tue, 3 Apr 2018 23:36:47 +0200 Subject: [PATCH 6/6] make tidy happy --- src/tools/compiletest/src/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 727d669339673..80cab96434ba7 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -623,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) && config.compare_mode.is_none()) + 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");