Add bless x.py subcommand for easy ui test replacement
This commit is contained in:
parent
e3150564f8
commit
37dee69dac
7 changed files with 111 additions and 59 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -311,6 +311,8 @@ impl<'a> ShouldRun<'a> {
|
|||
pub enum Kind {
|
||||
Build,
|
||||
Check,
|
||||
/// Run tests and replace any failing tests' output files (stderr/stout) with the correct ones
|
||||
Bless,
|
||||
Test,
|
||||
Bench,
|
||||
Dist,
|
||||
|
|
@ -334,6 +336,7 @@ impl<'a> Builder<'a> {
|
|||
native::Llvm, tool::Rustfmt, tool::Miri, native::Lld),
|
||||
Kind::Check => describe!(check::Std, check::Test, check::Rustc, check::CodegenBackend,
|
||||
check::Rustdoc),
|
||||
Kind::Bless |
|
||||
Kind::Test => describe!(test::Tidy, test::Bootstrap, test::Ui, test::RunPass,
|
||||
test::CompileFail, test::ParseFail, test::RunFail, test::RunPassValgrind,
|
||||
test::MirOpt, test::Codegen, test::CodegenUnits, test::Incremental, test::Debuginfo,
|
||||
|
|
@ -367,6 +370,7 @@ impl<'a> Builder<'a> {
|
|||
let kind = match subcommand {
|
||||
"build" => Kind::Build,
|
||||
"doc" => Kind::Doc,
|
||||
"bless" => Kind::Bless,
|
||||
"test" => Kind::Test,
|
||||
"bench" => Kind::Bench,
|
||||
"dist" => Kind::Dist,
|
||||
|
|
@ -408,6 +412,7 @@ impl<'a> Builder<'a> {
|
|||
Subcommand::Build { ref paths } => (Kind::Build, &paths[..]),
|
||||
Subcommand::Check { ref paths } => (Kind::Check, &paths[..]),
|
||||
Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]),
|
||||
Subcommand::Test { ref paths, bless: true, .. } => (Kind::Bless, &paths[..]),
|
||||
Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]),
|
||||
Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]),
|
||||
Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -142,6 +144,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
|
|||
let subcommand = args.iter().find(|&s|
|
||||
(s == "build")
|
||||
|| (s == "check")
|
||||
|| (s == "bless")
|
||||
|| (s == "test")
|
||||
|| (s == "bench")
|
||||
|| (s == "doc")
|
||||
|
|
@ -162,6 +165,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
|
|||
|
||||
// Some subcommands get extra options
|
||||
match subcommand.as_str() {
|
||||
"bless" |
|
||||
"test" => {
|
||||
opts.optflag("", "no-fail-fast", "Run all tests regardless of failure");
|
||||
opts.optmulti("", "test-args", "extra arguments", "ARGS");
|
||||
|
|
@ -248,6 +252,12 @@ Arguments:
|
|||
compilation, so there's no need to pass it separately, though it won't hurt. We also completely
|
||||
ignore the stage passed, as there's no way to compile in non-stage 0 without actually building
|
||||
the compiler.");
|
||||
}
|
||||
"bless" => {
|
||||
subcommand_help.push_str("\n
|
||||
Arguments:
|
||||
This subcommand works exactly like the `test` subcommand, but also updates stderr/stdout files
|
||||
before they cause a test failure");
|
||||
}
|
||||
"test" => {
|
||||
subcommand_help.push_str("\n
|
||||
|
|
@ -319,9 +329,11 @@ Arguments:
|
|||
"check" => {
|
||||
Subcommand::Check { paths: paths }
|
||||
}
|
||||
"bless" |
|
||||
"test" => {
|
||||
Subcommand::Test {
|
||||
paths,
|
||||
bless: subcommand.as_str() == "bless",
|
||||
test_args: matches.opt_strs("test-args"),
|
||||
rustc_args: matches.opt_strs("rustc-args"),
|
||||
fail_fast: !matches.opt_present("no-fail-fast"),
|
||||
|
|
|
|||
|
|
@ -41,16 +41,31 @@ const ADB_TEST_DIR: &str = "/data/tmp/work";
|
|||
/// The two modes of the test runner; tests or benchmarks.
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
|
||||
pub enum TestKind {
|
||||
/// Run `cargo bless`
|
||||
Bless,
|
||||
/// Run `cargo test`
|
||||
Test,
|
||||
/// Run `cargo bench`
|
||||
Bench,
|
||||
}
|
||||
|
||||
impl From<Kind> for TestKind {
|
||||
fn from(kind: Kind) -> Self {
|
||||
match kind {
|
||||
Kind::Test => TestKind::Test,
|
||||
Kind::Bless => TestKind::Bless,
|
||||
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 {
|
||||
match self {
|
||||
// bless and test are both `test` for folder names and cargo subcommands
|
||||
TestKind::Bless |
|
||||
TestKind::Test => "test",
|
||||
TestKind::Bench => "bench",
|
||||
}
|
||||
|
|
@ -60,6 +75,7 @@ impl TestKind {
|
|||
impl fmt::Display for TestKind {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.write_str(match *self {
|
||||
TestKind::Bless => "Testing (bless)",
|
||||
TestKind::Test => "Testing",
|
||||
TestKind::Bench => "Benchmarking",
|
||||
})
|
||||
|
|
@ -951,6 +967,10 @@ impl Step for Compiletest {
|
|||
cmd.arg("--host").arg(&*compiler.host);
|
||||
cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build));
|
||||
|
||||
if builder.kind == Kind::Bless {
|
||||
cmd.arg("--bless");
|
||||
}
|
||||
|
||||
if let Some(ref nodejs) = builder.config.nodejs {
|
||||
cmd.arg("--nodejs").arg(nodejs);
|
||||
}
|
||||
|
|
@ -1342,13 +1362,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,
|
||||
|
|
@ -1394,13 +1408,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,
|
||||
|
|
@ -1461,13 +1469,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,
|
||||
|
|
@ -1625,13 +1627,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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -2926,29 +2926,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!("");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2958,19 +2960,42 @@ 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 `{}`: {}",
|
||||
kind,
|
||||
output_file.display(),
|
||||
e
|
||||
)),
|
||||
let mut files = vec![output_file];
|
||||
if self.config.bless {
|
||||
files.push(self.expected_output_path(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())) {
|
||||
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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue