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