assertables/assert_success/
assert_success.rs

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