Skip to content

Commit 37dee69

Browse files
committed
Add bless x.py subcommand for easy ui test replacement
1 parent e315056 commit 37dee69

File tree

7 files changed

+111
-59
lines changed

7 files changed

+111
-59
lines changed

src/bootstrap/bin/rustc.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,12 @@ fn main() {
297297
}
298298

299299
if verbose > 1 {
300-
eprintln!("rustc command: {:?}", cmd);
300+
eprintln!(
301+
"rustc command: {:?}={:?} {:?}",
302+
bootstrap::util::dylib_path_var(),
303+
env::join_paths(&dylib_path).unwrap(),
304+
cmd,
305+
);
301306
eprintln!("sysroot: {:?}", sysroot);
302307
eprintln!("libdir: {:?}", libdir);
303308
}

src/bootstrap/builder.rs

+5
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,8 @@ impl<'a> ShouldRun<'a> {
311311
pub enum Kind {
312312
Build,
313313
Check,
314+
/// Run tests and replace any failing tests' output files (stderr/stout) with the correct ones
315+
Bless,
314316
Test,
315317
Bench,
316318
Dist,
@@ -334,6 +336,7 @@ impl<'a> Builder<'a> {
334336
native::Llvm, tool::Rustfmt, tool::Miri, native::Lld),
335337
Kind::Check => describe!(check::Std, check::Test, check::Rustc, check::CodegenBackend,
336338
check::Rustdoc),
339+
Kind::Bless |
337340
Kind::Test => describe!(test::Tidy, test::Bootstrap, test::Ui, test::RunPass,
338341
test::CompileFail, test::ParseFail, test::RunFail, test::RunPassValgrind,
339342
test::MirOpt, test::Codegen, test::CodegenUnits, test::Incremental, test::Debuginfo,
@@ -367,6 +370,7 @@ impl<'a> Builder<'a> {
367370
let kind = match subcommand {
368371
"build" => Kind::Build,
369372
"doc" => Kind::Doc,
373+
"bless" => Kind::Bless,
370374
"test" => Kind::Test,
371375
"bench" => Kind::Bench,
372376
"dist" => Kind::Dist,
@@ -408,6 +412,7 @@ impl<'a> Builder<'a> {
408412
Subcommand::Build { ref paths } => (Kind::Build, &paths[..]),
409413
Subcommand::Check { ref paths } => (Kind::Check, &paths[..]),
410414
Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]),
415+
Subcommand::Test { ref paths, bless: true, .. } => (Kind::Bless, &paths[..]),
411416
Subcommand::Test { ref paths, .. } => (Kind::Test, &paths[..]),
412417
Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]),
413418
Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]),

src/bootstrap/flags.rs

+12
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ pub enum Subcommand {
5959
},
6060
Test {
6161
paths: Vec<PathBuf>,
62+
/// Whether to automatically update stderr/stdout files
63+
bless: bool,
6264
test_args: Vec<String>,
6365
rustc_args: Vec<String>,
6466
fail_fast: bool,
@@ -142,6 +144,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
142144
let subcommand = args.iter().find(|&s|
143145
(s == "build")
144146
|| (s == "check")
147+
|| (s == "bless")
145148
|| (s == "test")
146149
|| (s == "bench")
147150
|| (s == "doc")
@@ -162,6 +165,7 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`");
162165

163166
// Some subcommands get extra options
164167
match subcommand.as_str() {
168+
"bless" |
165169
"test" => {
166170
opts.optflag("", "no-fail-fast", "Run all tests regardless of failure");
167171
opts.optmulti("", "test-args", "extra arguments", "ARGS");
@@ -248,6 +252,12 @@ Arguments:
248252
compilation, so there's no need to pass it separately, though it won't hurt. We also completely
249253
ignore the stage passed, as there's no way to compile in non-stage 0 without actually building
250254
the compiler.");
255+
}
256+
"bless" => {
257+
subcommand_help.push_str("\n
258+
Arguments:
259+
This subcommand works exactly like the `test` subcommand, but also updates stderr/stdout files
260+
before they cause a test failure");
251261
}
252262
"test" => {
253263
subcommand_help.push_str("\n
@@ -319,9 +329,11 @@ Arguments:
319329
"check" => {
320330
Subcommand::Check { paths: paths }
321331
}
332+
"bless" |
322333
"test" => {
323334
Subcommand::Test {
324335
paths,
336+
bless: subcommand.as_str() == "bless",
325337
test_args: matches.opt_strs("test-args"),
326338
rustc_args: matches.opt_strs("rustc-args"),
327339
fail_fast: !matches.opt_present("no-fail-fast"),

src/bootstrap/test.rs

+24-28
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,31 @@ const ADB_TEST_DIR: &str = "/data/tmp/work";
4141
/// The two modes of the test runner; tests or benchmarks.
4242
#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
4343
pub enum TestKind {
44+
/// Run `cargo bless`
45+
Bless,
4446
/// Run `cargo test`
4547
Test,
4648
/// Run `cargo bench`
4749
Bench,
4850
}
4951

52+
impl From<Kind> for TestKind {
53+
fn from(kind: Kind) -> Self {
54+
match kind {
55+
Kind::Test => TestKind::Test,
56+
Kind::Bless => TestKind::Bless,
57+
Kind::Bench => TestKind::Bench,
58+
_ => panic!("unexpected kind in crate: {:?}", kind)
59+
}
60+
}
61+
}
62+
5063
impl TestKind {
5164
// Return the cargo subcommand for this test kind
5265
fn subcommand(self) -> &'static str {
5366
match self {
67+
// bless and test are both `test` for folder names and cargo subcommands
68+
TestKind::Bless |
5469
TestKind::Test => "test",
5570
TestKind::Bench => "bench",
5671
}
@@ -60,6 +75,7 @@ impl TestKind {
6075
impl fmt::Display for TestKind {
6176
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6277
f.write_str(match *self {
78+
TestKind::Bless => "Testing (bless)",
6379
TestKind::Test => "Testing",
6480
TestKind::Bench => "Benchmarking",
6581
})
@@ -951,6 +967,10 @@ impl Step for Compiletest {
951967
cmd.arg("--host").arg(&*compiler.host);
952968
cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build));
953969

970+
if builder.kind == Kind::Bless {
971+
cmd.arg("--bless");
972+
}
973+
954974
if let Some(ref nodejs) = builder.config.nodejs {
955975
cmd.arg("--nodejs").arg(nodejs);
956976
}
@@ -1342,13 +1362,7 @@ impl Step for CrateLibrustc {
13421362

13431363
for krate in builder.in_tree_crates("rustc-main") {
13441364
if run.path.ends_with(&krate.path) {
1345-
let test_kind = if builder.kind == Kind::Test {
1346-
TestKind::Test
1347-
} else if builder.kind == Kind::Bench {
1348-
TestKind::Bench
1349-
} else {
1350-
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
1351-
};
1365+
let test_kind = builder.kind.into();
13521366

13531367
builder.ensure(CrateLibrustc {
13541368
compiler,
@@ -1394,13 +1408,7 @@ impl Step for CrateNotDefault {
13941408
let builder = run.builder;
13951409
let compiler = builder.compiler(builder.top_stage, run.host);
13961410

1397-
let test_kind = if builder.kind == Kind::Test {
1398-
TestKind::Test
1399-
} else if builder.kind == Kind::Bench {
1400-
TestKind::Bench
1401-
} else {
1402-
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
1403-
};
1411+
let test_kind = builder.kind.into();
14041412

14051413
builder.ensure(CrateNotDefault {
14061414
compiler,
@@ -1461,13 +1469,7 @@ impl Step for Crate {
14611469
let compiler = builder.compiler(builder.top_stage, run.host);
14621470

14631471
let make = |mode: Mode, krate: &CargoCrate| {
1464-
let test_kind = if builder.kind == Kind::Test {
1465-
TestKind::Test
1466-
} else if builder.kind == Kind::Bench {
1467-
TestKind::Bench
1468-
} else {
1469-
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
1470-
};
1472+
let test_kind = builder.kind.into();
14711473

14721474
builder.ensure(Crate {
14731475
compiler,
@@ -1625,13 +1627,7 @@ impl Step for CrateRustdoc {
16251627
fn make_run(run: RunConfig) {
16261628
let builder = run.builder;
16271629

1628-
let test_kind = if builder.kind == Kind::Test {
1629-
TestKind::Test
1630-
} else if builder.kind == Kind::Bench {
1631-
TestKind::Bench
1632-
} else {
1633-
panic!("unexpected builder.kind in crate: {:?}", builder.kind);
1634-
};
1630+
let test_kind = builder.kind.into();
16351631

16361632
builder.ensure(CrateRustdoc {
16371633
host: run.host,

src/tools/compiletest/src/common.rs

+3
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,9 @@ impl CompareMode {
118118

119119
#[derive(Clone)]
120120
pub struct Config {
121+
/// Whether to overwrite stderr/stdout files instead of complaining about changes in output
122+
pub bless: bool,
123+
121124
/// The library paths required for running the compiler
122125
pub compile_lib_path: PathBuf,
123126

src/tools/compiletest/src/main.rs

+6
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ pub fn parse_config(args: Vec<String>) -> Config {
166166
"FLAGS",
167167
)
168168
.optflag("", "verbose", "run tests verbosely, showing all output")
169+
.optflag(
170+
"",
171+
"bless",
172+
"overwrite stderr/stdout files instead of complaining about a mismatch",
173+
)
169174
.optflag(
170175
"",
171176
"quiet",
@@ -290,6 +295,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
290295
let src_base = opt_path(matches, "src-base");
291296
let run_ignored = matches.opt_present("ignored");
292297
Config {
298+
bless: matches.opt_present("bless"),
293299
compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
294300
run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
295301
rustc_path: opt_path(matches, "rustc-path"),

src/tools/compiletest/src/runtest.rs

+55-30
Original file line numberDiff line numberDiff line change
@@ -2926,29 +2926,31 @@ impl<'test> TestCx<'test> {
29262926
return 0;
29272927
}
29282928

2929-
if expected.is_empty() {
2930-
println!("normalized {}:\n{}\n", kind, actual);
2931-
} else {
2932-
println!("diff of {}:\n", kind);
2933-
let diff_results = make_diff(expected, actual, 3);
2934-
for result in diff_results {
2935-
let mut line_number = result.line_number;
2936-
for line in result.lines {
2937-
match line {
2938-
DiffLine::Expected(e) => {
2939-
println!("-\t{}", e);
2940-
line_number += 1;
2941-
}
2942-
DiffLine::Context(c) => {
2943-
println!("{}\t{}", line_number, c);
2944-
line_number += 1;
2945-
}
2946-
DiffLine::Resulting(r) => {
2947-
println!("+\t{}", r);
2929+
if !self.config.bless {
2930+
if expected.is_empty() {
2931+
println!("normalized {}:\n{}\n", kind, actual);
2932+
} else {
2933+
println!("diff of {}:\n", kind);
2934+
let diff_results = make_diff(expected, actual, 3);
2935+
for result in diff_results {
2936+
let mut line_number = result.line_number;
2937+
for line in result.lines {
2938+
match line {
2939+
DiffLine::Expected(e) => {
2940+
println!("-\t{}", e);
2941+
line_number += 1;
2942+
}
2943+
DiffLine::Context(c) => {
2944+
println!("{}\t{}", line_number, c);
2945+
line_number += 1;
2946+
}
2947+
DiffLine::Resulting(r) => {
2948+
println!("+\t{}", r);
2949+
}
29482950
}
29492951
}
2952+
println!("");
29502953
}
2951-
println!("");
29522954
}
29532955
}
29542956

@@ -2958,19 +2960,42 @@ impl<'test> TestCx<'test> {
29582960
.with_extra_extension(mode)
29592961
.with_extra_extension(kind);
29602962

2961-
match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) {
2962-
Ok(()) => {}
2963-
Err(e) => self.fatal(&format!(
2964-
"failed to write {} to `{}`: {}",
2965-
kind,
2966-
output_file.display(),
2967-
e
2968-
)),
2963+
let mut files = vec![output_file];
2964+
if self.config.bless {
2965+
files.push(self.expected_output_path(kind));
2966+
}
2967+
2968+
for output_file in &files {
2969+
if actual.is_empty() {
2970+
if let Err(e) = ::std::fs::remove_file(output_file) {
2971+
self.fatal(&format!(
2972+
"failed to delete `{}`: {}",
2973+
output_file.display(),
2974+
e,
2975+
));
2976+
}
2977+
} else {
2978+
match File::create(&output_file).and_then(|mut f| f.write_all(actual.as_bytes())) {
2979+
Ok(()) => {}
2980+
Err(e) => self.fatal(&format!(
2981+
"failed to write {} to `{}`: {}",
2982+
kind,
2983+
output_file.display(),
2984+
e
2985+
)),
2986+
}
2987+
}
29692988
}
29702989

29712990
println!("\nThe actual {0} differed from the expected {0}.", kind);
2972-
println!("Actual {} saved to {}", kind, output_file.display());
2973-
1
2991+
for output_file in files {
2992+
println!("Actual {} saved to {}", kind, output_file.display());
2993+
}
2994+
if self.config.bless {
2995+
0
2996+
} else {
2997+
1
2998+
}
29742999
}
29753000

29763001
fn create_stamp(&self) {

0 commit comments

Comments
 (0)