Skip to content

Commit 1204fb1

Browse files
Rollup merge of rust-lang#155238 - Ozzy1423:diff-by-lines, r=jieyouxu
compiletest: add a new diff for compare-out-by-lines tests. Previously, when comparing output by lines, only the actual diff was shown. This is unhelpful since we expect lines to be shuffled around. With this new print, we can see the exact lines that are missing or have appeared without the noise of the moved around lines. Example, in this case a note has moved slightly so there is one more separator line "|": ``` + | + = help: maybe it is overwritten before being read? Compare output by lines enabled, diff by lines: Expected contains these lines that are not in actual: (no lines found) Actual contains these lines that are not in expected: | The actual stderr differed from the expected stderr To update references, rerun the tests and pass the `--bless` flag To only update this specific test, also pass `--test-args liveness/liveness-consts.rs` ``` r? @jieyouxu cc @zetanumbers @ywxt
2 parents 26f47ae + 459be3e commit 1204fb1

2 files changed

Lines changed: 58 additions & 1 deletion

File tree

src/tools/compiletest/src/runtest.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::directives::{AuxCrate, TestProps};
2222
use crate::errors::{Error, ErrorKind, load_errors};
2323
use crate::output_capture::ConsoleOut;
2424
use crate::read2::{Truncated, read2_abbreviated};
25-
use crate::runtest::compute_diff::{DiffLine, make_diff, write_diff};
25+
use crate::runtest::compute_diff::{DiffLine, diff_by_lines, make_diff, write_diff};
2626
use crate::util::{Utf8PathBufExt, add_dylib_path, static_regex};
2727
use crate::{json, stamp_file_path};
2828

@@ -2779,6 +2779,7 @@ impl<'test> TestCx<'test> {
27792779
expected,
27802780
actual,
27812781
actual_unnormalized,
2782+
compare_output_by_lines || compare_output_by_lines_subset,
27822783
);
27832784
}
27842785
} else {
@@ -2816,6 +2817,7 @@ impl<'test> TestCx<'test> {
28162817
expected: &str,
28172818
actual: &str,
28182819
actual_unnormalized: &str,
2820+
show_diff_by_lines: bool,
28192821
) {
28202822
writeln!(self.stderr, "diff of {stream}:\n");
28212823
if let Some(diff_command) = self.config.diff_command.as_deref() {
@@ -2882,6 +2884,10 @@ impl<'test> TestCx<'test> {
28822884
write_diff(&mismatches_unnormalized, &mismatches_normalized, 0)
28832885
);
28842886
}
2887+
2888+
if show_diff_by_lines {
2889+
write!(self.stderr, "{}", diff_by_lines(expected, actual));
2890+
}
28852891
}
28862892

28872893
fn check_and_prune_duplicate_outputs(

src/tools/compiletest/src/runtest/compute_diff.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,54 @@ pub(crate) fn write_diff(expected: &str, actual: &str, context_size: usize) -> S
104104
}
105105
output
106106
}
107+
108+
pub(crate) fn diff_by_lines(expected: &str, actual: &str) -> String {
109+
use std::collections::HashMap;
110+
use std::fmt::Write;
111+
let mut output = String::new();
112+
let mut expected_counts: HashMap<&str, usize> = HashMap::new();
113+
let mut actual_counts: HashMap<&str, usize> = HashMap::new();
114+
115+
for line in expected.lines() {
116+
*expected_counts.entry(line).or_insert(0) += 1;
117+
}
118+
for line in actual.lines() {
119+
*actual_counts.entry(line).or_insert(0) += 1;
120+
}
121+
122+
fn write_expected_only_lines(
123+
output: &mut String,
124+
expected_lines: &HashMap<&str, usize>,
125+
actual_lines: &HashMap<&str, usize>,
126+
) {
127+
let mut expected_only: Vec<(&str, usize)> = expected_lines
128+
.iter()
129+
.filter_map(|(&line, &expected_count)| {
130+
let actual_count = actual_lines.get(line).copied().unwrap_or(0);
131+
if expected_count > actual_count {
132+
Some((line, expected_count - actual_count))
133+
} else {
134+
None
135+
}
136+
})
137+
.collect();
138+
expected_only.sort_by(|(a, _), (b, _)| a.cmp(b));
139+
140+
if expected_only.is_empty() {
141+
writeln!(output, "(no lines found)").unwrap();
142+
} else {
143+
for (line, diff) in expected_only {
144+
for _ in 0..diff {
145+
writeln!(output, "{line}").unwrap();
146+
}
147+
}
148+
}
149+
}
150+
151+
writeln!(output, "Compare output by lines enabled, diff by lines:").unwrap();
152+
writeln!(output, "Expected contains these lines that are not in actual:").unwrap();
153+
write_expected_only_lines(&mut output, &expected_counts, &actual_counts);
154+
writeln!(output, "Actual contains these lines that are not in expected:").unwrap();
155+
write_expected_only_lines(&mut output, &actual_counts, &expected_counts);
156+
output
157+
}

0 commit comments

Comments
 (0)