assertables/assert_ok/assert_ok_ne_x.rs
1//! Assert an expression is Ok and its value is not equal to an expression.
2//!
3//! Pseudocode:<br>
4//! (a ⇒ Ok(a1) ⇒ a1) ≠ b
5//!
6//! # Example
7//!
8//! ```rust
9//! use assertables::*;
10//!
11//! let a: Result<i8, i8> = Ok(1);
12//! let b: i8 = 2;
13//! assert_ok_ne_x!(a, b);
14//! ```
15//!
16//! # Module macros
17//!
18//! * [`assert_ok_ne_x`](macro@crate::assert_ok_ne_x)
19//! * [`assert_ok_ne_x_as_result`](macro@crate::assert_ok_ne_x_as_result)
20//! * [`debug_assert_ok_ne_x`](macro@crate::debug_assert_ok_ne_x)
21
22/// Assert an expression is Ok and its value is not equal to an expression.
23///
24/// Pseudocode:<br>
25/// (a ⇒ Ok(a1) ⇒ a1) = b
26///
27/// * If true, return Result `Ok((a1))`.
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_ok_ne_x`](macro@crate::assert_ok_ne_x)
37/// * [`assert_ok_ne_x_as_result`](macro@crate::assert_ok_ne_x_as_result)
38/// * [`debug_assert_ok_ne_x`](macro@crate::debug_assert_ok_ne_x)
39///
40#[macro_export]
41macro_rules! assert_ok_ne_x_as_result {
42 ($a:expr, $b:expr $(,)?) => {
43 match ($a, $b) {
44 (a, b) => match (a) {
45 Ok(a1) => {
46 if a1 != b {
47 Ok((a1))
48 } else {
49 Err(format!(
50 concat!(
51 "assertion failed: `assert_ok_ne_x!(a, b)`\n",
52 "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ok_ne_x.html\n",
53 " a label: `{}`,\n",
54 " a debug: `{:?}`,\n",
55 " a inner: `{:?}`,\n",
56 " b label: `{}`,\n",
57 " b debug: `{:?}`",
58 ),
59 stringify!($a),
60 a,
61 a1,
62 stringify!($b),
63 b
64 ))
65 }
66 }
67 _ => Err(format!(
68 concat!(
69 "assertion failed: `assert_ok_ne_x!(a, b)`\n",
70 "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ok_ne_x.html\n",
71 " a label: `{}`,\n",
72 " a debug: `{:?}`,\n",
73 " b label: `{}`,\n",
74 " b debug: `{:?}`",
75 ),
76 stringify!($a),
77 a,
78 stringify!($b),
79 b,
80 )),
81 },
82 }
83 };
84}
85
86#[cfg(test)]
87mod test_assert_ok_ne_x_as_result {
88 use std::sync::Once;
89
90 #[test]
91 fn lt() {
92 let a: Result<i8, i8> = Ok(1);
93 let b: i8 = 2;
94 for _ in 0..1 {
95 let actual = assert_ok_ne_x_as_result!(a, b);
96 assert_eq!(actual.unwrap(), 1);
97 }
98 }
99
100 #[test]
101 fn lt_once() {
102 static A: Once = Once::new();
103 fn a() -> Result<i8, i8> {
104 if A.is_completed() {
105 panic!("A.is_completed()")
106 } else {
107 A.call_once(|| {})
108 }
109 Ok(1)
110 }
111
112 static B: Once = Once::new();
113 fn b() -> i8 {
114 if B.is_completed() {
115 panic!("B.is_completed()")
116 } else {
117 B.call_once(|| {})
118 }
119 2
120 }
121
122 assert_eq!(A.is_completed(), false);
123 assert_eq!(B.is_completed(), false);
124 let result = assert_ok_ne_x_as_result!(a(), b());
125 assert!(result.is_ok());
126 assert_eq!(A.is_completed(), true);
127 assert_eq!(B.is_completed(), true);
128 }
129
130 #[test]
131 fn gt() {
132 let a: Result<i8, i8> = Ok(2);
133 let b: i8 = 1;
134 for _ in 0..1 {
135 let actual = assert_ok_ne_x_as_result!(a, b);
136 assert_eq!(actual.unwrap(), 2);
137 }
138 }
139
140 #[test]
141 fn gt_once() {
142 static A: Once = Once::new();
143 fn a() -> Result<i8, i8> {
144 if A.is_completed() {
145 panic!("A.is_completed()")
146 } else {
147 A.call_once(|| {})
148 }
149 Ok(2)
150 }
151
152 static B: Once = Once::new();
153 fn b() -> i8 {
154 if B.is_completed() {
155 panic!("B.is_completed()")
156 } else {
157 B.call_once(|| {})
158 }
159 1
160 }
161
162 assert_eq!(A.is_completed(), false);
163 assert_eq!(B.is_completed(), false);
164 let result = assert_ok_ne_x_as_result!(a(), b());
165 assert!(result.is_ok());
166 assert_eq!(A.is_completed(), true);
167 assert_eq!(B.is_completed(), true);
168 }
169
170 #[test]
171 fn eq() {
172 let a: Result<i8, i8> = Ok(1);
173 let b: i8 = 1;
174 let actual = assert_ok_ne_x_as_result!(a, b);
175 let message = concat!(
176 "assertion failed: `assert_ok_ne_x!(a, b)`\n",
177 "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ok_ne_x.html\n",
178 " a label: `a`,\n",
179 " a debug: `Ok(1)`,\n",
180 " a inner: `1`,\n",
181 " b label: `b`,\n",
182 " b debug: `1`",
183 );
184 assert_eq!(actual.unwrap_err(), message);
185 }
186
187 #[test]
188 fn not_ok() {
189 let a: Result<i8, i8> = Err(1);
190 let b: i8 = 2;
191 let actual = assert_ok_ne_x_as_result!(a, b);
192 let message = concat!(
193 "assertion failed: `assert_ok_ne_x!(a, b)`\n",
194 "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ok_ne_x.html\n",
195 " a label: `a`,\n",
196 " a debug: `Err(1)`,\n",
197 " b label: `b`,\n",
198 " b debug: `2`",
199 );
200 assert_eq!(actual.unwrap_err(), message);
201 }
202}
203
204/// Assert an expression is Ok and its value is not equal to an expression.
205///
206/// Pseudocode:<br>
207/// (a ⇒ Ok(a1) ⇒ a1) ≠ b
208///
209/// * If true, return `a1`.
210///
211/// * Otherwise, call [`panic!`] with a message and the values of the
212/// expressions with their debug representations.
213///
214/// # Examples
215///
216/// ```rust
217/// use assertables::*;
218/// # use std::panic;
219///
220/// # fn main() {
221/// let a: Result<i8, i8> = Ok(1);
222/// let b: i8 = 2;
223/// assert_ok_ne_x!(a, b);
224///
225/// # let result = panic::catch_unwind(|| {
226/// // This will panic
227/// let a: Result<i8, i8> = Ok(1);
228/// let b: i8 = 1;
229/// assert_ok_ne_x!(a, b);
230/// # });
231/// // assertion failed: `assert_ok_ne_x!(a, b)`
232/// // https://docs.rs/assertables/…/assertables/macro.assert_ok_ne_x.html
233/// // a label: `a`,
234/// // a debug: `Ok(1)`,
235/// // a inner: `1`,
236/// // b label: `b`,
237/// // b debug: `1`
238/// # let actual = result.unwrap_err().downcast::<String>().unwrap().to_string();
239/// # let message = concat!(
240/// # "assertion failed: `assert_ok_ne_x!(a, b)`\n",
241/// # "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ok_ne_x.html\n",
242/// # " a label: `a`,\n",
243/// # " a debug: `Ok(1)`,\n",
244/// # " a inner: `1`,\n",
245/// # " b label: `b`,\n",
246/// # " b debug: `1`",
247/// # );
248/// # assert_eq!(actual, message);
249/// # }
250/// ```
251///
252/// # Module macros
253///
254/// * [`assert_ok_ne_x`](macro@crate::assert_ok_ne_x)
255/// * [`assert_ok_ne_x_as_result`](macro@crate::assert_ok_ne_x_as_result)
256/// * [`debug_assert_ok_ne_x`](macro@crate::debug_assert_ok_ne_x)
257///
258#[macro_export]
259macro_rules! assert_ok_ne_x {
260 ($a:expr, $b:expr $(,)?) => {
261 match $crate::assert_ok_ne_x_as_result!($a, $b) {
262 Ok(x) => x,
263 Err(err) => panic!("{}", err),
264 }
265 };
266 ($a:expr, $b:expr, $($message:tt)+) => {
267 match $crate::assert_ok_ne_x_as_result!($a, $b) {
268 Ok(x) => x,
269 Err(err) => panic!("{}\n{}", format_args!($($message)+), err),
270 }
271 };
272}
273
274#[cfg(test)]
275mod test_assert_ok_ne_x {
276 use std::panic;
277
278 #[test]
279 fn ne() {
280 let a: Result<i8, i8> = Ok(1);
281 let b: i8 = 2;
282 for _ in 0..1 {
283 let actual = assert_ok_ne_x!(a, b);
284 assert_eq!(actual, 1);
285 }
286 }
287
288 #[test]
289 fn eq() {
290 let a: Result<i8, i8> = Ok(1);
291 let b: i8 = 1;
292 let result = panic::catch_unwind(|| {
293 let _actual = assert_ok_ne_x!(a, b);
294 });
295 let message = concat!(
296 "assertion failed: `assert_ok_ne_x!(a, b)`\n",
297 "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ok_ne_x.html\n",
298 " a label: `a`,\n",
299 " a debug: `Ok(1)`,\n",
300 " a inner: `1`,\n",
301 " b label: `b`,\n",
302 " b debug: `1`",
303 );
304 assert_eq!(
305 result
306 .unwrap_err()
307 .downcast::<String>()
308 .unwrap()
309 .to_string(),
310 message
311 );
312 }
313
314 #[test]
315 fn not_ok() {
316 let a: Result<i8, i8> = Err(1);
317 let b: i8 = 2;
318 let result = panic::catch_unwind(|| {
319 let _actual = assert_ok_ne_x!(a, b);
320 });
321 let message = concat!(
322 "assertion failed: `assert_ok_ne_x!(a, b)`\n",
323 "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ok_ne_x.html\n",
324 " a label: `a`,\n",
325 " a debug: `Err(1)`,\n",
326 " b label: `b`,\n",
327 " b debug: `2`",
328 );
329 assert_eq!(
330 result
331 .unwrap_err()
332 .downcast::<String>()
333 .unwrap()
334 .to_string(),
335 message
336 );
337 }
338}
339
340/// Assert an expression is Ok and its value is not equal to an expression.
341///
342/// Pseudocode:<br>
343/// (a ⇒ Ok(a1) ⇒ a1) ≠ b
344///
345/// This macro provides the same statements as [`assert_ok_ne_x`](macro.assert_ok_ne_x.html),
346/// except this macro's statements are only enabled in non-optimized
347/// builds by default. An optimized build will not execute this macro's
348/// statements unless `-C debug-assertions` is passed to the compiler.
349///
350/// This macro is useful for checks that are too expensive to be present
351/// in a release build but may be helpful during development.
352///
353/// The result of expanding this macro is always type checked.
354///
355/// An unchecked assertion allows a program in an inconsistent state to
356/// keep running, which might have unexpected consequences but does not
357/// introduce unsafety as long as this only happens in safe code. The
358/// performance cost of assertions, however, is not measurable in general.
359/// Replacing `assert*!` with `debug_assert*!` is thus only encouraged
360/// after thorough profiling, and more importantly, only in safe code!
361///
362/// This macro is intended to work in a similar way to
363/// [`::std::debug_assert`](https://doc.rust-lang.org/std/macro.debug_assert.html).
364///
365/// # Module macros
366///
367/// * [`assert_ok_ne_x`](macro@crate::assert_ok_ne_x)
368/// * [`assert_ok_ne_x`](macro@crate::assert_ok_ne_x)
369/// * [`debug_assert_ok_ne_x`](macro@crate::debug_assert_ok_ne_x)
370///
371#[macro_export]
372macro_rules! debug_assert_ok_ne_x {
373 ($($arg:tt)*) => {
374 if cfg!(debug_assertions) {
375 $crate::assert_ok_ne_x!($($arg)*);
376 }
377 };
378}
379
380#[cfg(test)]
381mod test_debug_assert_ok_ne_x {
382 use std::panic;
383
384 #[test]
385 fn ne() {
386 let a: Result<i8, i8> = Ok(1);
387 let b: i8 = 2;
388 for _ in 0..1 {
389 let _actual = debug_assert_ok_ne_x!(a, b);
390 // assert_eq!(actual, 1);
391 }
392 }
393
394 #[test]
395 fn eq() {
396 let a: Result<i8, i8> = Ok(1);
397 let b: i8 = 1;
398 let result = panic::catch_unwind(|| {
399 let _actual = debug_assert_ok_ne_x!(a, b);
400 });
401 let message = concat!(
402 "assertion failed: `assert_ok_ne_x!(a, b)`\n",
403 "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ok_ne_x.html\n",
404 " a label: `a`,\n",
405 " a debug: `Ok(1)`,\n",
406 " a inner: `1`,\n",
407 " b label: `b`,\n",
408 " b debug: `1`",
409 );
410 assert_eq!(
411 result
412 .unwrap_err()
413 .downcast::<String>()
414 .unwrap()
415 .to_string(),
416 message
417 );
418 }
419
420 #[test]
421 fn not_ok() {
422 let a: Result<i8, i8> = Err(1);
423 let b: i8 = 2;
424 let result = panic::catch_unwind(|| {
425 let _actual = debug_assert_ok_ne_x!(a, b);
426 });
427 let message = concat!(
428 "assertion failed: `assert_ok_ne_x!(a, b)`\n",
429 "https://docs.rs/assertables/9.8.6/assertables/macro.assert_ok_ne_x.html\n",
430 " a label: `a`,\n",
431 " a debug: `Err(1)`,\n",
432 " b label: `b`,\n",
433 " b debug: `2`",
434 );
435 assert_eq!(
436 result
437 .unwrap_err()
438 .downcast::<String>()
439 .unwrap()
440 .to_string(),
441 message
442 );
443 }
444}