Skip to content

Commit 0f03576

Browse files
author
Orion Gonzalez
committed
implemented custom differ
1 parent 5610223 commit 0f03576

File tree

5 files changed

+63
-39
lines changed

5 files changed

+63
-39
lines changed

config.example.toml

+3
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,9 @@
414414
# Specify the location of the Android NDK. Used when targeting Android.
415415
#android-ndk = "/path/to/android-ndk-r26d"
416416

417+
# What custom diff tool to use for displaying compiletest tests.
418+
#display-diff-tool = "difft --color=always --background=light --display=side-by-side"
419+
417420
# =============================================================================
418421
# General install configuration options
419422
# =============================================================================

src/bootstrap/src/core/build_steps/test.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1839,6 +1839,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
18391839

18401840
let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
18411841
flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
1842+
if let Some(display_diff_tool) = &builder.config.display_diff_tool {
1843+
flags.push(format!(r#"--display-diff-tool="{display_diff_tool}""#));
1844+
}
18421845
flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
18431846

18441847
if suite != "mir-opt" {

src/bootstrap/src/core/config/config.rs

+6
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,9 @@ pub struct Config {
365365
/// The paths to work with. For example: with `./x check foo bar` we get
366366
/// `paths=["foo", "bar"]`.
367367
pub paths: Vec<PathBuf>,
368+
369+
/// What custom diff tool to use for displaying compiletest tests.
370+
pub display_diff_tool: Option<String>,
368371
}
369372

370373
#[derive(Clone, Debug, Default)]
@@ -885,6 +888,7 @@ define_config! {
885888
metrics: Option<bool> = "metrics",
886889
android_ndk: Option<PathBuf> = "android-ndk",
887890
optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
891+
display_diff_tool: Option<String> = "display-diff-tool",
888892
}
889893
}
890894

@@ -1504,6 +1508,7 @@ impl Config {
15041508
metrics: _,
15051509
android_ndk,
15061510
optimized_compiler_builtins,
1511+
display_diff_tool,
15071512
} = toml.build.unwrap_or_default();
15081513

15091514
if let Some(file_build) = build {
@@ -2141,6 +2146,7 @@ impl Config {
21412146
config.rust_debuginfo_level_tests = debuginfo_level_tests.unwrap_or(DebuginfoLevel::None);
21422147
config.optimized_compiler_builtins =
21432148
optimized_compiler_builtins.unwrap_or(config.channel != "dev");
2149+
config.display_diff_tool = display_diff_tool;
21442150

21452151
let download_rustc = config.download_rustc_commit.is_some();
21462152
// See https://github.com/rust-lang/compiler-team/issues/326

src/tools/compiletest/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,9 @@ pub fn parse_config(args: Vec<String>) -> Config {
171171
"git-merge-commit-email",
172172
"email address used for finding merge commits",
173173
"EMAIL",
174-
);
174+
)
175+
.optopt("", "display-diff-tool", "What custom diff tool to use for displaying compiletest tests.", "COMMAND")
176+
;
175177

176178
let (argv0, args_) = args.split_first().unwrap();
177179
if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
@@ -360,7 +362,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
360362
git_merge_commit_email: matches.opt_str("git-merge-commit-email").unwrap(),
361363

362364
profiler_support: matches.opt_present("profiler-support"),
363-
diff_command: env::var("COMPILETEST_DIFF_TOOL").ok(),
365+
diff_command: matches.opt_str("display-diff-tool"),
364366
}
365367
}
366368

src/tools/compiletest/src/runtest.rs

+47-37
Original file line numberDiff line numberDiff line change
@@ -2480,7 +2480,7 @@ impl<'test> TestCx<'test> {
24802480
}
24812481
}
24822482

2483-
fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize {
2483+
fn compare_output(&self, stream: &str, actual: &str, expected: &str) -> usize {
24842484
let are_different = match (self.force_color_svg(), expected.find('\n'), actual.find('\n')) {
24852485
// FIXME: We ignore the first line of SVG files
24862486
// because the width parameter is non-deterministic.
@@ -2520,56 +2520,66 @@ impl<'test> TestCx<'test> {
25202520
(expected, actual)
25212521
};
25222522

2523+
// Write the actual output to a file in build/
2524+
let test_name = self.config.compare_mode.as_ref().map_or("", |m| m.to_str());
2525+
let actual_path = self
2526+
.output_base_name()
2527+
.with_extra_extension(self.revision.unwrap_or(""))
2528+
.with_extra_extension(test_name)
2529+
.with_extra_extension(stream);
2530+
2531+
if let Err(err) = fs::write(&actual_path, &actual) {
2532+
self.fatal(&format!("failed to write {stream} to `{actual_path:?}`: {err}",));
2533+
}
2534+
println!("Saved the actual {stream} to {actual_path:?}");
2535+
2536+
let expected_path =
2537+
expected_output_path(self.testpaths, self.revision, &self.config.compare_mode, stream);
2538+
25232539
if !self.config.bless {
25242540
if expected.is_empty() {
2525-
println!("normalized {}:\n{}\n", kind, actual);
2541+
println!("normalized {}:\n{}\n", stream, actual);
25262542
} else {
2527-
println!("diff of {}:\n", kind);
2528-
print!("{}", write_diff(expected, actual, 3));
2543+
println!("diff of {stream}:\n");
2544+
if let Some(diff_command) = self.config.diff_command.as_deref() {
2545+
let mut args = diff_command.split_whitespace();
2546+
let name = args.next().unwrap();
2547+
match Command::new(name)
2548+
.args(args)
2549+
.args([&expected_path, &actual_path])
2550+
.output()
2551+
{
2552+
Err(err) => {
2553+
self.fatal(&format!(
2554+
"failed to call custom diff command `{diff_command}`: {err}"
2555+
));
2556+
}
2557+
Ok(output) => {
2558+
let output = String::from_utf8_lossy_owned(output.stdout).unwrap();
2559+
print!("{output}");
2560+
}
2561+
}
2562+
} else {
2563+
print!("{}", write_diff(expected, actual, 3));
2564+
}
25292565
}
2530-
}
2531-
2532-
let mode = self.config.compare_mode.as_ref().map_or("", |m| m.to_str());
2533-
let output_file = self
2534-
.output_base_name()
2535-
.with_extra_extension(self.revision.unwrap_or(""))
2536-
.with_extra_extension(mode)
2537-
.with_extra_extension(kind);
2538-
2539-
let mut files = vec![output_file];
2540-
if self.config.bless {
2566+
} else {
25412567
// Delete non-revision .stderr/.stdout file if revisions are used.
25422568
// Without this, we'd just generate the new files and leave the old files around.
25432569
if self.revision.is_some() {
25442570
let old =
2545-
expected_output_path(self.testpaths, None, &self.config.compare_mode, kind);
2571+
expected_output_path(self.testpaths, None, &self.config.compare_mode, stream);
25462572
self.delete_file(&old);
25472573
}
2548-
files.push(expected_output_path(
2549-
self.testpaths,
2550-
self.revision,
2551-
&self.config.compare_mode,
2552-
kind,
2553-
));
2554-
}
25552574

2556-
for output_file in &files {
2557-
if actual.is_empty() {
2558-
self.delete_file(output_file);
2559-
} else if let Err(err) = fs::write(&output_file, &actual) {
2560-
self.fatal(&format!(
2561-
"failed to write {} to `{}`: {}",
2562-
kind,
2563-
output_file.display(),
2564-
err,
2565-
));
2575+
if let Err(err) = fs::write(&expected_path, &actual) {
2576+
self.fatal(&format!("failed to write {stream} to `{expected_path:?}`: {err}"));
25662577
}
2578+
println!("Blessing the {stream} of {test_name} in {expected_path:?}");
25672579
}
25682580

2569-
println!("\nThe actual {0} differed from the expected {0}.", kind);
2570-
for output_file in files {
2571-
println!("Actual {} saved to {}", kind, output_file.display());
2572-
}
2581+
println!("\nThe actual {0} differed from the expected {0}.", stream);
2582+
25732583
if self.config.bless { 0 } else { 1 }
25742584
}
25752585

0 commit comments

Comments
 (0)