1#[macro_export(local_inner_macros)]
14macro_rules! assert_that {
15 ($lhs:expr, eq $rhs:expr) => {
16 {
17 let lval = &$lhs;
18 let rval = &$rhs;
19
20 if !(lval == rval) {
21 assert_that!(message $lhs, $rhs, lval, rval, "==");
22 }
23 }
24 };
25 ($lhs:expr, ne $rhs:expr) => {
26 {
27 let lval = &$lhs;
28 let rval = &$rhs;
29
30 if !(lval != rval) {
31 assert_that!(message $lhs, $rhs, lval, rval, "!=");
32 }
33 }
34 };
35 ($lhs:expr, lt $rhs:expr) => {
36 {
37 let lval = &$lhs;
38 let rval = &$rhs;
39
40 if !(lval < rval) {
41 assert_that!(message $lhs, $rhs, lval, rval, "<");
42 }
43 }
44 };
45 ($lhs:expr, le $rhs:expr) => {
46 {
47 let lval = &$lhs;
48 let rval = &$rhs;
49
50 if !(lval <= rval) {
51 assert_that!(message $lhs, $rhs, lval, rval, "<=");
52 }
53 }
54 };
55 ($lhs:expr, gt $rhs:expr) => {
56 {
57 let lval = &$lhs;
58 let rval = &$rhs;
59
60 if !(lval > rval) {
61 assert_that!(message $lhs, $rhs, lval, rval, ">");
62 }
63 }
64 };
65 ($lhs:expr, ge $rhs:expr) => {
66 {
67 let lval = &$lhs;
68 let rval = &$rhs;
69
70 if !(lval >= rval) {
71 assert_that!(message $lhs, $rhs, lval, rval, ">=");
72 }
73 }
74 };
75 ($call:expr, eq $rhs:expr, before $guard:expr) => {
76 $crate::spin_until(|| $call() == $rhs, $guard);
77 };
78 ($call:expr, ne $rhs:expr, before $guard:expr) => {
79 $crate::spin_until(|| $call() != $rhs, $guard);
80 };
81 ($call:expr, lt $rhs:expr, before $guard:expr) => {
82 $crate::spin_until(|| $call() < $rhs, $guard);
83 };
84 ($call:expr, le $rhs:expr, before $guard:expr) => {
85 $crate::spin_until(|| $call() <= $rhs, $guard);
86 };
87 ($call:expr, gt $rhs:expr, before $guard:expr) => {
88 $crate::spin_until(|| $call() > $rhs, $guard);
89 };
90 ($call:expr, ge $rhs:expr, before $guard:expr) => {
91 $crate::spin_until(|| $call() >= $rhs, $guard);
92 };
93 ($lhs:expr, aligned_to $rhs:expr) => {
94 {
95 let lval = $lhs as usize;
96 let rval = $rhs as usize;
97 let act_result = lval % rval;
98
99 if !(act_result == 0) {
100 assert_that!(message $lhs, $rhs, lval, rval, "aligned to");
101 }
102 }
103 };
104 ($lhs:expr, mod $rhs:expr, is $result:expr) => {
105 {
106 let lval = &$lhs;
107 let rval = &$rhs;
108 let act_result = lval % rval;
109
110 if !(act_result == $result) {
111 assert_that!(message $lhs, $rhs, lval, rval, "%", $result, act_result);
112 }
113 }
114 };
115 ($lhs:expr, is_ok) => {
116 {
117 let lval = $lhs.is_ok();
118
119 if !lval {
120 assert_that!(message_result $lhs, "is_ok()");
121 }
122 }
123 };
124 ($lhs:expr, is_err) => {
125 {
126 let lval = $lhs.is_err();
127
128 if !lval {
129 assert_that!(message_result $lhs, "is_err()");
130 }
131 }
132 };
133 ($lhs:expr, is_some) => {
134 {
135 let lval = $lhs.is_some();
136
137 if !lval {
138 assert_that!(message_result $lhs, "is_some()");
139 }
140 }
141 };
142 ($lhs:expr, is_none) => {
143 {
144 let lval = $lhs.is_none();
145
146 if !lval {
147 assert_that!(message_result $lhs, "is_none()");
148 }
149 }
150 };
151 ($lhs:expr, is_empty) => {
152 {
153 let lval = $lhs.is_empty();
154
155 if !lval {
156 assert_that!(message_result $lhs, "is_empty()");
157 }
158 }
159 };
160 ($lhs:expr, is_not_empty) => {
161 {
162 let lval = !$lhs.is_empty();
163
164 if !lval {
165 assert_that!(message_result $lhs, "is_empty() (not)");
166 }
167 }
168 };
169 ($lhs:expr, len $rhs:expr) => {
170 {
171 let lval = $lhs.len();
172 if !(lval == $rhs) {
173 assert_that!(message_property $lhs, lval, "len()", $rhs);
174 }
175 }
176 };
177 ($lhs:expr, any_of $rhs:expr) => {
178 {
179 let mut found = false;
180 for value in &$rhs {
181 if *value == $lhs {
182 found = true;
183 break;
184 }
185 }
186 if !found {
187 assert_that!(message_any_of $lhs, $rhs);
188 }
189 }
190 };
191 ($lhs:expr, contains $rhs:expr) => {
192 {
193 let mut does_contain = false;
194 for value in &$lhs {
195 if *value == $rhs {
196 does_contain = true;
197 break;
198 }
199 }
200 if !does_contain {
201 assert_that!(message_contains $lhs, $rhs);
202 }
203 }
204 };
205 ($lhs:expr, excludes $rhs:expr) => {
206 {
207 let mut does_contain = false;
208 for value in &$lhs {
209 if *value == $rhs {
210 does_contain = true;
211 break;
212 }
213 }
214 if does_contain {
215 assert_that!(message_excludes $lhs, $rhs);
216 }
217 }
218 };
219 ($lhs:expr, contains_match |$element:ident| $predicate:expr) => {
220 {
221 let mut does_contain = false;
222 for $element in &$lhs {
223 if $predicate {
224 does_contain = true;
225 break;
226 }
227 }
228 if !does_contain {
229 assert_that!(message_contains_match $lhs, core::stringify!($predicate));
230 }
231 }
232 };
233 ($lhs:expr, not_contains_match |$element:ident| $predicate:expr) => {
234 {
235 let mut does_contain = false;
236 for $element in &$lhs {
237 if $predicate {
238 does_contain = true;
239 break;
240 }
241 }
242 if does_contain {
243 assert_that!(message_not_contains_match $lhs, core::stringify!($predicate));
244 }
245 }
246 };
247 ($lhs:expr, time_at_least $rhs:expr) => {
248 {
249 let lval = $lhs.as_secs_f32();
250 let rval = $rhs.as_secs_f32();
251 let rval_adjusted = rval * (1.0 - $crate::AT_LEAST_TIMING_VARIANCE).clamp(0.0, 1.0);
252
253 if !(lval >= rval_adjusted) {
254 assert_that!(message_time_at_least $lhs, $rhs, lval, rval, rval_adjusted);
255 }
256 }
257 };
258 [color_start] => {
259 {
260 if $crate::is_terminal() {
261 "\x1b[1;4;33m"
262 } else {
263 ""
264 }
265 }
266 };
267 [color_end] => {
268 {
269 if $crate::is_terminal() {
270 "\x1b[0m"
271 } else {
272 ""
273 }
274 }
275 };
276 [message_any_of $lhs:expr, $rhs:expr] => {
277 core::panic!(
278 "assertion failed: {}expr: {} any_of {} ({:?}); contents: {:?}{}",
279 assert_that![color_start],
280 core::stringify!($lhs),
281 core::stringify!($rhs),
282 $rhs,
283 $lhs,
284 assert_that![color_end]
285 );
286 };
287 [message_contains $lhs:expr, $rhs:expr] => {
288 core::panic!(
289 "assertion failed: {}expr: {} contains {} ({:?}); contents: {:?}{}",
290 assert_that![color_start],
291 core::stringify!($lhs),
292 core::stringify!($rhs),
293 $rhs,
294 $lhs,
295 assert_that![color_end]
296 );
297 };
298 [message_excludes $lhs:expr, $rhs:expr] => {
299 core::panic!(
300 "assertion failed: {}expr: {} shall not contain {} ({:?}); contents: {:?}{}",
301 assert_that![color_start],
302 core::stringify!($lhs),
303 core::stringify!($rhs),
304 $rhs,
305 $lhs,
306 assert_that![color_end]
307 );
308 };
309 [message_contains_match $lhs:expr, $predicate:expr] => {
310 core::panic!(
311 "assertion failed: {}expr: {} contains no element matching predicate: {}{}",
312 assert_that![color_start],
313 core::stringify!($lhs),
314 $predicate,
315 assert_that![color_end]
316 );
317 };
318 [message_not_contains_match $lhs:expr, $predicate:expr] => {
319 core::panic!(
320 "assertion failed: {}expr: {} contains element matching predicate: {}{}",
321 assert_that![color_start],
322 core::stringify!($lhs),
323 $predicate,
324 assert_that![color_end]
325 );
326 };
327 [message_property $lhs:expr, $lval:expr, $property:expr, $rhs:expr] => {
328 core::panic!(
329 "assertion failed: {}expr: {}.{} == {}; value: {} == {}{}",
330 assert_that![color_start],
331 core::stringify!($lhs),
332 $property,
333 $rhs,
334 $lval,
335 $rhs,
336 assert_that![color_end]
337 );
338 };
339 [message_result $lhs:expr, $state:expr] => {
340 core::panic!(
341 "assertion failed: {}{}.{}{}",
342 assert_that![color_start],
343 core::stringify!($lhs),
344 $state,
345 assert_that![color_end]
346 );
347 };
348 [message_time_at_least $lhs:expr, $rhs:expr, $lval:expr, $rval:expr, $rval_adjusted:expr] => {
349 core::panic!(
350 "assertion failed: [ time test ] {}expr: {} at least {}; value: {:?} at least {:?} (jitter adjusted: {:?}){}",
351 assert_that![color_start],
352 core::stringify!($lhs),
353 core::stringify!($rhs),
354 $lval,
355 $rval,
356 $rval_adjusted,
357 assert_that![color_end]
358 );
359 };
360 [message $lhs:expr, $rhs:expr, $lval:expr, $rval:expr, $symbol:expr] => {
361 core::panic!(
362 "assertion failed: {}expr: {} {} {}; value: {:?} {} {:?}{}",
363 assert_that![color_start],
364 core::stringify!($lhs),
365 $symbol,
366 core::stringify!($rhs),
367 $lval,
368 $symbol,
369 $rval,
370 assert_that![color_end]
371 );
372 };
373 [message $lhs:expr, $rhs:expr, $lval:expr, $rval:expr, $symbol:expr, $exp_result:expr, $act_result:expr] => {
374 core::panic!(
375 "assertion failed: {}expr: {} {} {} == {:?}; value: {:?} {} {:?} == {:?}{}",
376 assert_that![color_start],
377 core::stringify!($lhs),
378 $symbol,
379 core::stringify!($rhs),
380 $exp_result,
381 $lval,
382 $symbol,
383 $rval,
384 $act_result,
385 assert_that![color_end]
386 );
387 }
388}