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