Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions src/tools/run-make-support/src/diff/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use regex::Regex;
use similar::TextDiff;
use std::path::Path;

Expand All @@ -14,12 +15,19 @@ pub struct Diff {
expected_name: Option<String>,
actual: Option<String>,
actual_name: Option<String>,
normalizers: Vec<(String, String)>,
}

impl Diff {
/// Construct a bare `diff` invocation.
pub fn new() -> Self {
Self { expected: None, expected_name: None, actual: None, actual_name: None }
Self {
expected: None,
expected_name: None,
actual: None,
actual_name: None,
normalizers: Vec::new(),
}
}

/// Specify the expected output for the diff from a file.
Expand Down Expand Up @@ -58,15 +66,29 @@ impl Diff {
self
}

/// Specify a regex that should replace text in the "actual" text that will be compared.
pub fn normalize<R: Into<String>, I: Into<String>>(
&mut self,
regex: R,
replacement: I,
) -> &mut Self {
self.normalizers.push((regex.into(), replacement.into()));
self
}

/// Executes the diff process, prints any differences to the standard error.
#[track_caller]
pub fn run(&self) {
let expected = self.expected.as_ref().expect("expected text not set");
let actual = self.actual.as_ref().expect("actual text not set");
let mut actual = self.actual.as_ref().expect("actual text not set").to_string();
let expected_name = self.expected_name.as_ref().unwrap();
let actual_name = self.actual_name.as_ref().unwrap();
for (regex, replacement) in &self.normalizers {
let re = Regex::new(regex).expect("bad regex in custom normalization rule");
actual = re.replace_all(&actual, replacement).into_owned();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we assert that we actually replace something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you prefer.

}

let output = TextDiff::from_lines(expected, actual)
let output = TextDiff::from_lines(expected, &actual)
.unified_diff()
.header(expected_name, actual_name)
.to_string();
Expand Down
22 changes: 22 additions & 0 deletions src/tools/run-make-support/src/diff/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,26 @@ test failed: `EXPECTED_TEXT` is different from `ACTUAL_TEXT`

assert_eq!(output.downcast_ref::<String>().unwrap(), expected_output);
}

#[test]
fn test_normalize() {
let expected = "
running 2 tests
..
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
";
let actual = "
running 2 tests
..
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
";

diff()
.expected_text("EXPECTED_TEXT", expected)
.actual_text("ACTUAL_TEXT", actual)
.normalize(r#"finished in \d+\.\d+s"#, "finished in $$TIME")
.run();
}
}