Skip to content

Commit fa85f12

Browse files
committed
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 } ```
1 parent 5bbbc09 commit fa85f12

File tree

3 files changed

+116
-35
lines changed

3 files changed

+116
-35
lines changed

src/tools/compiletest/src/runtest.rs

+103-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};
@@ -2292,17 +2292,31 @@ impl<'test> TestCx<'test> {
22922292
match output_kind {
22932293
TestOutput::Compile => {
22942294
if !self.props.dont_check_compiler_stdout {
2295-
errors +=
2296-
self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
2295+
errors += self.compare_output(
2296+
stdout_kind,
2297+
&normalized_stdout,
2298+
&proc_res.stdout,
2299+
&expected_stdout,
2300+
);
22972301
}
22982302
if !self.props.dont_check_compiler_stderr {
2299-
errors +=
2300-
self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
2303+
errors += self.compare_output(
2304+
stderr_kind,
2305+
&normalized_stderr,
2306+
&stderr,
2307+
&expected_stderr,
2308+
);
23012309
}
23022310
}
23032311
TestOutput::Run => {
2304-
errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
2305-
errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
2312+
errors += self.compare_output(
2313+
stdout_kind,
2314+
&normalized_stdout,
2315+
&proc_res.stdout,
2316+
&expected_stdout,
2317+
);
2318+
errors +=
2319+
self.compare_output(stderr_kind, &normalized_stderr, &stderr, &expected_stderr);
23062320
}
23072321
}
23082322
errors
@@ -2530,7 +2544,13 @@ impl<'test> TestCx<'test> {
25302544
}
25312545
}
25322546

2533-
fn compare_output(&self, stream: &str, actual: &str, expected: &str) -> usize {
2547+
fn compare_output(
2548+
&self,
2549+
stream: &str,
2550+
actual: &str,
2551+
actual_unnormalized: &str,
2552+
expected: &str,
2553+
) -> usize {
25342554
let are_different = match (self.force_color_svg(), expected.find('\n'), actual.find('\n')) {
25352555
// FIXME: We ignore the first line of SVG files
25362556
// 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,73 @@ 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+
println!("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+
print!("{output}");
2665+
}
2666+
}
2667+
} else {
2668+
print!("{}", write_diff(expected, actual, context_size));
2669+
}
2670+
2671+
let context_size = 3;
2672+
// 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.
2673+
let diff_results = make_diff(actual, expected, context_size);
2674+
2675+
let (mut mismatches_normalized, mut mismatch_line_nos) = (String::new(), vec![]);
2676+
for hunk in diff_results {
2677+
let mut line_no = hunk.line_number;
2678+
for line in hunk.lines {
2679+
// NOTE: `Expected` is actually correct here, the argument order is reversed so our line numbers match up
2680+
if let DiffLine::Expected(normalized) = line {
2681+
mismatches_normalized += &normalized;
2682+
mismatches_normalized += "\n";
2683+
mismatch_line_nos.push(line_no);
2684+
line_no += 1;
2685+
}
2686+
}
2687+
}
2688+
let mut mismatches_unnormalized = String::new();
2689+
let diff_normalized = make_diff(actual, actual_unnormalized, 0);
2690+
for hunk in diff_normalized {
2691+
if mismatch_line_nos.contains(&hunk.line_number) {
2692+
for line in hunk.lines {
2693+
if let DiffLine::Resulting(unnormalized) = line {
2694+
mismatches_unnormalized += &unnormalized;
2695+
mismatches_unnormalized += "\n";
2696+
}
2697+
}
2698+
}
2699+
}
2700+
2701+
let normalized_diff = make_diff(&mismatches_normalized, &mismatches_unnormalized, 0);
2702+
if !normalized_diff.is_empty() {
2703+
println!("Note: some mismatched output was normalized before being compared");
2704+
// FIXME: respect diff_command
2705+
print!("{}", write_diff(&mismatches_unnormalized, &mismatches_normalized, 0));
2706+
}
2707+
}
2708+
26362709
fn check_and_prune_duplicate_outputs(
26372710
&self,
26382711
proc_res: &ProcRes,

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(

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)