Rollup merge of #50806 - oli-obk:gesundheit, r=ehuss

Add `bless` x.py subcommand for easy ui test replacement

fixes #49815

r? @nikomatsakis
This commit is contained in:
Mark Simulacrum
2018-05-17 13:51:26 -06:00
committed by GitHub
12 changed files with 161 additions and 70 deletions

View File

@@ -297,7 +297,12 @@ fn main() {
} }
if verbose > 1 { if verbose > 1 {
eprintln!("rustc command: {:?}", cmd); eprintln!(
"rustc command: {:?}={:?} {:?}",
bootstrap::util::dylib_path_var(),
env::join_paths(&dylib_path).unwrap(),
cmd,
);
eprintln!("sysroot: {:?}", sysroot); eprintln!("sysroot: {:?}", sysroot);
eprintln!("libdir: {:?}", libdir); eprintln!("libdir: {:?}", libdir);
} }

View File

@@ -1460,6 +1460,7 @@ mod __test {
rustc_args: vec![], rustc_args: vec![],
fail_fast: true, fail_fast: true,
doc_tests: DocTests::No, doc_tests: DocTests::No,
bless: false,
}; };
let build = Build::new(config); let build = Build::new(config);

View File

@@ -59,6 +59,8 @@ pub enum Subcommand {
}, },
Test { Test {
paths: Vec<PathBuf>, paths: Vec<PathBuf>,
/// Whether to automatically update stderr/stdout files
bless: bool,
test_args: Vec<String>, test_args: Vec<String>,
rustc_args: Vec<String>, rustc_args: Vec<String>,
fail_fast: bool, fail_fast: bool,
@@ -173,6 +175,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
); );
opts.optflag("", "no-doc", "do not run doc tests"); opts.optflag("", "no-doc", "do not run doc tests");
opts.optflag("", "doc", "only run doc tests"); opts.optflag("", "doc", "only run doc tests");
opts.optflag("", "bless", "update all stderr/stdout files of failing ui tests");
}, },
"bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); }, "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
"clean" => { opts.optflag("", "all", "clean all build artifacts"); }, "clean" => { opts.optflag("", "all", "clean all build artifacts"); },
@@ -258,6 +261,7 @@ Arguments:
./x.py test src/test/run-pass ./x.py test src/test/run-pass
./x.py test src/libstd --test-args hash_map ./x.py test src/libstd --test-args hash_map
./x.py test src/libstd --stage 0 ./x.py test src/libstd --stage 0
./x.py test src/test/ui --bless
If no arguments are passed then the complete artifacts for that stage are If no arguments are passed then the complete artifacts for that stage are
compiled and tested. compiled and tested.
@@ -322,6 +326,7 @@ Arguments:
"test" => { "test" => {
Subcommand::Test { Subcommand::Test {
paths, paths,
bless: matches.opt_present("bless"),
test_args: matches.opt_strs("test-args"), test_args: matches.opt_strs("test-args"),
rustc_args: matches.opt_strs("rustc-args"), rustc_args: matches.opt_strs("rustc-args"),
fail_fast: !matches.opt_present("no-fail-fast"), fail_fast: !matches.opt_present("no-fail-fast"),
@@ -424,6 +429,13 @@ impl Subcommand {
_ => DocTests::Yes, _ => DocTests::Yes,
} }
} }
pub fn bless(&self) -> bool {
match *self {
Subcommand::Test { bless, .. } => bless,
_ => false,
}
}
} }
fn split(s: Vec<String>) -> Vec<String> { fn split(s: Vec<String>) -> Vec<String> {

View File

@@ -47,6 +47,16 @@ pub enum TestKind {
Bench, Bench,
} }
impl From<Kind> for TestKind {
fn from(kind: Kind) -> Self {
match kind {
Kind::Test => TestKind::Test,
Kind::Bench => TestKind::Bench,
_ => panic!("unexpected kind in crate: {:?}", kind)
}
}
}
impl TestKind { impl TestKind {
// Return the cargo subcommand for this test kind // Return the cargo subcommand for this test kind
fn subcommand(self) -> &'static str { fn subcommand(self) -> &'static str {
@@ -951,6 +961,10 @@ impl Step for Compiletest {
cmd.arg("--host").arg(&*compiler.host); cmd.arg("--host").arg(&*compiler.host);
cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build)); cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build));
if builder.config.cmd.bless() {
cmd.arg("--bless");
}
if let Some(ref nodejs) = builder.config.nodejs { if let Some(ref nodejs) = builder.config.nodejs {
cmd.arg("--nodejs").arg(nodejs); cmd.arg("--nodejs").arg(nodejs);
} }
@@ -1342,13 +1356,7 @@ impl Step for CrateLibrustc {
for krate in builder.in_tree_crates("rustc-main") { for krate in builder.in_tree_crates("rustc-main") {
if run.path.ends_with(&krate.path) { if run.path.ends_with(&krate.path) {
let test_kind = if builder.kind == Kind::Test { let test_kind = builder.kind.into();
TestKind::Test
} else if builder.kind == Kind::Bench {
TestKind::Bench
} else {
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
};
builder.ensure(CrateLibrustc { builder.ensure(CrateLibrustc {
compiler, compiler,
@@ -1394,13 +1402,7 @@ impl Step for CrateNotDefault {
let builder = run.builder; let builder = run.builder;
let compiler = builder.compiler(builder.top_stage, run.host); let compiler = builder.compiler(builder.top_stage, run.host);
let test_kind = if builder.kind == Kind::Test { let test_kind = builder.kind.into();
TestKind::Test
} else if builder.kind == Kind::Bench {
TestKind::Bench
} else {
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
};
builder.ensure(CrateNotDefault { builder.ensure(CrateNotDefault {
compiler, compiler,
@@ -1461,13 +1463,7 @@ impl Step for Crate {
let compiler = builder.compiler(builder.top_stage, run.host); let compiler = builder.compiler(builder.top_stage, run.host);
let make = |mode: Mode, krate: &CargoCrate| { let make = |mode: Mode, krate: &CargoCrate| {
let test_kind = if builder.kind == Kind::Test { let test_kind = builder.kind.into();
TestKind::Test
} else if builder.kind == Kind::Bench {
TestKind::Bench
} else {
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
};
builder.ensure(Crate { builder.ensure(Crate {
compiler, compiler,
@@ -1625,13 +1621,7 @@ impl Step for CrateRustdoc {
fn make_run(run: RunConfig) { fn make_run(run: RunConfig) {
let builder = run.builder; let builder = run.builder;
let test_kind = if builder.kind == Kind::Test { let test_kind = builder.kind.into();
TestKind::Test
} else if builder.kind == Kind::Bench {
TestKind::Bench
} else {
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
};
builder.ensure(CrateRustdoc { builder.ensure(CrateRustdoc {
host: run.host, host: run.host,

View File

@@ -140,13 +140,9 @@ check that the test compiles successfully.
### Editing and updating the reference files ### Editing and updating the reference files
If you have changed the compiler's output intentionally, or you are If you have changed the compiler's output intentionally, or you are
making a new test, you can use the script `ui/update-references.sh` to making a new test, you can pass `--bless` to the command you used to
update the references. When you run the test framework, it will report run the tests. This will then copy over the files
various errors: in those errors is a command you can use to run the from the build directory and use them as the new reference.
`ui/update-references.sh` script, which will then copy over the files
from the build directory and use them as the new reference. You can
also just run `ui/update-all-references.sh`. In both cases, you can run
the script with `--help` to get a help message.
### Normalization ### Normalization

View File

@@ -0,0 +1,9 @@
error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
--> $DIR/E0508.rs:18:18
|
LL | let _value = array[0]; //[ast]~ ERROR [E0508]
| ^^^^^^^^ cannot move out of here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0508`.

View File

@@ -0,0 +1,12 @@
error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
--> $DIR/E0508.rs:18:18
|
LL | let _value = array[0]; //[ast]~ ERROR [E0508]
| ^^^^^^^^
| |
| cannot move out of here
| help: consider using a reference instead: `&array[0]`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0508`.

View File

@@ -0,0 +1,9 @@
error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
--> $DIR/E0508.rs:18:18
|
LL | let _value = array[0]; //[ast]~ ERROR [E0508]
| ^^^^^^^^ cannot move out of here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0508`.

20
src/test/ui/E0508.rs Normal file
View File

@@ -0,0 +1,20 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// revisions: ast mir
//[mir]compile-flags: -Z borrowck=mir
struct NonCopy;
fn main() {
let array = [NonCopy; 1];
let _value = array[0]; //[ast]~ ERROR [E0508]
//[mir]~^ ERROR [E0508]
}

View File

@@ -118,6 +118,9 @@ impl CompareMode {
#[derive(Clone)] #[derive(Clone)]
pub struct Config { pub struct Config {
/// Whether to overwrite stderr/stdout files instead of complaining about changes in output
pub bless: bool,
/// The library paths required for running the compiler /// The library paths required for running the compiler
pub compile_lib_path: PathBuf, pub compile_lib_path: PathBuf,

View File

@@ -166,6 +166,11 @@ pub fn parse_config(args: Vec<String>) -> Config {
"FLAGS", "FLAGS",
) )
.optflag("", "verbose", "run tests verbosely, showing all output") .optflag("", "verbose", "run tests verbosely, showing all output")
.optflag(
"",
"bless",
"overwrite stderr/stdout files instead of complaining about a mismatch",
)
.optflag( .optflag(
"", "",
"quiet", "quiet",
@@ -290,6 +295,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
let src_base = opt_path(matches, "src-base"); let src_base = opt_path(matches, "src-base");
let run_ignored = matches.opt_present("ignored"); let run_ignored = matches.opt_present("ignored");
Config { Config {
bless: matches.opt_present("bless"),
compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")), compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
run_lib_path: make_absolute(opt_path(matches, "run-lib-path")), run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
rustc_path: opt_path(matches, "rustc-path"), rustc_path: opt_path(matches, "rustc-path"),

View File

@@ -2596,15 +2596,13 @@ impl<'test> TestCx<'test> {
} }
if errors > 0 { if errors > 0 {
println!("To update references, run this command from build directory:"); println!("To update references, rerun the tests and pass the `--bless` flag");
let relative_path_to_file = self.testpaths let relative_path_to_file = self.testpaths
.relative_dir .relative_dir
.join(self.testpaths.file.file_name().unwrap()); .join(self.testpaths.file.file_name().unwrap());
println!( println!(
"{}/update-references.sh '{}' '{}'", "To only update this specific test, also pass `--test-args {}`",
self.config.src_base.display(), relative_path_to_file.display(),
self.config.build_base.display(),
relative_path_to_file.display()
); );
self.fatal_proc_rec( self.fatal_proc_rec(
&format!("{} errors occurred comparing output.", errors), &format!("{} errors occurred comparing output.", errors),
@@ -2926,6 +2924,7 @@ impl<'test> TestCx<'test> {
return 0; return 0;
} }
if !self.config.bless {
if expected.is_empty() { if expected.is_empty() {
println!("normalized {}:\n{}\n", kind, actual); println!("normalized {}:\n{}\n", kind, actual);
} else { } else {
@@ -2951,6 +2950,7 @@ impl<'test> TestCx<'test> {
println!(""); println!("");
} }
} }
}
let mode = self.config.compare_mode.as_ref().map_or("", |m| m.to_str()); let mode = self.config.compare_mode.as_ref().map_or("", |m| m.to_str());
let output_file = self.output_base_name() let output_file = self.output_base_name()
@@ -2958,6 +2958,26 @@ impl<'test> TestCx<'test> {
.with_extra_extension(mode) .with_extra_extension(mode)
.with_extra_extension(kind); .with_extra_extension(kind);
let mut files = vec![output_file];
if self.config.bless {
files.push(expected_output_path(
self.testpaths,
self.revision,
&self.config.compare_mode,
kind,
));
}
for output_file in &files {
if actual.is_empty() {
if let Err(e) = ::std::fs::remove_file(output_file) {
self.fatal(&format!(
"failed to delete `{}`: {}",
output_file.display(),
e,
));
}
} else {
match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) { match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) {
Ok(()) => {} Ok(()) => {}
Err(e) => self.fatal(&format!( Err(e) => self.fatal(&format!(
@@ -2967,11 +2987,19 @@ impl<'test> TestCx<'test> {
e e
)), )),
} }
}
}
println!("\nThe actual {0} differed from the expected {0}.", kind); println!("\nThe actual {0} differed from the expected {0}.", kind);
for output_file in files {
println!("Actual {} saved to {}", kind, output_file.display()); println!("Actual {} saved to {}", kind, output_file.display());
}
if self.config.bless {
0
} else {
1 1
} }
}
fn create_stamp(&self) { fn create_stamp(&self) {
let mut f = File::create(::stamp(&self.config, self.testpaths, self.revision)).unwrap(); let mut f = File::create(::stamp(&self.config, self.testpaths, self.revision)).unwrap();