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