Skip to content

Commit c05e7bd

Browse files
authored
Rollup merge of #133733 - jyn514:compiletest-diffs, r=jieyouxu
compiletest: show the difference between the normalized output and the actual output for lines which didn't match example output: ``` failures: ---- [ui] tests/ui/layout/enum.rs stdout ---- diff of stderr: - error: align: AbiAndPrefAlign { abi: Align(2 bytes), pref: $PREF_ALIGN } + error: align: AbiAndPrefAlign { abi: Align(2 bytes), pref: $PREF_ALIN } 2 --> $DIR/enum.rs:9:1 3 | 4 LL | enum UninhabitedVariantAlign { Note: some mismatched output was normalized before being compared - error: align: AbiAndPrefAlign { abi: Align(2 bytes), pref: Align(8 bytes) } - --> /home/jyn/src/rust2/tests/ui/layout/enum.rs:9:1 + error: align: AbiAndPrefAlign { abi: Align(2 bytes), pref: $PREF_ALIN } ```
2 parents 1868c8f + 8aacd1c commit c05e7bd

File tree

3 files changed

+119
-35
lines changed

3 files changed

+119
-35
lines changed

Diff for: src/tools/compiletest/src/runtest.rs

+106-30
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::common::{
2222
UI_STDERR, UI_STDOUT, UI_SVG, UI_WINDOWS_SVG, Ui, expected_output_path, incremental_dir,
2323
output_base_dir, output_base_name, output_testname_unique,
2424
};
25-
use crate::compute_diff::{write_diff, write_filtered_diff};
25+
use crate::compute_diff::{DiffLine, make_diff, write_diff, write_filtered_diff};
2626
use crate::errors::{self, Error, ErrorKind};
2727
use crate::header::TestProps;
2828
use crate::read2::{Truncated, read2_abbreviated};
@@ -2295,17 +2295,31 @@ impl<'test> TestCx<'test> {
22952295
match output_kind {
22962296
TestOutput::Compile => {
22972297
if !self.props.dont_check_compiler_stdout {
2298-
errors +=
2299-
self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
2298+
errors += self.compare_output(
2299+
stdout_kind,
2300+
&normalized_stdout,
2301+
&proc_res.stdout,
2302+
&expected_stdout,
2303+
);
23002304
}
23012305
if !self.props.dont_check_compiler_stderr {
2302-
errors +=
2303-
self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
2306+
errors += self.compare_output(
2307+
stderr_kind,
2308+
&normalized_stderr,
2309+
&stderr,
2310+
&expected_stderr,
2311+
);
23042312
}
23052313
}
23062314
TestOutput::Run => {
2307-
errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
2308-
errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
2315+
errors += self.compare_output(
2316+
stdout_kind,
2317+
&normalized_stdout,
2318+
&proc_res.stdout,
2319+
&expected_stdout,
2320+
);
2321+
errors +=
2322+
self.compare_output(stderr_kind, &normalized_stderr, &stderr, &expected_stderr);
23092323
}
23102324
}
23112325
errors
@@ -2533,7 +2547,13 @@ impl<'test> TestCx<'test> {
25332547
}
25342548
}
25352549

2536-
fn compare_output(&self, stream: &str, actual: &str, expected: &str) -> usize {
2550+
fn compare_output(
2551+
&self,
2552+
stream: &str,
2553+
actual: &str,
2554+
actual_unnormalized: &str,
2555+
expected: &str,
2556+
) -> usize {
25372557
let are_different = match (self.force_color_svg(), expected.find('\n'), actual.find('\n')) {
25382558
// FIXME: We ignore the first line of SVG files
25392559
// because the width parameter is non-deterministic.
@@ -2590,28 +2610,14 @@ impl<'test> TestCx<'test> {
25902610
if expected.is_empty() {
25912611
println!("normalized {}:\n{}\n", stream, actual);
25922612
} else {
2593-
println!("diff of {stream}:\n");
2594-
if let Some(diff_command) = self.config.diff_command.as_deref() {
2595-
let mut args = diff_command.split_whitespace();
2596-
let name = args.next().unwrap();
2597-
match Command::new(name)
2598-
.args(args)
2599-
.args([&expected_path, &actual_path])
2600-
.output()
2601-
{
2602-
Err(err) => {
2603-
self.fatal(&format!(
2604-
"failed to call custom diff command `{diff_command}`: {err}"
2605-
));
2606-
}
2607-
Ok(output) => {
2608-
let output = String::from_utf8_lossy(&output.stdout);
2609-
print!("{output}");
2610-
}
2611-
}
2612-
} else {
2613-
print!("{}", write_diff(expected, actual, 3));
2614-
}
2613+
self.show_diff(
2614+
stream,
2615+
&expected_path,
2616+
&actual_path,
2617+
expected,
2618+
actual,
2619+
actual_unnormalized,
2620+
);
26152621
}
26162622
} else {
26172623
// Delete non-revision .stderr/.stdout file if revisions are used.
@@ -2633,6 +2639,76 @@ impl<'test> TestCx<'test> {
26332639
if self.config.bless { 0 } else { 1 }
26342640
}
26352641

2642+
/// Returns whether to show the full stderr/stdout.
2643+
fn show_diff(
2644+
&self,
2645+
stream: &str,
2646+
expected_path: &Path,
2647+
actual_path: &Path,
2648+
expected: &str,
2649+
actual: &str,
2650+
actual_unnormalized: &str,
2651+
) {
2652+
eprintln!("diff of {stream}:\n");
2653+
if let Some(diff_command) = self.config.diff_command.as_deref() {
2654+
let mut args = diff_command.split_whitespace();
2655+
let name = args.next().unwrap();
2656+
match Command::new(name).args(args).args([expected_path, actual_path]).output() {
2657+
Err(err) => {
2658+
self.fatal(&format!(
2659+
"failed to call custom diff command `{diff_command}`: {err}"
2660+
));
2661+
}
2662+
Ok(output) => {
2663+
let output = String::from_utf8_lossy(&output.stdout);
2664+
eprint!("{output}");
2665+
}
2666+
}
2667+
} else {
2668+
eprint!("{}", write_diff(expected, actual, 3));
2669+
}
2670+
2671+
// NOTE: argument order is important, we need `actual` to be on the left so the line number match up when we compare it to `actual_unnormalized` below.
2672+
let diff_results = make_diff(actual, expected, 0);
2673+
2674+
let (mut mismatches_normalized, mut mismatch_line_nos) = (String::new(), vec![]);
2675+
for hunk in diff_results {
2676+
let mut line_no = hunk.line_number;
2677+
for line in hunk.lines {
2678+
// NOTE: `Expected` is actually correct here, the argument order is reversed so our line numbers match up
2679+
if let DiffLine::Expected(normalized) = line {
2680+
mismatches_normalized += &normalized;
2681+
mismatches_normalized += "\n";
2682+
mismatch_line_nos.push(line_no);
2683+
line_no += 1;
2684+
}
2685+
}
2686+
}
2687+
let mut mismatches_unnormalized = String::new();
2688+
let diff_normalized = make_diff(actual, actual_unnormalized, 0);
2689+
for hunk in diff_normalized {
2690+
if mismatch_line_nos.contains(&hunk.line_number) {
2691+
for line in hunk.lines {
2692+
if let DiffLine::Resulting(unnormalized) = line {
2693+
mismatches_unnormalized += &unnormalized;
2694+
mismatches_unnormalized += "\n";
2695+
}
2696+
}
2697+
}
2698+
}
2699+
2700+
let normalized_diff = make_diff(&mismatches_normalized, &mismatches_unnormalized, 0);
2701+
// HACK: instead of checking if each hunk is empty, this only checks if the whole input is empty. we should be smarter about this so we don't treat added or removed output as normalized.
2702+
if !normalized_diff.is_empty()
2703+
&& !mismatches_unnormalized.is_empty()
2704+
&& !mismatches_normalized.is_empty()
2705+
{
2706+
eprintln!("Note: some mismatched output was normalized before being compared");
2707+
// FIXME: respect diff_command
2708+
eprint!("{}", write_diff(&mismatches_unnormalized, &mismatches_normalized, 0));
2709+
}
2710+
}
2711+
26362712
fn check_and_prune_duplicate_outputs(
26372713
&self,
26382714
proc_res: &ProcRes,

Diff for: src/tools/compiletest/src/runtest/coverage.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,12 @@ impl<'test> TestCx<'test> {
3939
let expected_coverage_dump = self.load_expected_output(kind);
4040
let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]);
4141

42-
let coverage_dump_errors =
43-
self.compare_output(kind, &actual_coverage_dump, &expected_coverage_dump);
42+
let coverage_dump_errors = self.compare_output(
43+
kind,
44+
&actual_coverage_dump,
45+
&proc_res.stdout,
46+
&expected_coverage_dump,
47+
);
4448

4549
if coverage_dump_errors > 0 {
4650
self.fatal_proc_rec(
@@ -135,8 +139,12 @@ impl<'test> TestCx<'test> {
135139
self.fatal_proc_rec(&err, &proc_res);
136140
});
137141

138-
let coverage_errors =
139-
self.compare_output(kind, &normalized_actual_coverage, &expected_coverage);
142+
let coverage_errors = self.compare_output(
143+
kind,
144+
&normalized_actual_coverage,
145+
&proc_res.stdout,
146+
&expected_coverage,
147+
);
140148

141149
if coverage_errors > 0 {
142150
self.fatal_proc_rec(

Diff for: src/tools/compiletest/src/runtest/ui.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ impl TestCx<'_> {
100100
)
101101
});
102102

103-
errors += self.compare_output("fixed", &fixed_code, &expected_fixed);
103+
errors += self.compare_output("fixed", &fixed_code, &fixed_code, &expected_fixed);
104104
} else if !expected_fixed.is_empty() {
105105
panic!(
106106
"the `//@ run-rustfix` directive wasn't found but a `*.fixed` \

0 commit comments

Comments
 (0)