From 699a1b82c225311ffba6c2b39053c95f1ae01af8 Mon Sep 17 00:00:00 2001 From: Tom Milligan Date: Mon, 31 Jan 2022 22:19:05 +0000 Subject: [PATCH] [suggest] general str types, complete doc/tests --- pretty_assertions/src/lib.rs | 73 ++++++++++++++++++++++++++----- pretty_assertions/tests/macros.rs | 24 ++++++++++ 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/pretty_assertions/src/lib.rs b/pretty_assertions/src/lib.rs index a4c0b91..5bf03c2 100644 --- a/pretty_assertions/src/lib.rs +++ b/pretty_assertions/src/lib.rs @@ -144,7 +144,7 @@ where /// A comparison of two strings. /// /// In contrast to [`Comparison`], which uses the [`core::fmt::Debug`] representaiton, -/// this will print newlines unescaped, resulting in multi-line output for multiline strings. +/// `StrComparison` uses the string values directly, resulting in multi-line output for multiline strings. /// /// ``` /// use pretty_assertions::StrComparison; @@ -152,29 +152,62 @@ where /// print!("{}", StrComparison::new("foo\nbar", "foo\nbaz")); /// ``` /// +/// ## Value type bounds +/// +/// Any value that can be referenced as a [`str`] via [`AsRef`] may be used: +/// +/// ``` +/// use pretty_assertions::StrComparison; +/// +/// #[derive(PartialEq)] +/// struct MyString(String); +/// +/// impl AsRef for MyString { +/// fn as_ref(&self) -> &str { +/// &self.0 +/// } +/// } +/// +/// print!( +/// "{}", +/// StrComparison::new( +/// &MyString("foo\nbar".to_owned()), +/// &MyString("foo\nbaz".to_owned()), +/// ), +/// ); +/// ``` +/// /// The values may have different types, although in practice they are usually the same. -pub struct StrComparison<'a> +pub struct StrComparison<'a, TLeft, TRight> +where + TLeft: ?Sized, + TRight: ?Sized, { - left: &'a str, - right: &'a str, + left: &'a TLeft, + right: &'a TRight, } -impl<'a> StrComparison<'a> +impl<'a, TLeft, TRight> StrComparison<'a, TLeft, TRight> +where + TLeft: ?Sized, + TRight: ?Sized, { /// Store two values to be compared in future. /// /// Expensive diffing is deferred until calling `Debug::fmt`. - pub fn new(left: &'a str, right: &'a str) -> StrComparison<'a> { - StrComparison { left: left, right: right } + pub fn new(left: &'a TLeft, right: &'a TRight) -> StrComparison<'a, TLeft, TRight> { + StrComparison { left, right } } } -impl<'a> Display for StrComparison<'a> +impl<'a, TLeft, TRight> Display for StrComparison<'a, TLeft, TRight> +where + TLeft: AsRef + ?Sized, + TRight: AsRef + ?Sized, { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - // And then diff the debug output printer::write_header(f)?; - printer::write_lines(f, self.left, self.right) + printer::write_lines(f, self.left.as_ref(), self.right.as_ref()) } } @@ -223,7 +256,25 @@ macro_rules! assert_eq { }); } -/// TODO +/// Asserts that two expressions are equal to each other (using [`PartialEq`]). +/// +/// On panic, this macro will print a diff derived from each value's [`str`] representation. +/// See [`StrComparison`] for further details. +/// +/// This is a drop in replacement for [`core::assert_eq!`]. +/// You can provide a custom panic message if desired. +/// +/// # Examples +/// +/// ``` +/// use pretty_assertions::assert_str_eq; +/// +/// let a = "foo\nbar"; +/// let b = ["foo", "bar"].join("\n"); +/// assert_str_eq!(a, b); +/// +/// assert_str_eq!(a, b, "we are testing concatenation with {} and {}", a, b); +/// ``` #[macro_export] macro_rules! assert_str_eq { ($left:expr, $right:expr$(,)?) => ({ diff --git a/pretty_assertions/tests/macros.rs b/pretty_assertions/tests/macros.rs index a2fdbf8..81e0331 100644 --- a/pretty_assertions/tests/macros.rs +++ b/pretty_assertions/tests/macros.rs @@ -6,6 +6,8 @@ extern crate alloc; #[allow(clippy::eq_op)] mod assert_str_eq { + use ::core::{cmp::PartialEq, convert::AsRef}; + #[cfg(feature = "alloc")] use ::alloc::string::{String, ToString}; #[cfg(feature = "std")] @@ -30,6 +32,28 @@ mod assert_str_eq { ::pretty_assertions::assert_str_eq!(s0, s1); } + #[test] + fn passes_as_ref_types() { + #[derive(PartialEq)] + struct MyString(String); + + impl AsRef for MyString { + fn as_ref(&self) -> &str { + &self.0 + } + } + + impl PartialEq for MyString { + fn eq(&self, other: &String) -> bool { + &self.0 == other + } + } + + let s0 = MyString("foo".to_string()); + let s1 = "foo".to_string(); + ::pretty_assertions::assert_str_eq!(s0, s1); + } + #[test] #[should_panic(expected = r#"assertion failed: `(left == right)`