test_helpers/assertions.rs
1// assertions.rs : test_help-rs
2
3// Assertion macros
4
5/// Asserts that two scalar values are approximately equal.
6///
7/// # Forms
8///
9/// * `assert_scalar_eq_approx!(expected, actual)` — uses the stock
10/// [`crate::zero_margin_or_multiplier`] evaluator
11/// ([`crate::constants::DEFAULT_MULTIPLIER`] /
12/// [`crate::constants::DEFAULT_MARGIN`]);
13/// * `assert_scalar_eq_approx!(expected, actual, evaluator)` — custom
14/// [`crate::traits::ApproximateEqualityEvaluator`];
15///
16/// Operands must implement [`crate::traits::TestableAsF64`].
17///
18/// # Examples
19///
20/// ```
21/// use test_helpers::{assert_scalar_eq_approx, margin};
22///
23/// assert_scalar_eq_approx!(3.0, 3.0001, margin(0.0001));
24/// ```
25///
26/// # Panics
27///
28/// Panics when the evaluator reports [`crate::ComparisonResult::Unequal`].
29#[macro_export]
30macro_rules! assert_scalar_eq_approx {
31 ($expected:expr, $actual:expr, $evaluator:expr) => {
32 let expected_param = &$expected;
33 let actual_param = &$actual;
34
35 let (expected, actual) = {
36 let expected : &dyn $crate::traits::TestableAsF64 = expected_param;
37 let actual : &dyn $crate::traits::TestableAsF64 = actual_param;
38
39 let expected = expected.testable_as_f64();
40 let actual = actual.testable_as_f64();
41
42 (expected, actual)
43 };
44 let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
45
46 // scope to protect against multiple `use`s of crate type(s)
47 {
48 use $crate::ComparisonResult as CR;
49
50 let (comparison_result, margin_factor, multiplier_factor) = evaluator.evaluate(expected, actual);
51
52 match comparison_result {
53 CR::ExactlyEqual | CR::ApproximatelyEqual => (),
54 CR::Unequal => {
55 match margin_factor {
56 Some(margin_factor) => {
57 match multiplier_factor {
58 Some(multiplier_factor) => {
59 assert!(
60 false,
61 "assertion failed: failed to verify approximate equality: expected={expected_param:?}, actual={actual_param:?}, margin_factor={margin_factor}, multiplier_factor={multiplier_factor}",
62 );
63 },
64 None => {
65 assert!(
66 false,
67 "assertion failed: failed to verify approximate equality: expected={expected_param:?}, actual={actual_param:?}, margin_factor={margin_factor}",
68 );
69 },
70 };
71 },
72 None => {
73 match multiplier_factor {
74 Some(multiplier_factor) => {
75 assert!(
76 false,
77 "assertion failed: failed to verify approximate equality: expected={expected_param:?}, actual={actual_param:?}, multiplier_factor={multiplier_factor}",
78 );
79 },
80 None => {
81 panic!("VIOLATION: This should not occur, and may only result from an improperly written implementor of `ApproximateEqualityEvaluator`");
82 }
83 };
84 },
85 };
86 },
87 };
88 }
89 };
90 ($expected:expr, $actual:expr) => {
91 let evaluator = $crate::zero_margin_or_multiplier($crate::constants::DEFAULT_MULTIPLIER, $crate::constants::DEFAULT_MARGIN);
92
93 assert_scalar_eq_approx!($expected, $actual, evaluator);
94 };
95}
96
97/// Asserts that two scalar values are not approximately equal.
98///
99/// # Forms
100///
101/// * `assert_scalar_ne_approx!(expected, actual)` — uses the stock
102/// [`crate::zero_margin_or_multiplier`] evaluator
103/// ([`crate::constants::DEFAULT_MULTIPLIER`] /
104/// [`crate::constants::DEFAULT_MARGIN`]);
105/// * `assert_scalar_ne_approx!(expected, actual, evaluator)` — custom
106/// [`crate::traits::ApproximateEqualityEvaluator`];
107///
108/// Operands must implement [`crate::traits::TestableAsF64`].
109///
110/// # Examples
111///
112/// ```
113/// use test_helpers::{assert_scalar_ne_approx, margin};
114///
115/// assert_scalar_ne_approx!(3.0, 4.0, margin(0.0001));
116/// ```
117///
118/// # Panics
119///
120/// Panics when the evaluator reports
121/// [`crate::ComparisonResult::ExactlyEqual`] or
122/// [`crate::ComparisonResult::ApproximatelyEqual`].
123#[macro_export]
124macro_rules! assert_scalar_ne_approx {
125 ($expected:expr, $actual:expr, $evaluator:expr) => {
126 let expected_param = &$expected;
127 let actual_param = &$actual;
128
129 let (expected, actual) = {
130 let expected : &dyn $crate::traits::TestableAsF64 = expected_param;
131 let actual : &dyn $crate::traits::TestableAsF64 = actual_param;
132
133 let expected = expected.testable_as_f64();
134 let actual = actual.testable_as_f64();
135
136 (expected, actual)
137 };
138 let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
139
140 // scope to protect against multiple `use`s of crate type(s)
141 {
142 use $crate::ComparisonResult as CR;
143
144 let (comparison_result, margin_factor, multiplier_factor) = evaluator.evaluate(expected, actual);
145
146 match comparison_result {
147 CR::Unequal => (),
148 CR::ExactlyEqual | CR::ApproximatelyEqual => {
149 match margin_factor {
150 Some(margin_factor) => {
151 match multiplier_factor {
152 Some(multiplier_factor) => {
153 assert!(
154 false,
155 "assertion failed: failed to verify approximate inequality: expected={expected_param:?}, actual={actual_param:?}, margin_factor={margin_factor}, multiplier_factor={multiplier_factor}",
156 );
157 },
158 None => {
159 assert!(
160 false,
161 "assertion failed: failed to verify approximate inequality: expected={expected_param:?}, actual={actual_param:?}, margin_factor={margin_factor}",
162 );
163 },
164 };
165 },
166 None => {
167 match multiplier_factor {
168 Some(multiplier_factor) => {
169 assert!(
170 false,
171 "assertion failed: failed to verify approximate inequality: expected={expected_param:?}, actual={actual_param:?}, multiplier_factor={multiplier_factor}",
172 );
173 },
174 None => {
175 panic!("VIOLATION: This should not occur, and may only result from an improperly written implementor of `ApproximateEqualityEvaluator`");
176 }
177 };
178 }
179 };
180 },
181 };
182 }
183 };
184 ($expected:expr, $actual:expr) => {
185 let evaluator = $crate::zero_margin_or_multiplier($crate::constants::DEFAULT_MULTIPLIER, $crate::constants::DEFAULT_MARGIN);
186
187 assert_scalar_ne_approx!($expected, $actual, evaluator);
188 };
189}
190
191/// Asserts that two vectors are approximately equal element-wise.
192///
193/// # Forms
194///
195/// * `assert_vector_eq_approx!(expected, actual)` — uses the stock
196/// [`crate::zero_margin_or_multiplier`] evaluator
197/// ([`crate::constants::DEFAULT_MULTIPLIER`] /
198/// [`crate::constants::DEFAULT_MARGIN`]);
199/// * `assert_vector_eq_approx!(expected, actual, evaluator)` — custom
200/// [`crate::traits::ApproximateEqualityEvaluator`];
201///
202/// `expected` and `actual` may be slices, arrays, or [`Vec`]; element
203/// types must implement [`crate::traits::TestableAsF64`].
204///
205/// # Examples
206///
207/// ```
208/// use test_helpers::{assert_vector_eq_approx, multiplier};
209///
210/// let expected = &[3.0, -40404.0, 1.23456];
211/// let actual = vec![3.0, -40410.0, 1.234567];
212/// assert_vector_eq_approx!(expected, actual, multiplier(0.00015));
213/// ```
214///
215/// # Panics
216///
217/// Panics when lengths differ
218/// ([`crate::VectorComparisonResult::DifferentLengths`]), or when any
219/// element pair is unequal under the evaluator
220/// ([`crate::VectorComparisonResult::UnequalElements`]).
221#[macro_export]
222macro_rules! assert_vector_eq_approx {
223 ($expected:expr, $actual:expr, $evaluator:expr) => {
224 /*
225 let expected_param = &$expected;
226 let actual_param = &$actual;
227 */
228 let expected = &$expected;
229 let actual = &$actual;
230 let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
231
232 // scope to protect against multiple `use`s of crate type(s)
233 {
234 use $crate::VectorComparisonResult as CR;
235
236 let (comparison_result, margin_factor, multiplier_factor) = $crate::evaluate_vector_eq_approx(&expected, &actual, evaluator);
237
238 match comparison_result {
239 CR::ExactlyEqual | CR::ApproximatelyEqual => (),
240 CR::DifferentLengths {
241 expected_length,
242 actual_length,
243 } => {
244 assert!(
245 false,
246 "assertion failed: failed to verify approximate equality for vectors: expected-length {expected_length} differs from actual-length {actual_length}",
247 );
248 },
249 CR::UnequalElements {
250 index_of_first_unequal_element,
251 expected_value_of_first_unequal_element,
252 actual_value_of_first_unequal_element,
253 } => {
254 match margin_factor {
255 Some(margin_factor) => {
256 match multiplier_factor {
257 Some(multiplier_factor) => {
258 assert!(
259 false,
260 "assertion failed: failed to verify approximate equality for vectors: at index {index_of_first_unequal_element} expected={expected_value_of_first_unequal_element:?}, actual={actual_value_of_first_unequal_element:?}, margin_factor={margin_factor}, multiplier_factor={multiplier_factor}",
261 );
262 },
263 None => {
264 assert!(
265 false,
266 "assertion failed: failed to verify approximate equality for vectors: at index {index_of_first_unequal_element} expected={expected_value_of_first_unequal_element:?}, actual={actual_value_of_first_unequal_element:?}, margin_factor={margin_factor}",
267 );
268 },
269 };
270 },
271 None => {
272 match multiplier_factor {
273 Some(multiplier_factor) => {
274 assert!(
275 false,
276 "assertion failed: failed to verify approximate equality for vectors: at index {index_of_first_unequal_element} expected={expected_value_of_first_unequal_element:?}, actual={actual_value_of_first_unequal_element:?}, multiplier_factor={multiplier_factor}",
277 );
278 },
279 None => {
280 panic!("VIOLATION: This should not occur, and may only result from an improperly written implementor of `ApproximateEqualityEvaluator`");
281 }
282 };
283 },
284 };
285 },
286 };
287 }
288 };
289 ($expected:expr, $actual:expr) => {
290 let evaluator = $crate::zero_margin_or_multiplier($crate::constants::DEFAULT_MULTIPLIER, $crate::constants::DEFAULT_MARGIN);
291
292 assert_vector_eq_approx!($expected, $actual, evaluator);
293 };
294}
295
296/// Asserts that two vectors are not approximately equal.
297///
298/// # Forms
299///
300/// * `assert_vector_ne_approx!(expected, actual)` — uses the stock
301/// [`crate::zero_margin_or_multiplier`] evaluator
302/// ([`crate::constants::DEFAULT_MULTIPLIER`] /
303/// [`crate::constants::DEFAULT_MARGIN`]);
304/// * `assert_vector_ne_approx!(expected, actual, evaluator)` — custom
305/// [`crate::traits::ApproximateEqualityEvaluator`];
306///
307/// `expected` and `actual` may be slices, arrays, or [`Vec`]; element
308/// types must implement [`crate::traits::TestableAsF64`].
309///
310/// # Examples
311///
312/// ```
313/// use test_helpers::{assert_vector_ne_approx, multiplier};
314///
315/// let expected = &[1.0, 2.0];
316/// let actual = vec![1.0, 9.0];
317/// assert_vector_ne_approx!(expected, actual, multiplier(0.00015));
318/// ```
319///
320/// # Panics
321///
322/// Panics when lengths match and every element pair is equal under the
323/// evaluator ([`crate::VectorComparisonResult::ExactlyEqual`] or
324/// [`crate::VectorComparisonResult::ApproximatelyEqual`]).
325#[macro_export]
326macro_rules! assert_vector_ne_approx {
327 ($expected:expr, $actual:expr, $evaluator:expr) => {
328 /*
329 let expected_param = &$expected;
330 let actual_param = &$actual;
331 */
332 let expected = &$expected;
333 let actual = &$actual;
334 let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
335
336 // scope to protect against multiple `use`s of crate type(s)
337 {
338 use $crate::VectorComparisonResult as CR;
339
340 let (comparison_result, margin_factor, multiplier_factor) = $crate::evaluate_vector_eq_approx(&expected, &actual, evaluator);
341
342 match comparison_result {
343 CR::DifferentLengths { ..} | CR::UnequalElements {..} => (),
344 CR::ExactlyEqual | CR::ApproximatelyEqual => {
345 match margin_factor {
346 Some(margin_factor) => {
347 match multiplier_factor {
348 Some(multiplier_factor) => {
349 assert!(
350 false,
351 "assertion failed: failed to verify approximate inequality for vectors; margin_factor={margin_factor}, multiplier_factor={multiplier_factor}",
352 );
353 },
354 None => {
355 assert!(
356 false,
357 "assertion failed: failed to verify approximate inequality for vectors; margin_factor={margin_factor}",
358 );
359 },
360 };
361 },
362 None => {
363 match multiplier_factor {
364 Some(multiplier_factor) => {
365 assert!(
366 false,
367 "assertion failed: failed to verify approximate inequality for vectors; multiplier_factor={multiplier_factor}",
368 );
369 },
370 None => {
371 assert!(
372 false,
373 "assertion failed: failed to verify approximate inequality for vectors",
374 );
375 }
376 };
377 }
378 };
379 },
380 };
381 }
382 };
383 ($expected:expr, $actual:expr) => {
384 let evaluator =
385 $crate::zero_margin_or_multiplier($crate::constants::DEFAULT_MULTIPLIER, $crate::constants::DEFAULT_MARGIN);
386
387 assert_vector_ne_approx!($expected, $actual, evaluator);
388 };
389}
390
391// ///////////////////////////// end of file //////////////////////////// //