assertables/assert_is_match/
assert_is_match.rs

1//! Assert a matcher is a match for an expression.
2//!
3//! Pseudocode:<br>
4//! a.is_match(b)
5//!
6//! # Example
7//!
8//! ```rust
9//! use assertables::*;
10//! use regex::Regex;
11//!
12//! let a = Regex::new(r"lf").expect("regex");
13//! let b = "alfa";
14//! assert_is_match!(a, b);
15//! ```
16//!
17//! # Module macros
18//!
19//! * [`assert_is_match`](macro@crate::assert_is_match)
20//! * [`assert_is_match_as_result`](macro@crate::assert_is_match_as_result)
21//! * [`debug_assert_is_match`](macro@crate::debug_assert_is_match)
22
23/// Assert an expression (such as a regex) is a match for an expression (such as a string).
24///
25/// Pseudocode:<br>
26/// a.is_match(b)
27///
28/// * If true, return Result `Ok(())`.
29///
30/// * Otherwise, return Result `Err(message)`.
31///
32/// This macro is useful for runtime checks, such as checking parameters,
33/// or sanitizing inputs, or handling different results in different ways.
34///
35/// # Module macros
36///
37/// * [`assert_is_match`](macro@crate::assert_is_match)
38/// * [`assert_is_match_as_result`](macro@crate::assert_is_match_as_result)
39/// * [`debug_assert_is_match`](macro@crate::debug_assert_is_match)
40///
41#[macro_export]
42macro_rules! assert_is_match_as_result {
43    ($matcher:expr, $matchee:expr $(,)?) => {{
44        match (&$matcher, &$matchee) {
45            (matcher, matchee) => {
46                if matcher.is_match(matchee) {
47                    Ok(())
48                } else {
49                    Err(
50                        format!(
51                            concat!(
52                                "assertion failed: `assert_is_match!(matcher, matchee)`\n",
53                                "https://docs.rs/assertables/9.5.0/assertables/macro.assert_is_match.html\n",
54                                " matcher label: `{}`,\n",
55                                " matcher debug: `{:?}`,\n",
56                                " matchee label: `{}`,\n",
57                                " matchee debug: `{:?}`",
58                            ),
59                            stringify!($matcher),
60                            matcher,
61                            stringify!($matchee),
62                            matchee,
63                        )
64                    )
65                }
66            }
67        }
68    }};
69}
70
71#[cfg(test)]
72mod test_assert_is_match_as_result {
73    use regex::Regex;
74
75    #[test]
76    fn success() {
77        let a = Regex::new(r"lf").expect("regex");
78        let b = "alfa";
79        let actual = assert_is_match_as_result!(a, b);
80        assert_eq!(actual.unwrap(), ());
81    }
82
83    #[test]
84    fn failure() {
85        let a = Regex::new(r"lf").expect("regex");
86        let b = "bravo";
87        let actual = assert_is_match_as_result!(a, b);
88        let message = concat!(
89            "assertion failed: `assert_is_match!(matcher, matchee)`\n",
90            "https://docs.rs/assertables/9.5.0/assertables/macro.assert_is_match.html\n",
91            " matcher label: `a`,\n",
92            " matcher debug: `Regex(\"lf\")`,\n",
93            " matchee label: `b`,\n",
94            " matchee debug: `\"bravo\"`"
95        );
96        assert_eq!(actual.unwrap_err(), message);
97    }
98}
99
100/// Assert a matcher is a match for an expression.
101///
102/// Pseudocode:<br>
103/// a.is_match(b)
104///
105/// * If true, return `()`.
106///
107/// * Otherwise, call [`panic!`] with a message and the values of the
108///   expressions with their debug representations.
109///
110/// # Examples
111///
112/// ```rust
113/// use assertables::*;
114/// # use std::panic;
115/// use regex::Regex;
116///
117/// # fn main() {
118/// let a = Regex::new(r"lf").expect("regex");
119/// let b = "alfa";
120/// assert_is_match!(a, b);
121///
122/// # let result = panic::catch_unwind(|| {
123/// // This will panic
124/// let a = Regex::new(r"lf").expect("regex");
125/// let b = "bravo";
126/// assert_is_match!(a, b);
127/// # });
128/// // assertion failed: `assert_is_match!(matcher, matchee)`
129/// // https://docs.rs/assertables/9.5.0/assertables/macro.assert_is_match.html
130/// //  matcher label: `a`,
131/// //  matcher debug: `Regex(\"lf\")`,
132/// //  matchee label: `b`,
133/// //  matchee debug: `\"bravo\"`
134/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
135/// # let message = concat!(
136/// #     "assertion failed: `assert_is_match!(matcher, matchee)`\n",
137/// #     "https://docs.rs/assertables/9.5.0/assertables/macro.assert_is_match.html\n",
138/// #     " matcher label: `a`,\n",
139/// #     " matcher debug: `Regex(\"lf\")`,\n",
140/// #     " matchee label: `b`,\n",
141/// #     " matchee debug: `\"bravo\"`"
142/// # );
143/// # assert_eq!(actual, message);
144/// # }
145/// ```
146///
147/// # Module macros
148///
149/// * [`assert_is_match`](macro@crate::assert_is_match)
150/// * [`assert_is_match_as_result`](macro@crate::assert_is_match_as_result)
151/// * [`debug_assert_is_match`](macro@crate::debug_assert_is_match)
152///
153#[macro_export]
154macro_rules! assert_is_match {
155    ($matcher:expr, $matchee:expr $(,)?) => {{
156        match $crate::assert_is_match_as_result!($matcher, $matchee) {
157            Ok(()) => (),
158            Err(err) => panic!("{}", err),
159        }
160    }};
161    ($matcher:expr, $matchee:expr, $($message:tt)+) => {{
162        match $crate::assert_is_match_as_result!($matcher, $matchee) {
163            Ok(()) => (),
164            Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
165        }
166    }};
167}
168
169#[cfg(test)]
170mod test_assert_is_match {
171    use regex::Regex;
172    use std::panic;
173
174    #[test]
175    fn success() {
176        let a = Regex::new(r"lf").expect("regex");
177        let b = "alfa";
178        let actual = assert_is_match!(a, b);
179        assert_eq!(actual, ());
180    }
181
182    #[test]
183    fn failure() {
184        let result = panic::catch_unwind(|| {
185            let a = Regex::new(r"lf").expect("regex");
186            let b = "bravo";
187            let _actual = assert_is_match!(a, b);
188        });
189        let message = concat!(
190            "assertion failed: `assert_is_match!(matcher, matchee)`\n",
191            "https://docs.rs/assertables/9.5.0/assertables/macro.assert_is_match.html\n",
192            " matcher label: `a`,\n",
193            " matcher debug: `Regex(\"lf\")`,\n",
194            " matchee label: `b`,\n",
195            " matchee debug: `\"bravo\"`"
196        );
197        assert_eq!(
198            result
199                .unwrap_err()
200                .downcast::<String>()
201                .unwrap()
202                .to_string(),
203            message
204        );
205    }
206}
207
208/// Assert a matcher is a match for an expression.
209///
210/// Pseudocode:<br>
211/// a.is_match(b)
212///
213/// This macro provides the same statements as [`assert_is_match`](macro.assert_is_match.html),
214/// except this macro's statements are only enabled in non-optimized
215/// builds by default. An optimized build will not execute this macro's
216/// statements unless `-C debug-assertions` is passed to the compiler.
217///
218/// This macro is useful for checks that are too expensive to be present
219/// in a release build but may be helpful during development.
220///
221/// The result of expanding this macro is always type checked.
222///
223/// An unchecked assertion allows a program in an inconsistent state to
224/// keep running, which might have unexpected consequences but does not
225/// introduce unsafety as long as this only happens in safe code. The
226/// performance cost of assertions, however, is not measurable in general.
227/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
228/// after thorough profiling, and more importantly, only in safe code!
229///
230/// This macro is intended to work in a similar way to
231/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
232///
233/// # Module macros
234///
235/// * [`assert_is_match`](macro@crate::assert_is_match)
236/// * [`assert_is_match`](macro@crate::assert_is_match)
237/// * [`debug_assert_is_match`](macro@crate::debug_assert_is_match)
238///
239#[macro_export]
240macro_rules! debug_assert_is_match {
241    ($($arg:tt)*) => {
242        if $crate::cfg!(debug_assertions) {
243            $crate::assert_is_match!($($arg)*);
244        }
245    };
246}