assert_str/
lib.rs

1//! Macros for asserting of multiline strings [`String`] and [`&str`].
2//! The API is very similar to the API provided by the stdlib's own assert_eq!
3//! or assert_ne!. Left and right expression could be different types.
4//!
5//! # Examples
6//!
7//! Some examples are provided in the docs for
8//! [each individual macro](#macros).
9//!
10//! [`String`]: https://doc.rust-lang.org/std/string/struct.String.html
11//! [`&str`]: https://doc.rust-lang.org/std/str/index.html
12
13/// Asserts that multiline strings([`&str`] or [`String`]) are identical. It
14/// ignores different new line characters for different OSes: `\n` or `\r\n`.
15///
16/// # Examples
17///
18/// Test on equality of two strings generated on different OSes:
19///
20/// ```
21/// use assert_str::assert_str_eq;
22/// assert_str_eq!("This string\nEnd", "This string\r\nEnd", "Responces should be equal");
23/// ```
24///
25#[macro_export]
26macro_rules! assert_str_eq {
27    ($left:expr, $right:expr) => ({
28        match (&$left, &$right) {
29            (left_val, right_val) => {
30                let left_lines = left_val.lines().collect::<Vec<_>>();
31                let right_lines = right_val.lines().collect::<Vec<_>>();
32                if !(left_lines == right_lines) {
33                    panic!(r#"assertion failed: `(left == right)`
34  left: `{}`,
35 right: `{}`"#, left_lines.join("\n"), right_lines.join("\n"))
36                }
37            }
38        }
39    });
40    ($left:expr, $right:expr,) => ({
41        $crate::assert_str_eq!($left, $right)
42    });
43    ($left:expr, $right:expr, $($arg:tt)+) => ({
44        match (&$left, &$right) {
45            (left_val, right_val) => {
46                let left_lines = left_val.lines().collect::<Vec<_>>();
47                let right_lines = right_val.lines().collect::<Vec<_>>();
48                if !(left_lines == right_lines) {
49                    panic!(r#"assertion failed: `(left == right)`
50  left: `{}`,
51 right: `{}`: {}"#, left_lines.join("\n"), right_lines.join("\n"),
52                    format_args!($($arg)+))
53                }
54            }
55        }
56    });
57}
58
59/// Asserts that multiline strings(`&str` or `String`) are not identical. It
60/// ignores different new line characters for different OSes: `\n` or `\r\n`.
61///
62/// # Examples
63///
64/// Test on inequality of two strings generated on different OSes:
65///
66/// ```
67/// use assert_str::assert_str_ne;
68/// assert_str_ne!("This string\nEnd", "This string\r\nFinalEnd", "Responces should not be equal");
69/// ```
70///
71#[macro_export]
72macro_rules! assert_str_ne {
73    ($left:expr, $right:expr) => ({
74        match (&$left, &$right) {
75            (left_val, right_val) => {
76                let left_lines = left_val.lines().collect::<Vec<_>>();
77                let right_lines = right_val.lines().collect::<Vec<_>>();
78                if (left_lines == right_lines) {
79                    panic!(r#"assertion failed: `(left != right)`
80  left: `{}`,
81 right: `{}`"#, left_lines.join("\n"), right_lines.join("\n"))
82                }
83            }
84        }
85    });
86    ($left:expr, $right:expr,) => ({
87        $crate::assert_str_ne!($left, $right)
88    });
89    ($left:expr, $right:expr, $($arg:tt)+) => ({
90        match (&$left, &$right) {
91            (left_val, right_val) => {
92                let left_lines = left_val.lines().collect::<Vec<_>>();
93                let right_lines = right_val.lines().collect::<Vec<_>>();
94                if (left_lines == right_lines) {
95                    panic!(r#"assertion failed: `(left != right)`
96  left: `{}`,
97  right: `{}`: {}"#, left_lines.join("\n"), right_lines.join("\n"),
98                    format_args!($($arg)+))
99                }
100            }
101        }
102    });
103}
104
105/// Asserts that multiline strings(`&str` or `String`) are identical when
106/// every line is trimmed and empty lines are removed. It ignores different
107/// new line characters for different OSes: `\n` or `\r\n`.
108///
109/// # Examples
110///
111/// Test on equality of two trimmed strings generated on different OSes:
112///
113/// ```
114/// use assert_str::assert_str_trim_eq;
115/// assert_str_trim_eq!("<html>\t \n\t<head> \n\t</head></html>",
116///     "<html>\r\n<head>\r\n</head></html>", "Responces should be equal");
117/// ```
118///
119#[macro_export]
120macro_rules! assert_str_trim_eq {
121    ($left:expr, $right:expr) => ({
122        match (&$left, &$right) {
123            (left_val, right_val) => {
124                let left_lines = left_val
125                    .lines()
126                    .map(|line| line.trim())
127                    .filter(|line| !line.is_empty())
128                    .collect::<Vec<_>>();
129
130                let right_lines = right_val
131                    .lines()
132                    .map(|line| line.trim())
133                    .filter(|line| !line.is_empty())
134                    .collect::<Vec<_>>();
135
136                if !(left_lines == right_lines) {
137                    panic!(r#"assertion failed: `(left == right)`
138  left: `{}`,
139 right: `{}`"#, left_lines.join("\n"), right_lines.join("\n"))
140                }
141            }
142        }
143    });
144    ($left:expr, $right:expr,) => ({
145        $crate::assert_str_trim_eq!($left, $right)
146    });
147    ($left:expr, $right:expr, $($arg:tt)+) => ({
148        match (&$left, &$right) {
149            (left_val, right_val) => {
150                let left_lines = left_val
151                    .lines()
152                    .map(|line| line.trim())
153                    .filter(|line| !line.is_empty())
154                    .collect::<Vec<_>>();
155
156                let right_lines = right_val
157                    .lines()
158                    .map(|line| line.trim())
159                    .filter(|line| !line.is_empty())
160                    .collect::<Vec<_>>();
161
162                if !(left_lines == right_lines) {
163                    panic!(r#"assertion failed: `(left == right)`
164  left: `{}`,
165 right: `{}`: {}"#, left_lines.join("\n"), right_lines.join("\n"),
166                    format_args!($($arg)+))
167                }
168            }
169        }
170    });
171}
172
173/// Asserts that multiline strings([&str] or [String]) are identical. It
174/// ignores different new line characters for different OSes: `\n` or `\r\n`
175///
176/// # Examples
177///
178/// Test on equality of two trimmed strings:
179///
180/// ```
181/// use assert_str::assert_str_trim_ne;
182/// assert_str_trim_ne!("<html>\t \n\t<head> \n\t</head></html>",
183///     "<HTML><head></head></html>", "Responces should not be equal");
184/// ```
185///
186#[macro_export]
187macro_rules! assert_str_trim_ne {
188    ($left:expr, $right:expr) => ({
189        match (&$left, &$right) {
190            (left_val, right_val) => {
191                let left_lines = left_val
192                    .lines()
193                    .map(|x| x.trim())
194                    .filter(|line| !line.is_empty())
195                    .collect::<Vec<_>>();
196
197                let right_lines = right_val
198                    .lines()
199                    .map(|x| x.trim())
200                    .filter(|line| !line.is_empty())
201                    .collect::<Vec<_>>();
202
203                if (left_lines == right_lines) {
204                    panic!(r#"assertion failed: `(left != right)`
205  left: `{}`,
206 right: `{}`"#, left_lines.join("\n"), right_lines.join("\n"))
207                }
208            }
209        }
210    });
211    ($left:expr, $right:expr,) => ({
212        $crate::assert_str_trim_ne!($left, $right)
213    });
214    ($left:expr, $right:expr, $($arg:tt)+) => ({
215        match (&$left, &$right) {
216            (left_val, right_val) => {
217                let left_lines = left_val
218                    .lines()
219                    .map(|x| x.trim())
220                    .filter(|line| !line.is_empty())
221                    .collect::<Vec<_>>();
222
223                let right_lines = right_val
224                    .lines()
225                    .map(|x| x.trim())
226                    .filter(|line| !line.is_empty())
227                    .collect::<Vec<_>>();
228
229                if (left_lines == right_lines) {
230                    panic!(r#"assertion failed: `(left != right)`
231  left: `{}`,
232 right: `{}`: {}"#, left_lines.join("\n"), right_lines.join("\n"),
233                    format_args!($($arg)+))
234                }
235            }
236        }
237    });
238}
239
240/// Asserts that multiline strings(`&str` or `String`) are identical when
241/// every line is trimmed and new lines are removed.
242///
243/// # Examples
244///
245/// Test on equality of two trimmed strings:
246///
247/// ```
248/// use assert_str::assert_str_trim_all_eq;
249/// assert_str_trim_all_eq!("<html>\t \n\t<head> \n\t</head></html>",
250///     "<html><head></head></html>", "Responces should be equal");
251/// ```
252///
253#[macro_export]
254macro_rules! assert_str_trim_all_eq {
255    ($left:expr, $right:expr) => ({
256        match (&$left, &$right) {
257            (left_val, right_val) => {
258                let left_lines = left_val
259                    .lines()
260                    .map(|line| line.trim())
261                    .filter(|line| !line.is_empty())
262                    .collect::<Vec<_>>();
263
264                let right_lines = right_val
265                    .lines()
266                    .map(|line| line.trim())
267                    .filter(|line| !line.is_empty())
268                    .collect::<Vec<_>>();
269
270                if !(left_lines == right_lines) {
271                    panic!(r#"assertion failed: `(left == right)`
272  left: `{}`,
273 right: `{}`"#, left_lines.join("\n"), right_lines.join("\n"))
274                }
275            }
276        }
277    });
278    ($left:expr, $right:expr,) => ({
279        $crate::assert_str_trim_eq!($left, $right)
280    });
281    ($left:expr, $right:expr, $($arg:tt)+) => ({
282        match (&$left, &$right) {
283            (left_val, right_val) => {
284                let left_lines = left_val
285                    .lines()
286                    .map(|line| line.trim())
287                    .fold(String::new(), |acc, x| acc + x);
288
289                let right_lines = right_val
290                    .lines()
291                    .map(|line| line.trim())
292                    .fold(String::new(), |acc, x| acc + x);
293
294                if !(left_lines == right_lines) {
295                    panic!(r#"assertion failed: `(left == right)`
296  left: `{}`,
297 right: `{}`: {}"#, left_lines, right_lines,
298                    format_args!($($arg)+))
299                }
300            }
301        }
302    });
303}
304
305/// Asserts that multiline strings([&str] or [String]) are identical when
306/// every line is trimmed and new lines are removed.
307///
308/// # Examples
309///
310/// Test on inequality of two trimmed strings:
311///
312/// ```
313/// use assert_str::assert_str_trim_all_ne;
314/// assert_str_trim_all_ne!("<html>\t \n\t<head> \n\t</head></html>",
315///     "<HTML><head></head></html>", "Responces should not be equal");
316/// ```
317///
318#[macro_export]
319macro_rules! assert_str_trim_all_ne {
320    ($left:expr, $right:expr) => ({
321        match (&$left, &$right) {
322            (left_val, right_val) => {
323                let left_lines = left_val
324                    .lines()
325                    .map(|x| x.trim())
326                    .fold(String::new(), |acc, x| acc + x);
327
328                let right_lines = right_val
329                    .lines()
330                    .map(|x| x.trim())
331                    .fold(String::new(), |acc, x| acc + x);
332
333                if (left_lines == right_lines) {
334                    panic!(r#"assertion failed: `(left != right)`
335  left: `{}`,
336 right: `{}`"#, left_lines, right_lines)
337                }
338            }
339        }
340    });
341    ($left:expr, $right:expr,) => ({
342        $crate::assert_str_trim_ne!($left, $right)
343    });
344    ($left:expr, $right:expr, $($arg:tt)+) => ({
345        match (&$left, &$right) {
346            (left_val, right_val) => {
347                let left_lines = left_val
348                    .lines()
349                    .map(|x| x.trim())
350                    .fold(String::new(), |acc, x| acc + x);
351
352                let right_lines = right_val
353                    .lines()
354                    .map(|x| x.trim())
355                    .fold(String::new(), |acc, x| acc + x);
356
357                if (left_lines == right_lines) {
358                    panic!(r#"assertion failed: `(left != right)`
359  left: `{}`,
360 right: `{}`: {}"#, left_lines, right_lines,
361                    format_args!($($arg)+))
362                }
363            }
364        }
365    });
366}
367
368#[cfg(test)]
369mod tests {
370    #[test]
371    fn cross_str_equal_simple() {
372        assert_str_eq!("Line\nLine2", "Line\r\nLine2");
373        assert_str_eq!("Line\nLine2".to_owned(), "Line\r\nLine2");
374        assert_str_eq!("Line\nLine2", "Line\r\nLine2".to_owned());
375        assert_str_eq!("Line\nLine2".to_owned(), "Line\r\nLine2".to_owned());
376        assert_str_eq!("Line\nLine2", "Line\r\nLine2",);
377    }
378
379    #[test]
380    fn cross_str_equal_message() {
381        assert_str_eq!("Line\nLine2".to_owned(), "Line\r\nLine2", "Message");
382        assert_str_eq!("Line\nLine2", "Line\r\nLine2".to_owned(), "Message");
383        assert_str_eq!("L\nLine2".to_owned(), "L\r\nLine2".to_owned(), "Message");
384        assert_str_eq!("Line\nLine2", "Line\r\nLine2", "Message");
385    }
386
387    #[test]
388    fn cross_str_not_equal_simple() {
389        assert_str_ne!("Line\nLine2", "Line\r\nLine");
390        assert_str_ne!("Line\nLine2".to_owned(), "Line\r\nLine");
391        assert_str_ne!("Line\nLine2", "Line\r\nLine".to_owned());
392        assert_str_ne!("Line\nLine2", "Line\r\nLine",);
393    }
394
395    #[test]
396    fn cross_str_not_equal_message() {
397        assert_str_ne!("Line\nLine2".to_owned(), "Line\r\nLine", "Message");
398        assert_str_ne!("Line\nLine2", "Line\r\nLine".to_owned(), "Message");
399        assert_str_ne!("L\nLine2".to_owned(), "L\r\nLine".to_owned(), "Message");
400        assert_str_ne!("Line\nLine2", "Line\r\nLine", "Message");
401    }
402
403    #[test]
404    fn cross_str_trim_equal() {
405        let left = "String  \n Line ".to_owned();
406        let right = "String\r\nLine".to_owned();
407        assert_str_trim_eq!(left, right);
408        assert_str_trim_eq!(&left, right);
409        assert_str_trim_eq!(left, &right);
410        assert_str_trim_eq!(&left, &right);
411        assert_str_trim_eq!(left, right,);
412    }
413
414    #[test]
415    fn cross_str_trim_equal_message() {
416        let left = "String  \n Line ".to_owned();
417        let right = "String\r\nLine".to_owned();
418        assert_str_trim_eq!(&left, right, "Message");
419        assert_str_trim_eq!(left, &right, "Message");
420        assert_str_trim_eq!(left, right, "Message");
421        assert_str_trim_eq!(&left, &right, "Message");
422    }
423
424    #[test]
425    fn cross_str_trim_not_equal() {
426        let left = "String  \n Line ".to_owned();
427        let right = "String\r\n12".to_owned();
428        assert_str_trim_ne!(left, right);
429        assert_str_trim_ne!(&left, right);
430        assert_str_trim_ne!(left, &right);
431        assert_str_trim_ne!(&left, &right);
432        assert_str_trim_ne!(left, right,);
433    }
434
435    #[test]
436    fn cross_str_trim_not_equal_message() {
437        let left = "String  \n Line ".to_owned();
438        let right = "String\r\n12".to_owned();
439        assert_str_trim_ne!(left, right, "Message");
440        assert_str_trim_ne!(&left, right, "Message");
441        assert_str_trim_ne!(left, &right, "Message");
442        assert_str_trim_ne!(&left, &right, "Message");
443    }
444
445    #[test]
446    fn cross_str_trim_all_equal() {
447        let left = "String  \n Line ".to_owned();
448        let right = "String\r\nLine".to_owned();
449        assert_str_trim_all_eq!(left, right);
450        assert_str_trim_all_eq!(&left, right);
451        assert_str_trim_all_eq!(left, &right);
452        assert_str_trim_all_eq!(&left, &right);
453        assert_str_trim_all_eq!(left, right,);
454    }
455
456    #[test]
457    fn cross_str_trim_all_equal_message() {
458        let left = "String  \n Line ".to_owned();
459        let right = "StringLine".to_owned();
460        assert_str_trim_all_eq!(&left, right, "Message");
461        assert_str_trim_all_eq!(left, &right, "Message");
462        assert_str_trim_all_eq!(left, right, "Message");
463        assert_str_trim_all_eq!(&left, &right, "Message");
464    }
465
466    #[test]
467    fn cross_str_trim_all_not_equal() {
468        let left = "String  \n Line ".to_owned();
469        let right = "Stringline".to_owned();
470        assert_str_trim_all_ne!(left, right);
471        assert_str_trim_all_ne!(&left, right);
472        assert_str_trim_all_ne!(left, &right);
473        assert_str_trim_all_ne!(&left, &right);
474        assert_str_trim_all_ne!(left, right,);
475    }
476
477    #[test]
478    fn cross_str_trim_all_not_equal_message() {
479        let left = "String  \n Line ".to_owned();
480        let right = "String12".to_owned();
481        assert_str_trim_all_ne!(left, right, "Message");
482        assert_str_trim_all_ne!(&left, right, "Message");
483        assert_str_trim_all_ne!(left, &right, "Message");
484        assert_str_trim_all_ne!(&left, &right, "Message");
485    }
486}