/rust/registry/src/index.crates.io-1949cf8c6b5b557f/pretty_assertions-1.4.1/src/lib.rs
Line | Count | Source |
1 | | //! # Pretty Assertions |
2 | | //! |
3 | | //! When writing tests in Rust, you'll probably use `assert_eq!(a, b)` _a lot_. |
4 | | //! |
5 | | //! If such a test fails, it will present all the details of `a` and `b`. |
6 | | //! But you have to spot the differences yourself, which is not always straightforward, |
7 | | //! like here: |
8 | | //! |
9 | | //!  |
10 | | //! |
11 | | //! Wouldn't that task be _much_ easier with a colorful diff? |
12 | | //! |
13 | | //!  |
14 | | //! |
15 | | //! Yep — and you only need **one line of code** to make it happen: |
16 | | //! |
17 | | //! ```rust |
18 | | //! use pretty_assertions::{assert_eq, assert_ne}; |
19 | | //! ``` |
20 | | //! |
21 | | //! <details> |
22 | | //! <summary>Show the example behind the screenshots above.</summary> |
23 | | //! |
24 | | //! ```rust,should_panic |
25 | | //! // 1. add the `pretty_assertions` dependency to `Cargo.toml`. |
26 | | //! // 2. insert this line at the top of each module, as needed |
27 | | //! use pretty_assertions::{assert_eq, assert_ne}; |
28 | | //! |
29 | | //! #[derive(Debug, PartialEq)] |
30 | | //! struct Foo { |
31 | | //! lorem: &'static str, |
32 | | //! ipsum: u32, |
33 | | //! dolor: Result<String, String>, |
34 | | //! } |
35 | | //! |
36 | | //! let x = Some(Foo { lorem: "Hello World!", ipsum: 42, dolor: Ok("hey".to_string())}); |
37 | | //! let y = Some(Foo { lorem: "Hello Wrold!", ipsum: 42, dolor: Ok("hey ho!".to_string())}); |
38 | | //! |
39 | | //! assert_eq!(x, y); |
40 | | //! ``` |
41 | | //! </details> |
42 | | //! |
43 | | //! ## Tip |
44 | | //! |
45 | | //! Specify it as [`[dev-dependencies]`](http://doc.crates.io/specifying-dependencies.html#development-dependencies) |
46 | | //! and it will only be used for compiling tests, examples, and benchmarks. |
47 | | //! This way the compile time of `cargo build` won't be affected! |
48 | | //! |
49 | | //! Also add `#[cfg(test)]` to your `use` statements, like this: |
50 | | //! |
51 | | //! ```rust |
52 | | //! #[cfg(test)] |
53 | | //! use pretty_assertions::{assert_eq, assert_ne}; |
54 | | //! ``` |
55 | | //! |
56 | | //! ## Note |
57 | | //! |
58 | | //! * Since `Rust 2018` edition, you need to declare |
59 | | //! `use pretty_assertions::{assert_eq, assert_ne};` per module. |
60 | | //! Before you would write `#[macro_use] extern crate pretty_assertions;`. |
61 | | //! * The replacement is only effective in your own crate, not in other libraries |
62 | | //! you include. |
63 | | //! * `assert_ne` is also switched to multi-line presentation, but does _not_ show |
64 | | //! a diff. |
65 | | //! |
66 | | //! ## Features |
67 | | //! |
68 | | //! Features provided by the crate are: |
69 | | //! |
70 | | //! - `std`: Use the Rust standard library. Enabled by default. |
71 | | //! Exactly one of `std` and `alloc` is required. |
72 | | //! - `alloc`: Use the `alloc` crate. |
73 | | //! Exactly one of `std` and `alloc` is required. |
74 | | //! - `unstable`: opt-in to unstable features that may not follow Semantic Versioning. |
75 | | //! The implementation behind this feature is subject to change without warning between patch versions. |
76 | | |
77 | | #![cfg_attr(not(feature = "std"), no_std)] |
78 | | #![deny(clippy::all, missing_docs, unsafe_code)] |
79 | | |
80 | | #[cfg(feature = "alloc")] |
81 | | #[macro_use] |
82 | | extern crate alloc; |
83 | | use core::fmt::{self, Debug, Display}; |
84 | | |
85 | | mod printer; |
86 | | |
87 | | /// A comparison of two values. |
88 | | /// |
89 | | /// Where both values implement `Debug`, the comparison can be displayed as a pretty diff. |
90 | | /// |
91 | | /// ``` |
92 | | /// use pretty_assertions::Comparison; |
93 | | /// |
94 | | /// print!("{}", Comparison::new(&123, &134)); |
95 | | /// ``` |
96 | | /// |
97 | | /// The values may have different types, although in practice they are usually the same. |
98 | | pub struct Comparison<'a, TLeft, TRight> |
99 | | where |
100 | | TLeft: ?Sized, |
101 | | TRight: ?Sized, |
102 | | { |
103 | | left: &'a TLeft, |
104 | | right: &'a TRight, |
105 | | } |
106 | | |
107 | | impl<'a, TLeft, TRight> Comparison<'a, TLeft, TRight> |
108 | | where |
109 | | TLeft: ?Sized, |
110 | | TRight: ?Sized, |
111 | | { |
112 | | /// Store two values to be compared in future. |
113 | | /// |
114 | | /// Expensive diffing is deferred until calling `Debug::fmt`. |
115 | 0 | pub fn new(left: &'a TLeft, right: &'a TRight) -> Comparison<'a, TLeft, TRight> { |
116 | 0 | Comparison { left, right } |
117 | 0 | } Unexecuted instantiation: <pretty_assertions::Comparison<&alloc::vec::Vec<pulldown_cmark::Event>, &alloc::vec::Vec<pulldown_cmark::Event>>>::new Unexecuted instantiation: <pretty_assertions::Comparison<_, _>>::new |
118 | | } |
119 | | |
120 | | impl<'a, TLeft, TRight> Display for Comparison<'a, TLeft, TRight> |
121 | | where |
122 | | TLeft: Debug + ?Sized, |
123 | | TRight: Debug + ?Sized, |
124 | | { |
125 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
126 | | // To diff arbitary types, render them as debug strings |
127 | 0 | let left_debug = format!("{:#?}", self.left); |
128 | 0 | let right_debug = format!("{:#?}", self.right); |
129 | | // And then diff the debug output |
130 | 0 | printer::write_header(f)?; |
131 | 0 | printer::write_lines(f, &left_debug, &right_debug) |
132 | 0 | } Unexecuted instantiation: <pretty_assertions::Comparison<&alloc::vec::Vec<pulldown_cmark::Event>, &alloc::vec::Vec<pulldown_cmark::Event>> as core::fmt::Display>::fmt Unexecuted instantiation: <pretty_assertions::Comparison<_, _> as core::fmt::Display>::fmt |
133 | | } |
134 | | |
135 | | /// A comparison of two strings. |
136 | | /// |
137 | | /// In contrast to [`Comparison`], which uses the [`core::fmt::Debug`] representation, |
138 | | /// `StrComparison` uses the string values directly, resulting in multi-line output for multiline strings. |
139 | | /// |
140 | | /// ``` |
141 | | /// use pretty_assertions::StrComparison; |
142 | | /// |
143 | | /// print!("{}", StrComparison::new("foo\nbar", "foo\nbaz")); |
144 | | /// ``` |
145 | | /// |
146 | | /// ## Value type bounds |
147 | | /// |
148 | | /// Any value that can be referenced as a [`str`] via [`AsRef`] may be used: |
149 | | /// |
150 | | /// ``` |
151 | | /// use pretty_assertions::StrComparison; |
152 | | /// |
153 | | /// #[derive(PartialEq)] |
154 | | /// struct MyString(String); |
155 | | /// |
156 | | /// impl AsRef<str> for MyString { |
157 | | /// fn as_ref(&self) -> &str { |
158 | | /// &self.0 |
159 | | /// } |
160 | | /// } |
161 | | /// |
162 | | /// print!( |
163 | | /// "{}", |
164 | | /// StrComparison::new( |
165 | | /// &MyString("foo\nbar".to_owned()), |
166 | | /// &MyString("foo\nbaz".to_owned()), |
167 | | /// ), |
168 | | /// ); |
169 | | /// ``` |
170 | | /// |
171 | | /// The values may have different types, although in practice they are usually the same. |
172 | | pub struct StrComparison<'a, TLeft, TRight> |
173 | | where |
174 | | TLeft: ?Sized, |
175 | | TRight: ?Sized, |
176 | | { |
177 | | left: &'a TLeft, |
178 | | right: &'a TRight, |
179 | | } |
180 | | |
181 | | impl<'a, TLeft, TRight> StrComparison<'a, TLeft, TRight> |
182 | | where |
183 | | TLeft: AsRef<str> + ?Sized, |
184 | | TRight: AsRef<str> + ?Sized, |
185 | | { |
186 | | /// Store two values to be compared in future. |
187 | | /// |
188 | | /// Expensive diffing is deferred until calling `Debug::fmt`. |
189 | 0 | pub fn new(left: &'a TLeft, right: &'a TRight) -> StrComparison<'a, TLeft, TRight> { |
190 | 0 | StrComparison { left, right } |
191 | 0 | } |
192 | | } |
193 | | |
194 | | impl<'a, TLeft, TRight> Display for StrComparison<'a, TLeft, TRight> |
195 | | where |
196 | | TLeft: AsRef<str> + ?Sized, |
197 | | TRight: AsRef<str> + ?Sized, |
198 | | { |
199 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
200 | 0 | printer::write_header(f)?; |
201 | 0 | printer::write_lines(f, self.left.as_ref(), self.right.as_ref()) |
202 | 0 | } |
203 | | } |
204 | | |
205 | | /// Asserts that two expressions are equal to each other (using [`PartialEq`]). |
206 | | /// |
207 | | /// On panic, this macro will print a diff derived from [`Debug`] representation of |
208 | | /// each value. |
209 | | /// |
210 | | /// This is a drop in replacement for [`core::assert_eq!`]. |
211 | | /// You can provide a custom panic message if desired. |
212 | | /// |
213 | | /// # Examples |
214 | | /// |
215 | | /// ``` |
216 | | /// use pretty_assertions::assert_eq; |
217 | | /// |
218 | | /// let a = 3; |
219 | | /// let b = 1 + 2; |
220 | | /// assert_eq!(a, b); |
221 | | /// |
222 | | /// assert_eq!(a, b, "we are testing addition with {} and {}", a, b); |
223 | | /// ``` |
224 | | #[macro_export] |
225 | | macro_rules! assert_eq { |
226 | | ($left:expr, $right:expr$(,)?) => ({ |
227 | | $crate::assert_eq!(@ $left, $right, "", ""); |
228 | | }); |
229 | | ($left:expr, $right:expr, $($arg:tt)*) => ({ |
230 | | $crate::assert_eq!(@ $left, $right, ": ", $($arg)+); |
231 | | }); |
232 | | (@ $left:expr, $right:expr, $maybe_colon:expr, $($arg:tt)*) => ({ |
233 | | match (&($left), &($right)) { |
234 | | (left_val, right_val) => { |
235 | | if !(*left_val == *right_val) { |
236 | | use $crate::private::CreateComparison; |
237 | | ::core::panic!("assertion failed: `(left == right)`{}{}\ |
238 | | \n\ |
239 | | \n{}\ |
240 | | \n", |
241 | | $maybe_colon, |
242 | | format_args!($($arg)*), |
243 | | (left_val, right_val).create_comparison() |
244 | | ) |
245 | | } |
246 | | } |
247 | | } |
248 | | }); |
249 | | } |
250 | | |
251 | | /// Asserts that two expressions are equal to each other (using [`PartialEq`]). |
252 | | /// |
253 | | /// On panic, this macro will print a diff derived from each value's [`str`] representation. |
254 | | /// See [`StrComparison`] for further details. |
255 | | /// |
256 | | /// This is a drop in replacement for [`core::assert_eq!`]. |
257 | | /// You can provide a custom panic message if desired. |
258 | | /// |
259 | | /// # Examples |
260 | | /// |
261 | | /// ``` |
262 | | /// use pretty_assertions::assert_str_eq; |
263 | | /// |
264 | | /// let a = "foo\nbar"; |
265 | | /// let b = ["foo", "bar"].join("\n"); |
266 | | /// assert_str_eq!(a, b); |
267 | | /// |
268 | | /// assert_str_eq!(a, b, "we are testing concatenation with {} and {}", a, b); |
269 | | /// ``` |
270 | | #[macro_export] |
271 | | macro_rules! assert_str_eq { |
272 | | ($left:expr, $right:expr$(,)?) => ({ |
273 | | $crate::assert_str_eq!(@ $left, $right, "", ""); |
274 | | }); |
275 | | ($left:expr, $right:expr, $($arg:tt)*) => ({ |
276 | | $crate::assert_str_eq!(@ $left, $right, ": ", $($arg)+); |
277 | | }); |
278 | | (@ $left:expr, $right:expr, $maybe_colon:expr, $($arg:tt)*) => ({ |
279 | | match (&($left), &($right)) { |
280 | | (left_val, right_val) => { |
281 | | if !(*left_val == *right_val) { |
282 | | ::core::panic!("assertion failed: `(left == right)`{}{}\ |
283 | | \n\ |
284 | | \n{}\ |
285 | | \n", |
286 | | $maybe_colon, |
287 | | format_args!($($arg)*), |
288 | | $crate::StrComparison::new(left_val, right_val) |
289 | | ) |
290 | | } |
291 | | } |
292 | | } |
293 | | }); |
294 | | } |
295 | | |
296 | | /// Asserts that two expressions are not equal to each other (using [`PartialEq`]). |
297 | | /// |
298 | | /// On panic, this macro will print the values of the expressions with their |
299 | | /// [`Debug`] representations. |
300 | | /// |
301 | | /// This is a drop in replacement for [`core::assert_ne!`]. |
302 | | /// You can provide a custom panic message if desired. |
303 | | /// |
304 | | /// # Examples |
305 | | /// |
306 | | /// ``` |
307 | | /// use pretty_assertions::assert_ne; |
308 | | /// |
309 | | /// let a = 3; |
310 | | /// let b = 2; |
311 | | /// assert_ne!(a, b); |
312 | | /// |
313 | | /// assert_ne!(a, b, "we are testing that the values are not equal"); |
314 | | /// ``` |
315 | | #[macro_export] |
316 | | macro_rules! assert_ne { |
317 | | ($left:expr, $right:expr$(,)?) => ({ |
318 | | $crate::assert_ne!(@ $left, $right, "", ""); |
319 | | }); |
320 | | ($left:expr, $right:expr, $($arg:tt)+) => ({ |
321 | | $crate::assert_ne!(@ $left, $right, ": ", $($arg)+); |
322 | | }); |
323 | | (@ $left:expr, $right:expr, $maybe_colon:expr, $($arg:tt)+) => ({ |
324 | | match (&($left), &($right)) { |
325 | | (left_val, right_val) => { |
326 | | if *left_val == *right_val { |
327 | | ::core::panic!("assertion failed: `(left != right)`{}{}\ |
328 | | \n\ |
329 | | \nBoth sides:\ |
330 | | \n{:#?}\ |
331 | | \n\ |
332 | | \n", |
333 | | $maybe_colon, |
334 | | format_args!($($arg)+), |
335 | | left_val |
336 | | ) |
337 | | } |
338 | | } |
339 | | } |
340 | | }); |
341 | | } |
342 | | |
343 | | /// Asserts that a value matches a pattern. |
344 | | /// |
345 | | /// On panic, this macro will print a diff derived from [`Debug`] representation of |
346 | | /// the value, and a string representation of the pattern. |
347 | | /// |
348 | | /// This is a drop in replacement for [`core::assert_matches::assert_matches!`]. |
349 | | /// You can provide a custom panic message if desired. |
350 | | /// |
351 | | /// # Examples |
352 | | /// |
353 | | /// ``` |
354 | | /// use pretty_assertions::assert_matches; |
355 | | /// |
356 | | /// let a = Some(3); |
357 | | /// assert_matches!(a, Some(_)); |
358 | | /// |
359 | | /// assert_matches!(a, Some(value) if value > 2, "we are testing {:?} with a pattern", a); |
360 | | /// ``` |
361 | | /// |
362 | | /// # Features |
363 | | /// |
364 | | /// Requires the `unstable` feature to be enabled. |
365 | | /// |
366 | | /// **Please note:** implementation under the `unstable` feature may be changed between |
367 | | /// patch versions without warning. |
368 | | #[cfg(feature = "unstable")] |
369 | | #[macro_export] |
370 | | macro_rules! assert_matches { |
371 | | ($left:expr, $( $pattern:pat )|+ $( if $guard: expr )? $(,)?) => ({ |
372 | | match $left { |
373 | | $( $pattern )|+ $( if $guard )? => {} |
374 | | ref left_val => { |
375 | | $crate::assert_matches!( |
376 | | @ |
377 | | left_val, |
378 | | ::core::stringify!($($pattern)|+ $(if $guard)?), |
379 | | "", |
380 | | "" |
381 | | ); |
382 | | } |
383 | | } |
384 | | }); |
385 | | ($left:expr, $( $pattern:pat )|+ $( if $guard: expr )?, $($arg:tt)+) => ({ |
386 | | match $left { |
387 | | $( $pattern )|+ $( if $guard )? => {} |
388 | | ref left_val => { |
389 | | $crate::assert_matches!( |
390 | | @ |
391 | | left_val, |
392 | | ::core::stringify!($($pattern)|+ $(if $guard)?), |
393 | | ": ", |
394 | | $($arg)+ |
395 | | ); |
396 | | } |
397 | | } |
398 | | |
399 | | }); |
400 | | (@ $left:expr, $right:expr, $maybe_colon:expr, $($arg:tt)*) => ({ |
401 | | match (&($left), &($right)) { |
402 | | (left_val, right_val) => { |
403 | | // Use the Display implementation to display the pattern, |
404 | | // as using Debug would add another layer of quotes to the output. |
405 | | struct Pattern<'a>(&'a str); |
406 | | impl ::core::fmt::Debug for Pattern<'_> { |
407 | | fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { |
408 | | ::core::fmt::Display::fmt(self.0, f) |
409 | | } |
410 | | } |
411 | | |
412 | | ::core::panic!("assertion failed: `(left matches right)`{}{}\ |
413 | | \n\ |
414 | | \n{}\ |
415 | | \n", |
416 | | $maybe_colon, |
417 | | format_args!($($arg)*), |
418 | | $crate::Comparison::new(left_val, &Pattern(right_val)) |
419 | | ) |
420 | | } |
421 | | } |
422 | | }); |
423 | | } |
424 | | |
425 | | // Not public API. Used by the expansion of this crate's assert macros. |
426 | | #[doc(hidden)] |
427 | | pub mod private { |
428 | | #[cfg(feature = "alloc")] |
429 | | use alloc::string::String; |
430 | | |
431 | | pub trait CompareAsStrByDefault: AsRef<str> {} |
432 | | impl CompareAsStrByDefault for str {} |
433 | | impl CompareAsStrByDefault for String {} |
434 | | impl<T: CompareAsStrByDefault + ?Sized> CompareAsStrByDefault for &T {} |
435 | | |
436 | | pub trait CreateComparison { |
437 | | type Comparison; |
438 | | fn create_comparison(self) -> Self::Comparison; |
439 | | } |
440 | | |
441 | | impl<'a, T, U> CreateComparison for &'a (T, U) { |
442 | | type Comparison = crate::Comparison<'a, T, U>; |
443 | 0 | fn create_comparison(self) -> Self::Comparison { |
444 | 0 | crate::Comparison::new(&self.0, &self.1) |
445 | 0 | } Unexecuted instantiation: <&(&alloc::vec::Vec<pulldown_cmark::Event>, &alloc::vec::Vec<pulldown_cmark::Event>) as pretty_assertions::private::CreateComparison>::create_comparison Unexecuted instantiation: <&(_, _) as pretty_assertions::private::CreateComparison>::create_comparison |
446 | | } |
447 | | |
448 | | impl<'a, T, U> CreateComparison for (&'a T, &'a U) |
449 | | where |
450 | | T: CompareAsStrByDefault + ?Sized, |
451 | | U: CompareAsStrByDefault + ?Sized, |
452 | | { |
453 | | type Comparison = crate::StrComparison<'a, T, U>; |
454 | 0 | fn create_comparison(self) -> Self::Comparison { |
455 | 0 | crate::StrComparison::new(self.0, self.1) |
456 | 0 | } |
457 | | } |
458 | | } |