assertables/assert_count/
assert_count_eq_x.rs

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