Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add bless x.py subcommand for easy ui test replacement #50806

Merged
merged 5 commits into from
May 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/bootstrap/bin/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,12 @@ fn main() {
}

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!("libdir: {:?}", libdir);
}
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1461,6 +1461,7 @@ mod __test {
rustc_args: vec![],
fail_fast: true,
doc_tests: DocTests::No,
bless: false,
};

let build = Build::new(config);
Expand Down
12 changes: 12 additions & 0 deletions src/bootstrap/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ pub enum Subcommand {
},
Test {
paths: Vec<PathBuf>,
/// Whether to automatically update stderr/stdout files
bless: bool,
test_args: Vec<String>,
rustc_args: Vec<String>,
fail_fast: bool,
Expand Down Expand Up @@ -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("", "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"); },
"clean" => { opts.optflag("", "all", "clean all build artifacts"); },
Expand Down Expand Up @@ -258,6 +261,7 @@ Arguments:
./x.py test src/test/run-pass
./x.py test src/libstd --test-args hash_map
./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
compiled and tested.
Expand Down Expand Up @@ -322,6 +326,7 @@ Arguments:
"test" => {
Subcommand::Test {
paths,
bless: matches.opt_present("bless"),
test_args: matches.opt_strs("test-args"),
rustc_args: matches.opt_strs("rustc-args"),
fail_fast: !matches.opt_present("no-fail-fast"),
Expand Down Expand Up @@ -424,6 +429,13 @@ impl Subcommand {
_ => DocTests::Yes,
}
}

pub fn bless(&self) -> bool {
match *self {
Subcommand::Test { bless, .. } => bless,
_ => false,
}
}
}

fn split(s: Vec<String>) -> Vec<String> {
Expand Down
46 changes: 18 additions & 28 deletions src/bootstrap/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ pub enum TestKind {
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 {
// Return the cargo subcommand for this test kind
fn subcommand(self) -> &'static str {
Expand Down Expand Up @@ -951,6 +961,10 @@ impl Step for Compiletest {
cmd.arg("--host").arg(&*compiler.host);
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 {
cmd.arg("--nodejs").arg(nodejs);
}
Expand Down Expand Up @@ -1342,13 +1356,7 @@ impl Step for CrateLibrustc {

for krate in builder.in_tree_crates("rustc-main") {
if run.path.ends_with(&krate.path) {
let test_kind = if builder.kind == Kind::Test {
TestKind::Test
} else if builder.kind == Kind::Bench {
TestKind::Bench
} else {
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
};
let test_kind = builder.kind.into();

builder.ensure(CrateLibrustc {
compiler,
Expand Down Expand Up @@ -1394,13 +1402,7 @@ impl Step for CrateNotDefault {
let builder = run.builder;
let compiler = builder.compiler(builder.top_stage, run.host);

let test_kind = if builder.kind == Kind::Test {
TestKind::Test
} else if builder.kind == Kind::Bench {
TestKind::Bench
} else {
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
};
let test_kind = builder.kind.into();

builder.ensure(CrateNotDefault {
compiler,
Expand Down Expand Up @@ -1461,13 +1463,7 @@ impl Step for Crate {
let compiler = builder.compiler(builder.top_stage, run.host);

let make = |mode: Mode, krate: &CargoCrate| {
let test_kind = if builder.kind == Kind::Test {
TestKind::Test
} else if builder.kind == Kind::Bench {
TestKind::Bench
} else {
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
};
let test_kind = builder.kind.into();

builder.ensure(Crate {
compiler,
Expand Down Expand Up @@ -1625,13 +1621,7 @@ impl Step for CrateRustdoc {
fn make_run(run: RunConfig) {
let builder = run.builder;

let test_kind = if builder.kind == Kind::Test {
TestKind::Test
} else if builder.kind == Kind::Bench {
TestKind::Bench
} else {
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
};
let test_kind = builder.kind.into();

builder.ensure(CrateRustdoc {
host: run.host,
Expand Down
10 changes: 3 additions & 7 deletions src/test/COMPILER_TESTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,9 @@ check that the test compiles successfully.
### Editing and updating the reference files

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
update the references. When you run the test framework, it will report
various errors: in those errors is a command you can use to run the
`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.
making a new test, you can pass `--bless` to the command you used to
run the tests. This will then copy over the files
from the build directory and use them as the new reference.

### Normalization

Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/E0508.ast.nll.stderr
Original file line number Diff line number Diff line change
@@ -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`.
12 changes: 12 additions & 0 deletions src/test/ui/E0508.ast.stderr
Original file line number Diff line number Diff line change
@@ -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`.
9 changes: 9 additions & 0 deletions src/test/ui/E0508.mir.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions src/test/ui/E0508.rs
Original file line number Diff line number Diff line change
@@ -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]
}
3 changes: 3 additions & 0 deletions src/tools/compiletest/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ impl CompareMode {

#[derive(Clone)]
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
pub compile_lib_path: PathBuf,

Expand Down
6 changes: 6 additions & 0 deletions src/tools/compiletest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ pub fn parse_config(args: Vec<String>) -> Config {
"FLAGS",
)
.optflag("", "verbose", "run tests verbosely, showing all output")
.optflag(
"",
"bless",
"overwrite stderr/stdout files instead of complaining about a mismatch",
)
.optflag(
"",
"quiet",
Expand Down Expand Up @@ -290,6 +295,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
let src_base = opt_path(matches, "src-base");
let run_ignored = matches.opt_present("ignored");
Config {
bless: matches.opt_present("bless"),
compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
rustc_path: opt_path(matches, "rustc-path"),
Expand Down
96 changes: 62 additions & 34 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2596,15 +2596,13 @@ impl<'test> TestCx<'test> {
}

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
.relative_dir
.join(self.testpaths.file.file_name().unwrap());
println!(
"{}/update-references.sh '{}' '{}'",
self.config.src_base.display(),
self.config.build_base.display(),
relative_path_to_file.display()
"To only update this specific test, also pass `--test-args {}`",
relative_path_to_file.display(),
);
self.fatal_proc_rec(
&format!("{} errors occurred comparing output.", errors),
Expand Down Expand Up @@ -2926,29 +2924,31 @@ impl<'test> TestCx<'test> {
return 0;
}

if expected.is_empty() {
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);
if !self.config.bless {
if expected.is_empty() {
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!("");
}
println!("");
}
}

Expand All @@ -2958,19 +2958,47 @@ impl<'test> TestCx<'test> {
.with_extra_extension(mode)
.with_extra_extension(kind);

match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) {
Ok(()) => {}
Err(e) => self.fatal(&format!(
"failed to write {} to `{}`: {}",
let mut files = vec![output_file];
if self.config.bless {
files.push(expected_output_path(
self.testpaths,
self.revision,
&self.config.compare_mode,
kind,
output_file.display(),
e
)),
));
}

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())) {
Ok(()) => {}
Err(e) => self.fatal(&format!(
"failed to write {} to `{}`: {}",
kind,
output_file.display(),
e
)),
}
}
}

println!("\nThe actual {0} differed from the expected {0}.", kind);
println!("Actual {} saved to {}", kind, output_file.display());
1
for output_file in files {
println!("Actual {} saved to {}", kind, output_file.display());
}
if self.config.bless {
0
} else {
1
}
}

fn create_stamp(&self) {
Expand Down