assert_cmp/lib.rs
1//! Convenient assertion macros that print the failed expressions and their evaluated values.
2#![no_std]
3#![no_implicit_prelude]
4
5/// Create assertion macros for boolean binary operators.
6#[macro_export]
7macro_rules! operator_assertion_macros {
8 (
9 $(#![$shared_attr:meta])*
10 in $module:path;
11 use $assert:path;
12 $(#[$attr_simple:meta])* simple = $name_simple:ident;
13 $(#[$attr_expr:meta])* expr = $name_expr:ident;
14 ) => {
15 $(#[$shared_attr])*
16 $(#[$attr_expr])*
17 macro_rules! $name_expr {
18 ($left:expr, $op:tt, $right:expr) => {
19 match ($left, $right) {
20 (left, right) => {
21 $assert!(
22 left $op right,
23 "{left_expr} {op} {right_expr} ⇒ {left_value:?} {op} {right_value:?} ⇒ false",
24 op = stringify!($op),
25 left_expr = stringify!($left),
26 right_expr = stringify!($right),
27 left_value = left,
28 right_value = right,
29 )
30 }
31 }
32 };
33 }
34
35 $(#[$shared_attr])*
36 $(#[$attr_simple])*
37 macro_rules! $name_simple {
38 ($left:ident $op:tt $right:ident) => {
39 $module::$name_expr!($left, $op, $right)
40 };
41 ($left:ident $op:tt $right:literal) => {
42 $module::$name_expr!($left, $op, $right)
43 };
44 ($left:literal $op:tt $right:ident) => {
45 $module::$name_expr!($left, $op, $right)
46 };
47 ($left:literal $op:tt $right:literal) => {
48 $module::$name_expr!($left, $op, $right)
49 };
50 }
51 };
52}
53
54/// Create an assertion macro for boolean function calls.
55#[macro_export]
56macro_rules! function_assertion_macro {
57 (
58 $(#![$shared_attr:meta])*
59 use $assert:path;
60 $(#[$attr:meta])* $name:ident;
61 ) => {
62 $(#[$shared_attr])*
63 $(#[$attr])*
64 macro_rules! $name {
65 ($function:ident($left:expr, $right:expr)) => {
66 match ($left, $right) {
67 (left, right) => {
68 $assert!(
69 $function($left, $right),
70 "{func}({left_expr}, {right_expr}) ⇒ {func}({left_value:?}, {right_value:?}) ⇒ false",
71 func = stringify!($function),
72 left_expr = stringify!($left),
73 right_expr = stringify!($right),
74 left_value = left,
75 right_value = right,
76 )
77 }
78 }
79 };
80
81 (not $function:ident($left:expr, $right:expr)) => {
82 match ($left, $right) {
83 (left, right) => {
84 $assert!(
85 !$function($left, $right),
86 "{func}({left_expr}, {right_expr}) ⇒ {func}({left_value}, {right_value}) ⇒ true",
87 func = stringify!($function),
88 left_expr = stringify!($left),
89 right_expr = stringify!($right),
90 left_value = left,
91 right_value = right,
92 )
93 }
94 }
95 };
96 }
97 };
98}
99
100operator_assertion_macros! {
101 #![macro_export]
102 in ::assert_cmp;
103 use ::core::assert;
104
105 /// Assert that a binary expression of 2 identifiers/literals returns `true`.
106 ///
107 /// **Syntax:**
108 ///
109 /// ```ignore
110 /// assert_op!($left $op $right)
111 /// ```
112 ///
113 /// * `$left` and `$right` are either identifiers or literals or both.
114 /// * `$op` is a binary operator (e.g. `>`, `<`, `>=`, `<=`, `==`, `!=`).
115 ///
116 /// **Example:** An assertion that passes
117 ///
118 /// ```
119 /// # use assert_cmp::assert_op;
120 /// assert_op!(123 < 456);
121 /// ```
122 ///
123 /// **Example:** An assertion that fails
124 ///
125 /// ```should_panic
126 /// # use assert_cmp::assert_op;
127 /// assert_op!(123 > 456); // panic: 123 > 456 ⇒ 123 > 456 ⇒ false
128 /// ```
129 simple = assert_op;
130
131 /// Assert that a binary expression of 2 expressions returns `true`.
132 ///
133 /// **Syntax:**
134 ///
135 /// ```ignore
136 /// assert_op_expr!($left, $op, $right)
137 /// ```
138 ///
139 /// * `$left` and `$right` are expressions.
140 /// * `$op` is a binary operator (e.g. `>`, `<`, `>=`, `<=`, `==`, `!=`).
141 ///
142 /// **Example:** An assertion that passes
143 ///
144 /// ```
145 /// # use assert_cmp::assert_op_expr;
146 /// assert_op_expr!(12 + 34, ==, 34 + 12);
147 /// ```
148 ///
149 /// **Example:** An assertion that fails
150 ///
151 /// ```should_panic
152 /// # use assert_cmp::assert_op_expr;
153 /// assert_op_expr!(12 + 34, ==, 43 + 21); // panic: 12 + 34 == 43 + 21 ⇒ 46 == 64 ⇒ false
154 /// ```
155 expr = assert_op_expr;
156}
157
158operator_assertion_macros! {
159 #![macro_export]
160 in ::assert_cmp;
161 use ::core::debug_assert;
162
163 /// Assert that a binary expression of 2 identifiers/literals returns `true`.
164 ///
165 /// This macro is the debug-only version of [`assert_op`].
166 /// It acts like `assert_op` in debug mode, but does nothing in release mode.
167 simple = debug_assert_op;
168
169 /// Assert that a binary expression of 2 expressions returns `true`.
170 ///
171 /// This macro is the debug-only version of [`assert_op`].
172 /// It acts like `assert_op_expr` in debug mode, but does nothing in release mode.
173 expr = debug_assert_op_expr;
174}
175
176function_assertion_macro! {
177 #![macro_export]
178 use ::core::assert;
179
180 /// Assert that a binary function call of 2 expressions returns `true`.
181 ///
182 /// **Syntax:**
183 ///
184 /// ```ignore
185 /// assert_fn!($function($left, $right))
186 /// ```
187 ///
188 /// ```ignore
189 /// assert_fn!(not $function($left, $right))
190 /// ```
191 ///
192 /// * `$function` is an identifier of a binary function.
193 /// * `$left` and `$right` are expressions.
194 /// * `not`'s appearance means expecting the function call to returns `false` instead of `true`.
195 ///
196 /// **Example:** An assertion that passes
197 ///
198 /// ```
199 /// # use assert_cmp::assert_fn;
200 /// fn func<A, B>(_: A, _: B) -> bool {
201 /// true
202 /// }
203 /// assert_fn!(func(123, 456));
204 /// ```
205 ///
206 /// **Example:** An assertion that fails
207 ///
208 /// ```should_panic
209 /// # use assert_cmp::assert_fn;
210 /// fn func<A, B>(_: A, _: B) -> bool {
211 /// false
212 /// }
213 /// assert_fn!(func(123, 456)); // panic: func(123, 456) ⇒ func(123, 456) ⇒ false
214 /// ```
215 ///
216 /// **Example:** A negative assertion that passes
217 ///
218 /// ```
219 /// # use assert_cmp::assert_fn;
220 /// fn func<A, B>(_: A, _: B) -> bool {
221 /// false
222 /// }
223 /// assert_fn!(not func(123, 456));
224 /// ```
225 ///
226 /// **Example:** A negative assertion that fails
227 ///
228 /// ```should_panic
229 /// # use assert_cmp::assert_fn;
230 /// fn func<A, B>(_: A, _: B) -> bool {
231 /// true
232 /// }
233 /// assert_fn!(not func(123, 456)); // panic: func(123, 456) ⇒ func(123, 456) ⇒ true
234 /// ```
235 assert_fn;
236}
237
238function_assertion_macro! {
239 #![macro_export]
240 use ::core::debug_assert;
241
242 /// Assert that a binary function call of 2 expressions returns `true`.
243 ///
244 /// This macro is the debug-only version of [`assert_fn`].
245 /// It acts like `assert_op_expr` in debug mode, but does nothing in release mode.
246 debug_assert_fn;
247}