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}