]> git.proxmox.com Git - rustc.git/blob - vendor/pretty_assertions/src/lib.rs
New upstream version 1.60.0+dfsg1
[rustc.git] / vendor / pretty_assertions / src / lib.rs
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 //! ![standard assertion](https://raw.githubusercontent.com/colin-kiegel/rust-pretty-assertions/2d2357ff56d22c51a86b2f1cfe6efcee9f5a8081/examples/standard_assertion.png)
10 //!
11 //! Wouldn't that task be _much_ easier with a colorful diff?
12 //!
13 //! ![pretty assertion](https://raw.githubusercontent.com/colin-kiegel/rust-pretty-assertions/2d2357ff56d22c51a86b2f1cfe6efcee9f5a8081/examples/pretty_assertion.png)
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 #![deny(clippy::all, missing_docs, unsafe_code)]
67
68 pub use ansi_term::Style;
69 use std::fmt::{self, Debug, Display};
70
71 mod printer;
72
73 #[cfg(windows)]
74 use ctor::*;
75 #[cfg(windows)]
76 #[ctor]
77 fn init() {
78 output_vt100::try_init().ok(); // Do not panic on fail
79 }
80
81 /// A comparison of two values.
82 ///
83 /// Where both values implement `Debug`, the comparison can be displayed as a pretty diff.
84 ///
85 /// ```
86 /// use pretty_assertions::Comparison;
87 ///
88 /// print!("{}", Comparison::new(&123, &134));
89 /// ```
90 ///
91 /// The values may have different types, although in practice they are usually the same.
92 pub struct Comparison<'a, TLeft, TRight>
93 where
94 TLeft: ?Sized,
95 TRight: ?Sized,
96 {
97 left: &'a TLeft,
98 right: &'a TRight,
99 }
100
101 impl<'a, TLeft, TRight> Comparison<'a, TLeft, TRight>
102 where
103 TLeft: ?Sized,
104 TRight: ?Sized,
105 {
106 /// Store two values to be compared in future.
107 ///
108 /// Expensive diffing is deferred until calling `Debug::fmt`.
109 pub fn new(left: &'a TLeft, right: &'a TRight) -> Comparison<'a, TLeft, TRight> {
110 Comparison { left, right }
111 }
112 }
113
114 impl<'a, TLeft, TRight> Display for Comparison<'a, TLeft, TRight>
115 where
116 TLeft: Debug + ?Sized,
117 TRight: Debug + ?Sized,
118 {
119 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
120 // To diff arbitary types, render them as debug strings
121 let left_debug = format!("{:#?}", self.left);
122 let right_debug = format!("{:#?}", self.right);
123 // And then diff the debug output
124 printer::write_header(f)?;
125 printer::write_lines(f, &left_debug, &right_debug)
126 }
127 }
128
129 /// Asserts that two expressions are equal to each other (using [`PartialEq`]).
130 ///
131 /// On panic, this macro will print a diff derived from [`Debug`] representation of
132 /// each value.
133 ///
134 /// This is a drop in replacement for [`std::assert_eq!`].
135 /// You can provide a custom panic message if desired.
136 ///
137 /// # Examples
138 ///
139 /// ```
140 /// use pretty_assertions::assert_eq;
141 ///
142 /// let a = 3;
143 /// let b = 1 + 2;
144 /// assert_eq!(a, b);
145 ///
146 /// assert_eq!(a, b, "we are testing addition with {} and {}", a, b);
147 /// ```
148 #[macro_export]
149 macro_rules! assert_eq {
150 ($left:expr , $right:expr,) => ({
151 $crate::assert_eq!($left, $right)
152 });
153 ($left:expr , $right:expr) => ({
154 match (&($left), &($right)) {
155 (left_val, right_val) => {
156 if !(*left_val == *right_val) {
157 ::std::panic!("assertion failed: `(left == right)`\
158 \n\
159 \n{}\
160 \n",
161 $crate::Comparison::new(left_val, right_val))
162 }
163 }
164 }
165 });
166 ($left:expr , $right:expr, $($arg:tt)*) => ({
167 match (&($left), &($right)) {
168 (left_val, right_val) => {
169 if !(*left_val == *right_val) {
170 ::std::panic!("assertion failed: `(left == right)`: {}\
171 \n\
172 \n{}\
173 \n",
174 format_args!($($arg)*),
175 $crate::Comparison::new(left_val, right_val))
176 }
177 }
178 }
179 });
180 }
181
182 /// Asserts that two expressions are not equal to each other (using [`PartialEq`]).
183 ///
184 /// On panic, this macro will print the values of the expressions with their
185 /// [`Debug`] representations.
186 ///
187 /// This is a drop in replacement for [`std::assert_ne!`].
188 /// You can provide a custom panic message if desired.
189 ///
190 /// # Examples
191 ///
192 /// ```
193 /// use pretty_assertions::assert_ne;
194 ///
195 /// let a = 3;
196 /// let b = 2;
197 /// assert_ne!(a, b);
198 ///
199 /// assert_ne!(a, b, "we are testing that the values are not equal");
200 /// ```
201 #[macro_export]
202 macro_rules! assert_ne {
203 ($left:expr, $right:expr) => ({
204 $crate::assert_ne!(@ $left, $right, "", "");
205 });
206 ($left:expr, $right:expr,) => ({
207 $crate::assert_ne!(@ $left, $right, "", "");
208 });
209 ($left:expr, $right:expr, $($arg:tt)+) => ({
210 $crate::assert_ne!(@ $left, $right, ": ", $($arg)+);
211 });
212 (@ $left:expr, $right:expr, $maybe_semicolon:expr, $($arg:tt)+) => ({
213 match (&($left), &($right)) {
214 (left_val, right_val) => {
215 if *left_val == *right_val {
216 let left_dbg = ::std::format!("{:?}", &*left_val);
217 let right_dbg = ::std::format!("{:?}", &*right_val);
218 if left_dbg != right_dbg {
219
220 ::std::panic!("assertion failed: `(left != right)`{}{}\
221 \n\
222 \n{}\
223 \n{}: According to the `PartialEq` implementation, both of the values \
224 are partially equivalent, even if the `Debug` outputs differ.\
225 \n\
226 \n",
227 $maybe_semicolon,
228 format_args!($($arg)+),
229 $crate::Comparison::new(left_val, right_val),
230 $crate::Style::new()
231 .bold()
232 .underline()
233 .paint("Note"))
234 }
235
236 ::std::panic!("assertion failed: `(left != right)`{}{}\
237 \n\
238 \n{}:\
239 \n{:#?}\
240 \n\
241 \n",
242 $maybe_semicolon,
243 format_args!($($arg)+),
244 $crate::Style::new().bold().paint("Both sides"),
245 left_val)
246 }
247 }
248 }
249 });
250 }
251
252 #[cfg(test)]
253 #[allow(clippy::eq_op)]
254 #[no_implicit_prelude]
255 mod test {
256 mod assert_eq {
257 use ::std::string::{String, ToString};
258
259 #[test]
260 fn passes() {
261 let a = "some value";
262 crate::assert_eq!(a, a);
263 }
264
265 #[test]
266 fn passes_unsized() {
267 let a: &[u8] = b"e";
268 crate::assert_eq!(*a, *a);
269 }
270
271 #[test]
272 fn passes_comparable_types() {
273 let s0: &'static str = "foo";
274 let s1: String = "foo".to_string();
275 crate::assert_eq!(s0, s1);
276 }
277
278 #[test]
279 #[should_panic(expected = r#"assertion failed: `(left == right)`
280
281 \e[1mDiff\e[0m \e[31m< left\e[0m / \e[32mright >\e[0m :
282 \e[31m<\e[0m\e[1;48;5;52;31m666\e[0m
283 \e[32m>\e[0m\e[1;48;5;22;32m999\e[0m
284
285 "#)]
286 fn fails() {
287 crate::assert_eq!(666, 999);
288 }
289
290 #[test]
291 #[should_panic(expected = r#"assertion failed: `(left == right)`
292
293 \e[1mDiff\e[0m \e[31m< left\e[0m / \e[32mright >\e[0m :
294 \e[31m<\e[0m\e[1;48;5;52;31m666\e[0m
295 \e[32m>\e[0m\e[1;48;5;22;32m999\e[0m
296
297 "#)]
298 fn fails_trailing_comma() {
299 crate::assert_eq!(666, 999,);
300 }
301
302 #[test]
303 #[should_panic(expected = r#"assertion failed: `(left == right)`
304
305 \e[1mDiff\e[0m \e[31m< left\e[0m / \e[32mright >\e[0m :
306 [
307 101,
308 \e[32m> 101,\e[0m
309 ]
310
311 "#)]
312 fn fails_unsized() {
313 let a: &[u8] = b"e";
314 let b: &[u8] = b"ee";
315 crate::assert_eq!(*a, *b);
316 }
317
318 #[test]
319 #[should_panic(
320 expected = r#"assertion failed: `(left == right)`: custom panic message
321
322 \e[1mDiff\e[0m \e[31m< left\e[0m / \e[32mright >\e[0m :
323 \e[31m<\e[0m\e[1;48;5;52;31m666\e[0m
324 \e[32m>\e[0m\e[1;48;5;22;32m999\e[0m
325
326 "#
327 )]
328 fn fails_custom() {
329 crate::assert_eq!(666, 999, "custom panic message");
330 }
331
332 #[test]
333 #[should_panic(
334 expected = r#"assertion failed: `(left == right)`: custom panic message
335
336 \e[1mDiff\e[0m \e[31m< left\e[0m / \e[32mright >\e[0m :
337 \e[31m<\e[0m\e[1;48;5;52;31m666\e[0m
338 \e[32m>\e[0m\e[1;48;5;22;32m999\e[0m
339
340 "#
341 )]
342 fn fails_custom_trailing_comma() {
343 crate::assert_eq!(666, 999, "custom panic message",);
344 }
345 }
346
347 mod assert_ne {
348 use ::std::string::{String, ToString};
349
350 #[test]
351 fn passes() {
352 let a = "a";
353 let b = "b";
354 crate::assert_ne!(a, b);
355 }
356
357 #[test]
358 fn passes_unsized() {
359 let a: &[u8] = b"e";
360 let b: &[u8] = b"ee";
361 crate::assert_ne!(*a, *b);
362 }
363
364 #[test]
365 fn passes_comparable_types() {
366 let s0: &'static str = "foo";
367 let s1: String = "bar".to_string();
368 crate::assert_ne!(s0, s1);
369 }
370
371 #[test]
372 #[should_panic(expected = r#"assertion failed: `(left != right)`
373
374 \e[1mBoth sides\e[0m:
375 666
376 "#)]
377 fn fails() {
378 crate::assert_ne!(666, 666);
379 }
380
381 #[test]
382 #[should_panic(expected = r#"assertion failed: `(left != right)`
383
384 \e[1mBoth sides\e[0m:
385 666
386 "#)]
387 fn fails_trailing_comma() {
388 crate::assert_ne!(666, 666,);
389 }
390
391 #[test]
392 #[should_panic(expected = r#"assertion failed: `(left != right)`
393
394 \e[1mBoth sides\e[0m:
395 [
396 101,
397 ]
398
399 "#)]
400 fn fails_unsized() {
401 let a: &[u8] = b"e";
402 crate::assert_ne!(*a, *a);
403 }
404
405 #[test]
406 #[should_panic(
407 expected = r#"assertion failed: `(left != right)`: custom panic message
408
409 \e[1mBoth sides\e[0m:
410 666
411 "#
412 )]
413 fn fails_custom() {
414 crate::assert_ne!(666, 666, "custom panic message");
415 }
416
417 #[test]
418 #[should_panic(
419 expected = r#"assertion failed: `(left != right)`: custom panic message
420
421 \e[1mBoth sides\e[0m:
422 666
423 "#
424 )]
425 fn fails_custom_trailing_comma() {
426 crate::assert_ne!(666, 666, "custom panic message",);
427 }
428
429 // If the values are equal but their debug outputs are not
430 // show a specific warning
431
432 #[test]
433 #[should_panic(expected = r#"assertion failed: `(left != right)`
434
435 \e[1mDiff\e[0m \e[31m< left\e[0m / \e[32mright >\e[0m :
436 \e[31m<\e[0m\e[1;48;5;52;31m-\e[0m\e[31m0.0\e[0m
437 \e[32m>0.0\e[0m
438
439 \e[1;4mNote\e[0m: According to the `PartialEq` implementation, both of the values are partially equivalent, even if the `Debug` outputs differ.
440
441 "#)]
442 fn assert_ne_partial() {
443 // Workaround for https://github.com/rust-lang/rust/issues/47619
444 // can be removed, when we require rust 1.25 or higher
445 struct Foo(f32);
446
447 use ::std::fmt;
448 impl fmt::Debug for Foo {
449 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
450 ::std::write!(f, "{:.1?}", self.0)
451 }
452 }
453
454 impl ::std::cmp::PartialEq for Foo {
455 fn eq(&self, other: &Self) -> bool {
456 self.0 == other.0
457 }
458 }
459
460 crate::assert_ne!(Foo(-0.0), Foo(0.0));
461 }
462
463 // Regression tests
464
465 #[test]
466 #[should_panic]
467 fn assert_ne_non_empty_return() {
468 fn not_zero(x: u32) -> u32 {
469 crate::assert_ne!(x, 0);
470 x
471 }
472 not_zero(0);
473 }
474 }
475 }