Auto merge of #49293 - memoryleak47:add-compiletest-nll-compare-mode, r=pnkfelix
Add compiletest `--compare-mode nll` option Before implementing the tidy stuff, I'd appreciate if someone reviews the changes so far. This is my first non-trivial pull request, so I could really use some feedback. :) closes #48879. r? @nikomatsakis
This commit is contained in:
commit
db4235c4fd
@ -95,6 +95,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)]
|
#[derive(Clone)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// The library paths required for running the compiler
|
/// The library paths required for running the compiler
|
||||||
@ -210,6 +230,9 @@ pub struct Config {
|
|||||||
/// where to find the remote test client process, if we're using it
|
/// where to find the remote test client process, if we're using it
|
||||||
pub remote_test_client: Option<PathBuf>,
|
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
|
// Configuration for various run-make tests frobbing things like C compilers
|
||||||
// or querying about various LLVM component information.
|
// or querying about various LLVM component information.
|
||||||
pub cc: String,
|
pub cc: String,
|
||||||
@ -230,12 +253,19 @@ pub struct TestPaths {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Used by `ui` tests to generate things like `foo.stderr` from `foo.rs`.
|
/// 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));
|
assert!(UI_EXTENSIONS.contains(&kind));
|
||||||
let extension = match revision {
|
let mut parts = Vec::new();
|
||||||
Some(r) => format!("{}.{}", r, kind),
|
|
||||||
None => kind.to_string(),
|
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)
|
testpaths.file.with_extension(extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ use getopts::Options;
|
|||||||
use common::{Config, TestPaths};
|
use common::{Config, TestPaths};
|
||||||
use common::{DebugInfoGdb, DebugInfoLldb, Mode, Pretty};
|
use common::{DebugInfoGdb, DebugInfoLldb, Mode, Pretty};
|
||||||
use common::{expected_output_path, UI_EXTENSIONS};
|
use common::{expected_output_path, UI_EXTENSIONS};
|
||||||
|
use common::CompareMode;
|
||||||
use test::ColorConfig;
|
use test::ColorConfig;
|
||||||
use util::logv;
|
use util::logv;
|
||||||
|
|
||||||
@ -227,6 +228,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||||||
"path to the remote test client",
|
"path to the remote test client",
|
||||||
"PATH",
|
"PATH",
|
||||||
)
|
)
|
||||||
|
.optopt(
|
||||||
|
"",
|
||||||
|
"compare-mode",
|
||||||
|
"mode describing what file the actual ui output will be compared to",
|
||||||
|
"COMPARE MODE"
|
||||||
|
)
|
||||||
.optflag("h", "help", "show this message");
|
.optflag("h", "help", "show this message");
|
||||||
|
|
||||||
let (argv0, args_) = args.split_first().unwrap();
|
let (argv0, args_) = args.split_first().unwrap();
|
||||||
@ -320,6 +327,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
|
|||||||
quiet: matches.opt_present("quiet"),
|
quiet: matches.opt_present("quiet"),
|
||||||
color,
|
color,
|
||||||
remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
|
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(),
|
cc: matches.opt_str("cc").unwrap(),
|
||||||
cxx: matches.opt_str("cxx").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
|
// 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.mode == DebugInfoGdb || config.mode == DebugInfoLldb)
|
||||||
&& config.target.contains("emscripten");
|
&& config.target.contains("emscripten");
|
||||||
|
|
||||||
@ -688,12 +697,15 @@ fn up_to_date(config: &Config, testpaths: &TestPaths, props: &EarlyProps) -> boo
|
|||||||
// UI test files.
|
// UI test files.
|
||||||
for extension in UI_EXTENSIONS {
|
for extension in UI_EXTENSIONS {
|
||||||
for revision in &props.revisions {
|
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));
|
inputs.push(mtime(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
if props.revisions.is_empty() {
|
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));
|
inputs.push(mtime(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
|
|||||||
use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc};
|
use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc};
|
||||||
use common::{Incremental, MirOpt, RunMake, Ui};
|
use common::{Incremental, MirOpt, RunMake, Ui};
|
||||||
use common::{expected_output_path, UI_STDERR, UI_STDOUT};
|
use common::{expected_output_path, UI_STDERR, UI_STDOUT};
|
||||||
|
use common::CompareMode;
|
||||||
use diff;
|
use diff;
|
||||||
use errors::{self, Error, ErrorKind};
|
use errors::{self, Error, ErrorKind};
|
||||||
use filetime::FileTime;
|
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 {
|
if self.props.force_host {
|
||||||
rustc.args(self.split_maybe_args(&self.config.host_rustcflags));
|
rustc.args(self.split_maybe_args(&self.config.host_rustcflags));
|
||||||
} else {
|
} else {
|
||||||
@ -2505,11 +2513,8 @@ impl<'test> TestCx<'test> {
|
|||||||
let proc_res = self.compile_test();
|
let proc_res = self.compile_test();
|
||||||
self.check_if_test_should_compile(&proc_res);
|
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(UI_STDERR);
|
||||||
let expected_stderr = self.load_expected_output(&expected_stderr_path);
|
let expected_stdout = self.load_expected_output(UI_STDOUT);
|
||||||
|
|
||||||
let expected_stdout_path = self.expected_output_path(UI_STDOUT);
|
|
||||||
let expected_stdout = self.load_expected_output(&expected_stdout_path);
|
|
||||||
|
|
||||||
let normalized_stdout =
|
let normalized_stdout =
|
||||||
self.normalize_output(&proc_res.stdout, &self.props.normalize_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);
|
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() {
|
if !expected_errors.is_empty() || !proc_res.status.success() {
|
||||||
// "// error-pattern" comments
|
// "// error-pattern" comments
|
||||||
self.check_expected_errors(expected_errors, &proc_res);
|
self.check_expected_errors(expected_errors, &proc_res);
|
||||||
@ -2795,19 +2800,32 @@ impl<'test> TestCx<'test> {
|
|||||||
normalized
|
normalized
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expected_output_path(&self, kind: &str) -> PathBuf {
|
fn load_expected_output(&self, kind: &str) -> String {
|
||||||
expected_output_path(&self.testpaths, self.revision, kind)
|
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() && self.config.compare_mode.is_some() {
|
||||||
if !path.exists() {
|
// fallback!
|
||||||
return String::new();
|
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();
|
let mut result = String::new();
|
||||||
match File::open(path).and_then(|mut f| f.read_to_string(&mut result)) {
|
match File::open(path).and_then(|mut f| f.read_to_string(&mut result)) {
|
||||||
Ok(_) => result,
|
Ok(_) => Ok(result),
|
||||||
Err(e) => self.fatal(&format!(
|
Err(e) => Err(format!(
|
||||||
"failed to load expected output from `{}`: {}",
|
"failed to load expected output from `{}`: {}",
|
||||||
path.display(),
|
path.display(),
|
||||||
e
|
e
|
||||||
|
Loading…
Reference in New Issue
Block a user