Skip to content

Commit d7ddb47

Browse files
hovinenbcopybara-github
authored andcommitted
Modify the summary diff of EqMatcher::explain_match in the case that the debug output resembles that of a string.
Previously, multiline strings would not benefit from the diff output feature of `EqMatcher::explain_match` because they would only ever be a single line. This uses a heuristic to detect whether the expected and actual debug outputs are likely those of multiline strings. This is the case when they are surrounded by quotes, do not contain newlines, and do contain escaped newlines. In that case, `EqMatcher::explain_match` will simulate the `Display` output of the strings and output a diff of those instead of the debug output. Such uses of `eq` will now benefit from this feature. This does not change `eq_deref_of` analogously, since it doesn't make any sense to use `eq_deref_of` on string types. PiperOrigin-RevId: 533481089
1 parent dda1212 commit d7ddb47

File tree

1 file changed

+93
-6
lines changed

1 file changed

+93
-6
lines changed

googletest/src/matchers/eq_matcher.rs

Lines changed: 93 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,27 @@ impl<A: Debug + ?Sized, T: PartialEq<A> + Debug> Matcher for EqMatcher<A, T> {
9595
}
9696

9797
fn explain_match(&self, actual: &A) -> String {
98-
format!(
99-
"which {}{}",
100-
&self.describe(self.matches(actual)),
98+
let expected_debug = format!("{:#?}", self.expected);
99+
let actual_debug = format!("{:#?}", actual);
100+
let description = self.describe(self.matches(actual));
101+
102+
let diff = if is_multiline_string_debug(&actual_debug)
103+
&& is_multiline_string_debug(&expected_debug)
104+
{
101105
create_diff(
102-
&format!("{:#?}", self.expected),
103-
&format!("{:#?}", actual),
106+
// The two calls below return None if and only if the strings expected_debug
107+
// respectively actual_debug are not enclosed in ". The calls to
108+
// is_multiline_string_debug above ensure that they are. So the calls cannot
109+
// actually return None and unwrap() should not panic.
110+
&to_display_output(&expected_debug).unwrap(),
111+
&to_display_output(&actual_debug).unwrap(),
104112
edit_distance::Mode::FullMatch,
105113
)
106-
)
114+
} else {
115+
create_diff(&expected_debug, &actual_debug, edit_distance::Mode::FullMatch)
116+
};
117+
118+
format!("which {description}{diff}")
107119
}
108120
}
109121

@@ -155,6 +167,17 @@ fn edit_list_summary(edit_list: &[edit_distance::Edit<&str>]) -> String {
155167
summary
156168
}
157169

170+
fn is_multiline_string_debug(string: &str) -> bool {
171+
string.starts_with('"')
172+
&& string.ends_with('"')
173+
&& !string.contains('\n')
174+
&& string.contains("\\n")
175+
}
176+
177+
fn to_display_output(string: &str) -> Option<String> {
178+
Some(string.strip_prefix('"')?.strip_suffix('"')?.split("\\n").collect::<Vec<_>>().join("\n"))
179+
}
180+
158181
#[cfg(test)]
159182
mod tests {
160183
use super::eq;
@@ -273,4 +296,68 @@ mod tests {
273296
"#})))
274297
)
275298
}
299+
300+
#[test]
301+
fn match_explanation_contains_diff_of_strings_if_more_than_one_line() -> Result<()> {
302+
let result = verify_that!(
303+
indoc!(
304+
"
305+
First line
306+
Second line
307+
Third line
308+
"
309+
),
310+
eq(indoc!(
311+
"
312+
First line
313+
Second lines
314+
Third line
315+
"
316+
))
317+
);
318+
319+
verify_that!(
320+
result,
321+
err(displays_as(contains_substring(indoc!(
322+
r#"
323+
First line
324+
+Second line
325+
-Second lines
326+
Third line
327+
"#
328+
))))
329+
)
330+
}
331+
332+
#[test]
333+
fn match_explanation_does_not_show_diff_if_actual_value_is_single_line() -> Result<()> {
334+
let result = verify_that!(
335+
"First line",
336+
eq(indoc!(
337+
"
338+
First line
339+
Second line
340+
Third line
341+
"
342+
))
343+
);
344+
345+
verify_that!(result, err(displays_as(not(contains_substring("Difference:")))))
346+
}
347+
348+
#[test]
349+
fn match_explanation_does_not_show_diff_if_expected_value_is_single_line() -> Result<()> {
350+
let result = verify_that!(
351+
indoc!(
352+
"
353+
First line
354+
Second line
355+
Third line
356+
"
357+
),
358+
eq("First line")
359+
);
360+
361+
verify_that!(result, err(displays_as(not(contains_substring("Difference:")))))
362+
}
276363
}

0 commit comments

Comments
 (0)