assertables/assert_contains/
assert_not_contains.rs

1//! Assert an expression (such as a string) does not contain an expression (such as a substring).
2//!
3//! Pseudocode:<br>
4//! ¬ a.contains(b)
5//!
6//! # Example
7//!
8//! ```rust
9//! use assertables::*;
10//!
11//! // String contains substring?
12//! let a = "alfa";
13//! let b = "zz";
14//! assert_not_contains!(a, b);
15//!
16//! // Range contains value?
17//! let a = 1..3;
18//! let b = 4;
19//! assert_not_contains!(a, &b);
20//!
21//! // Vector contains element?
22//! let a = vec![1, 2, 3];
23//! let b = 4;
24//! assert_not_contains!(a, &b);
25//! ```
26//!
27//! # Module macros
28//!
29//! * [`assert_not_contains`](macro@crate::assert_not_contains)
30//! * [`assert_not_contains_as_result`](macro@crate::assert_not_contains_as_result)
31//! * [`debug_assert_not_contains`](macro@crate::debug_assert_not_contains)
32
33/// Assert an expression (such as a string) does not contain an expression (such as a substring).
34///
35/// Pseudocode:<br>
36/// ¬ a.contains(b)
37///
38/// * If true, return Result `Ok(())`.
39///
40/// * Otherwise, return Result `Err(message)`.
41///
42/// This macro is useful for runtime checks, such as checking parameters,
43/// or sanitizing inputs, or handling different results in different ways.
44///
45/// # Module macros
46///
47/// * [`assert_not_contains`](macro@crate::assert_not_contains)
48/// * [`assert_not_contains_as_result`](macro@crate::assert_not_contains_as_result)
49/// * [`debug_assert_not_contains`](macro@crate::debug_assert_not_contains)
50///
51#[macro_export]
52macro_rules! assert_not_contains_as_result {
53    ($container:expr, $containee:expr $(,)?) => {{
54        match (&$container, &$containee) {
55            (container, containee) => {
56                if !(container.contains($containee)) {
57                    Ok(())
58                } else {
59                    Err(
60                        format!(
61                            concat!(
62                                "assertion failed: `assert_not_contains!(container, containee)`\n",
63                                "https://docs.rs/assertables/9.5.1/assertables/macro.assert_not_contains.html\n",
64                                " container label: `{}`,\n",
65                                " container debug: `{:?}`,\n",
66                                " containee label: `{}`,\n",
67                                " containee debug: `{:?}`",
68                            ),
69                            stringify!($container),
70                            container,
71                            stringify!($containee),
72                            containee,
73                        )
74                    )
75                }
76            }
77        }
78    }};
79}
80
81#[cfg(test)]
82mod test_assert_not_contains_as_result {
83
84    mod str {
85
86        #[test]
87        fn success() {
88            let a = "alfa";
89            let b = "zz";
90            let actual = assert_not_contains_as_result!(a, b);
91            assert_eq!(actual.unwrap(), ());
92        }
93
94        #[test]
95        fn failure() {
96            let a = "alfa";
97            let b = "lf";
98            let actual = assert_not_contains_as_result!(a, b);
99            let message = concat!(
100                "assertion failed: `assert_not_contains!(container, containee)`\n",
101                "https://docs.rs/assertables/9.5.1/assertables/macro.assert_not_contains.html\n",
102                " container label: `a`,\n",
103                " container debug: `\"alfa\"`,\n",
104                " containee label: `b`,\n",
105                " containee debug: `\"lf\"`"
106            );
107            assert_eq!(actual.unwrap_err(), message);
108        }
109    }
110
111    mod range {
112
113        #[test]
114        fn success() {
115            let a = 1..3;
116            let b = 4;
117            let actual = assert_not_contains_as_result!(a, &b);
118            assert_eq!(actual.unwrap(), ());
119        }
120
121        #[test]
122        fn failure() {
123            let a = 1..3;
124            let b = 2;
125            let actual = assert_not_contains_as_result!(a, &b);
126            let message = concat!(
127                "assertion failed: `assert_not_contains!(container, containee)`\n",
128                "https://docs.rs/assertables/9.5.1/assertables/macro.assert_not_contains.html\n",
129                " container label: `a`,\n",
130                " container debug: `1..3`,\n",
131                " containee label: `&b`,\n",
132                " containee debug: `2`"
133            );
134            assert_eq!(actual.unwrap_err(), message);
135        }
136    }
137
138    mod vec {
139
140        #[test]
141        fn success() {
142            let a = 1..3;
143            let b = 4;
144            let actual = assert_not_contains_as_result!(a, &b);
145            assert_eq!(actual.unwrap(), ());
146        }
147
148        #[test]
149        fn failure() {
150            let a = vec![1, 2, 3];
151            let b = 2;
152            let actual = assert_not_contains_as_result!(a, &b);
153            let message = concat!(
154                "assertion failed: `assert_not_contains!(container, containee)`\n",
155                "https://docs.rs/assertables/9.5.1/assertables/macro.assert_not_contains.html\n",
156                " container label: `a`,\n",
157                " container debug: `[1, 2, 3]`,\n",
158                " containee label: `&b`,\n",
159                " containee debug: `2`"
160            );
161            assert_eq!(actual.unwrap_err(), message);
162        }
163    }
164}
165
166/// Assert an expression (such as a string) does not contain an expression (such as a substring).
167///
168/// Pseudocode:<br>
169/// ¬ a.contains(b)
170///
171/// * If true, return `()`.
172///
173/// * Otherwise, call [`panic!`] with a message and the values of the
174///   expressions with their debug representations.
175///
176/// # Examples
177///
178/// ```rust
179/// use assertables::*;
180/// # use std::panic;
181///
182/// # fn main() {
183/// // String contains substring?
184/// let a = "alfa";
185/// let b = "zz";
186/// assert_not_contains!(a, b);
187///
188/// // Range contains value?
189/// let a = 1..3;
190/// let b = 4;
191/// assert_not_contains!(a, &b);
192///
193/// // Vector contains element?
194/// let a = vec![1, 2, 3];
195/// let b = 4;
196/// assert_not_contains!(a, &b);
197///
198/// # let result = panic::catch_unwind(|| {
199/// // This will panic
200/// let a = "alfa";
201/// let b = "lf";
202/// assert_not_contains!(a, b);
203/// # });
204/// // assertion failed: `assert_not_contains!(container, containee)`
205/// // https://docs.rs/assertables/9.5.1/assertables/macro.assert_not_contains.html
206/// //  container label: `a`,
207/// //  container debug: `\"alfa\"`,
208/// //  containee label: `b`,
209/// //  containee debug: `\"lf\"`
210/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
211/// # let message = concat!(
212/// #     "assertion failed: `assert_not_contains!(container, containee)`\n",
213/// #     "https://docs.rs/assertables/9.5.1/assertables/macro.assert_not_contains.html\n",
214/// #     " container label: `a`,\n",
215/// #     " container debug: `\"alfa\"`,\n",
216/// #     " containee label: `b`,\n",
217/// #     " containee debug: `\"lf\"`"
218/// # );
219/// # assert_eq!(actual, message);
220/// # }
221/// ```
222///
223/// # Module macros
224///
225/// * [`assert_not_contains`](macro@crate::assert_not_contains)
226/// * [`assert_not_contains_as_result`](macro@crate::assert_not_contains_as_result)
227/// * [`debug_assert_not_contains`](macro@crate::debug_assert_not_contains)
228///
229#[macro_export]
230macro_rules! assert_not_contains {
231    ($container:expr, $containee:expr $(,)?) => {{
232        match $crate::assert_not_contains_as_result!($container, $containee) {
233            Ok(()) => (),
234            Err(err) => panic!("{}", err),
235        }
236    }};
237    ($container:expr, $containee:expr, $($message:tt)+) => {{
238        match $crate::assert_not_contains_as_result!($container, $containee) {
239            Ok(()) => (),
240            Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
241        }
242    }};
243}
244
245#[cfg(test)]
246mod test_assert_not_contains {
247
248    mod str {
249        use std::panic;
250
251        #[test]
252        fn success() {
253            let a = "alfa";
254            let b = "zz";
255            let actual = assert_not_contains!(a, b);
256            assert_eq!(actual, ());
257        }
258
259        #[test]
260        fn failure() {
261            let result = panic::catch_unwind(|| {
262                let a = "alfa";
263                let b = "lf";
264                let _actual = assert_not_contains!(a, b);
265            });
266            let message = concat!(
267                "assertion failed: `assert_not_contains!(container, containee)`\n",
268                "https://docs.rs/assertables/9.5.1/assertables/macro.assert_not_contains.html\n",
269                " container label: `a`,\n",
270                " container debug: `\"alfa\"`,\n",
271                " containee label: `b`,\n",
272                " containee debug: `\"lf\"`"
273            );
274            assert_eq!(
275                result
276                    .unwrap_err()
277                    .downcast::<String>()
278                    .unwrap()
279                    .to_string(),
280                message
281            );
282        }
283    }
284
285    mod range {
286        use std::panic;
287
288        #[test]
289        fn success() {
290            let a = 1..3;
291            let b = 4;
292            let actual = assert_not_contains!(a, &b);
293            assert_eq!(actual, ());
294        }
295
296        #[test]
297        fn failure() {
298            let result = panic::catch_unwind(|| {
299                let a = 1..3;
300                let b = 2;
301                let _actual = assert_not_contains!(a, &b);
302            });
303            let message = concat!(
304                "assertion failed: `assert_not_contains!(container, containee)`\n",
305                "https://docs.rs/assertables/9.5.1/assertables/macro.assert_not_contains.html\n",
306                " container label: `a`,\n",
307                " container debug: `1..3`,\n",
308                " containee label: `&b`,\n",
309                " containee debug: `2`"
310            );
311            assert_eq!(
312                result
313                    .unwrap_err()
314                    .downcast::<String>()
315                    .unwrap()
316                    .to_string(),
317                message
318            );
319        }
320    }
321
322    mod vec {
323        use std::panic;
324
325        #[test]
326        fn success() {
327            let a = 1..3;
328            let b = 4;
329            let actual = assert_not_contains!(a, &b);
330            assert_eq!(actual, ());
331        }
332
333        #[test]
334        fn failure() {
335            let result = panic::catch_unwind(|| {
336                let a = vec![1, 2, 3];
337                let b = 2;
338                let _actual = assert_not_contains!(a, &b);
339            });
340            let message = concat!(
341                "assertion failed: `assert_not_contains!(container, containee)`\n",
342                "https://docs.rs/assertables/9.5.1/assertables/macro.assert_not_contains.html\n",
343                " container label: `a`,\n",
344                " container debug: `[1, 2, 3]`,\n",
345                " containee label: `&b`,\n",
346                " containee debug: `2`"
347            );
348            assert_eq!(
349                result
350                    .unwrap_err()
351                    .downcast::<String>()
352                    .unwrap()
353                    .to_string(),
354                message
355            );
356        }
357    }
358}
359
360/// Assert an expression (such as a string) does not contain an expression (such as a substring).
361///
362/// Pseudocode:<br>
363/// ¬ a.contains(b)
364///
365/// This macro provides the same statements as [`assert_not_contains`](macro.assert_not_contains.html),
366/// except this macro's statements are only enabled in non-optimized
367/// builds by default. An optimized build will not execute this macro's
368/// statements unless `-C debug-assertions` is passed to the compiler.
369///
370/// This macro is useful for checks that are too expensive to be present
371/// in a release build but may be helpful during development.
372///
373/// The result of expanding this macro is always type checked.
374///
375/// An unchecked assertion allows a program in an inconsistent state to
376/// keep running, which might have unexpected consequences but does not
377/// introduce unsafety as long as this only happens in safe code. The
378/// performance cost of assertions, however, is not measurable in general.
379/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
380/// after thorough profiling, and more importantly, only in safe code!
381///
382/// This macro is intended to work in a similar way to
383/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
384///
385/// # Module macros
386///
387/// * [`assert_not_contains`](macro@crate::assert_not_contains)
388/// * [`assert_not_contains`](macro@crate::assert_not_contains)
389/// * [`debug_assert_not_contains`](macro@crate::debug_assert_not_contains)
390///
391#[macro_export]
392macro_rules! debug_assert_not_contains {
393    ($($arg:tt)*) => {
394        if $crate::cfg!(debug_assertions) {
395            $crate::assert_not_contains!($($arg)*);
396        }
397    };
398}