Skip to content

Commit a30171c

Browse files
committed
Add compare-output-lines-by-subset flag to compiletest
1 parent 5546cb6 commit a30171c

File tree

2 files changed

+68
-8
lines changed

2 files changed

+68
-8
lines changed

src/tools/compiletest/src/header.rs

+10
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ pub struct TestProps {
102102
pub dont_check_compiler_stdout: bool,
103103
// For UI tests, allows compiler to generate arbitrary output to stderr
104104
pub dont_check_compiler_stderr: bool,
105+
// When checking the output of stdout or stderr check
106+
// that the lines of expected output are a subset of the actual output.
107+
pub compare_output_lines_by_subset: bool,
105108
// Don't force a --crate-type=dylib flag on the command line
106109
//
107110
// Set this for example if you have an auxiliary test file that contains
@@ -209,6 +212,7 @@ mod directives {
209212
pub const KNOWN_BUG: &'static str = "known-bug";
210213
pub const MIR_UNIT_TEST: &'static str = "unit-test";
211214
pub const REMAP_SRC_BASE: &'static str = "remap-src-base";
215+
pub const COMPARE_OUTPUT_LINES_BY_SUBSET: &'static str = "compare-output-lines-by-subset";
212216
// This isn't a real directive, just one that is probably mistyped often
213217
pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags";
214218
}
@@ -233,6 +237,7 @@ impl TestProps {
233237
check_run_results: false,
234238
dont_check_compiler_stdout: false,
235239
dont_check_compiler_stderr: false,
240+
compare_output_lines_by_subset: false,
236241
no_prefer_dynamic: false,
237242
pretty_expanded: false,
238243
pretty_mode: "normal".to_string(),
@@ -467,6 +472,11 @@ impl TestProps {
467472
s.trim().to_string()
468473
});
469474
config.set_name_directive(ln, REMAP_SRC_BASE, &mut self.remap_src_base);
475+
config.set_name_directive(
476+
ln,
477+
COMPARE_OUTPUT_LINES_BY_SUBSET,
478+
&mut self.compare_output_lines_by_subset,
479+
);
470480
});
471481
}
472482

src/tools/compiletest/src/runtest.rs

+58-8
Original file line numberDiff line numberDiff line change
@@ -3238,17 +3238,35 @@ impl<'test> TestCx<'test> {
32383238
match output_kind {
32393239
TestOutput::Compile => {
32403240
if !self.props.dont_check_compiler_stdout {
3241-
errors +=
3242-
self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
3241+
errors += self.compare_output(
3242+
stdout_kind,
3243+
&normalized_stdout,
3244+
&expected_stdout,
3245+
self.props.compare_output_lines_by_subset,
3246+
);
32433247
}
32443248
if !self.props.dont_check_compiler_stderr {
3245-
errors +=
3246-
self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
3249+
errors += self.compare_output(
3250+
stderr_kind,
3251+
&normalized_stderr,
3252+
&expected_stderr,
3253+
self.props.compare_output_lines_by_subset,
3254+
);
32473255
}
32483256
}
32493257
TestOutput::Run => {
3250-
errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
3251-
errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
3258+
errors += self.compare_output(
3259+
stdout_kind,
3260+
&normalized_stdout,
3261+
&expected_stdout,
3262+
self.props.compare_output_lines_by_subset,
3263+
);
3264+
errors += self.compare_output(
3265+
stderr_kind,
3266+
&normalized_stderr,
3267+
&expected_stderr,
3268+
self.props.compare_output_lines_by_subset,
3269+
);
32523270
}
32533271
}
32543272
errors
@@ -3332,7 +3350,12 @@ impl<'test> TestCx<'test> {
33323350
)
33333351
});
33343352

3335-
errors += self.compare_output("fixed", &fixed_code, &expected_fixed);
3353+
errors += self.compare_output(
3354+
"fixed",
3355+
&fixed_code,
3356+
&expected_fixed,
3357+
self.props.compare_output_lines_by_subset,
3358+
);
33363359
} else if !expected_fixed.is_empty() {
33373360
panic!(
33383361
"the `// run-rustfix` directive wasn't found but a `*.fixed` \
@@ -3790,11 +3813,38 @@ impl<'test> TestCx<'test> {
37903813
}
37913814
}
37923815

3793-
fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize {
3816+
fn compare_output(
3817+
&self,
3818+
kind: &str,
3819+
actual: &str,
3820+
expected: &str,
3821+
compare_output_by_lines: bool,
3822+
) -> usize {
37943823
if actual == expected {
37953824
return 0;
37963825
}
37973826

3827+
let tmp;
3828+
let (expected, actual): (&str, &str) = if compare_output_by_lines {
3829+
let actual_lines: HashSet<_> = actual.lines().collect();
3830+
let expected_lines: Vec<_> = expected.lines().collect();
3831+
let mut used = expected_lines.clone();
3832+
used.retain(|line| actual_lines.contains(line));
3833+
// check if `expected` contains a subset of the lines of `actual`
3834+
if used.len() == expected_lines.len() && (expected.is_empty() == actual.is_empty()) {
3835+
return 0;
3836+
}
3837+
if expected_lines.is_empty() {
3838+
// if we have no lines to check, force a full overwite
3839+
("", actual)
3840+
} else {
3841+
tmp = (expected_lines.join("\n"), used.join("\n"));
3842+
(&tmp.0, &tmp.1)
3843+
}
3844+
} else {
3845+
(expected, actual)
3846+
};
3847+
37983848
if !self.config.bless {
37993849
if expected.is_empty() {
38003850
println!("normalized {}:\n{}\n", kind, actual);

0 commit comments

Comments
 (0)