test_helpers/macros.rs
1// macros.rs : test_help-rs
2
3// Macros
4
5/// Asserts that two scalar values are approximately equal.
6///
7/// # Forms
8///
9/// * `assert_scalar_eq_approx!(expected, actual)` — stock
10/// [`zero_margin_or_multiplier`] evaluator
11/// ([`constants::DEFAULT_MULTIPLIER`] /
12/// [`constants::DEFAULT_MARGIN`]);
13/// * `assert_scalar_eq_approx!(expected, actual, evaluator)` — custom
14/// [`traits::ApproximateEqualityEvaluator`];
15///
16/// Operands must implement [`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 [`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)` — stock
102/// [`zero_margin_or_multiplier`] evaluator;
103/// * `assert_scalar_ne_approx!(expected, actual, evaluator)` — custom
104/// [`traits::ApproximateEqualityEvaluator`];
105///
106/// Operands must implement [`traits::TestableAsF64`].
107///
108/// # Panics
109///
110/// Panics when the evaluator reports [`ComparisonResult::ExactlyEqual`]
111/// or [`ComparisonResult::ApproximatelyEqual`].
112#[macro_export]
113macro_rules! assert_scalar_ne_approx {
114 ($expected:expr, $actual:expr, $evaluator:expr) => {
115 let expected_param = &$expected;
116 let actual_param = &$actual;
117
118 let (expected, actual) = {
119 let expected : &dyn $crate::traits::TestableAsF64 = expected_param;
120 let actual : &dyn $crate::traits::TestableAsF64 = actual_param;
121
122 let expected = expected.testable_as_f64();
123 let actual = actual.testable_as_f64();
124
125 (expected, actual)
126 };
127 let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
128
129 // scope to protect against multiple `use`s of crate type(s)
130 {
131 use $crate::ComparisonResult as CR;
132
133 let (comparison_result, margin_factor, multiplier_factor) = evaluator.evaluate(expected, actual);
134
135 match comparison_result {
136 CR::Unequal => (),
137 CR::ExactlyEqual | CR::ApproximatelyEqual => {
138 match margin_factor {
139 Some(margin_factor) => {
140 match multiplier_factor {
141 Some(multiplier_factor) => {
142 assert!(
143 false,
144 "assertion failed: failed to verify approximate inequality: expected={expected_param:?}, actual={actual_param:?}, margin_factor={margin_factor}, multiplier_factor={multiplier_factor}",
145 );
146 },
147 None => {
148 assert!(
149 false,
150 "assertion failed: failed to verify approximate inequality: expected={expected_param:?}, actual={actual_param:?}, margin_factor={margin_factor}",
151 );
152 },
153 };
154 },
155 None => {
156 match multiplier_factor {
157 Some(multiplier_factor) => {
158 assert!(
159 false,
160 "assertion failed: failed to verify approximate inequality: expected={expected_param:?}, actual={actual_param:?}, multiplier_factor={multiplier_factor}",
161 );
162 },
163 None => {
164 panic!("VIOLATION: This should not occur, and may only result from an improperly written implementor of `ApproximateEqualityEvaluator`");
165 }
166 };
167 }
168 };
169 },
170 };
171 }
172 };
173 ($expected:expr, $actual:expr) => {
174 let evaluator = $crate::zero_margin_or_multiplier($crate::constants::DEFAULT_MULTIPLIER, $crate::constants::DEFAULT_MARGIN);
175
176 assert_scalar_ne_approx!($expected, $actual, evaluator);
177 };
178}
179
180/// Asserts that two vectors are approximately equal element-wise.
181///
182/// # Forms
183///
184/// * `assert_vector_eq_approx!(expected, actual)` — stock
185/// [`zero_margin_or_multiplier`] evaluator;
186/// * `assert_vector_eq_approx!(expected, actual, evaluator)` — custom
187/// [`traits::ApproximateEqualityEvaluator`];
188///
189/// `expected` and `actual` may be slices, arrays, or [`Vec`]; element
190/// types must implement [`traits::TestableAsF64`].
191///
192/// # Examples
193///
194/// ```
195/// use test_helpers::{assert_vector_eq_approx, multiplier};
196///
197/// let expected = &[3.0, -40404.0, 1.23456];
198/// let actual = vec![3.0, -40410.0, 1.234567];
199/// assert_vector_eq_approx!(expected, actual, multiplier(0.00015));
200/// ```
201///
202/// # Panics
203///
204/// Panics when lengths differ, when any element pair is unequal under the
205/// evaluator, or when [`VectorComparisonResult::UnequalElements`] applies.
206#[macro_export]
207macro_rules! assert_vector_eq_approx {
208 ($expected:expr, $actual:expr, $evaluator:expr) => {
209 /*
210 let expected_param = &$expected;
211 let actual_param = &$actual;
212 */
213 let expected = &$expected;
214 let actual = &$actual;
215 let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
216
217 // scope to protect against multiple `use`s of crate type(s)
218 {
219 use $crate::VectorComparisonResult as CR;
220
221 let (comparison_result, margin_factor, multiplier_factor) = $crate::evaluate_vector_eq_approx(&expected, &actual, evaluator);
222
223 match comparison_result {
224 CR::ExactlyEqual | CR::ApproximatelyEqual => (),
225 CR::DifferentLengths {
226 expected_length,
227 actual_length,
228 } => {
229 assert!(
230 false,
231 "assertion failed: failed to verify approximate equality for vectors: expected-length {expected_length} differs from actual-length {actual_length}",
232 );
233 },
234 CR::UnequalElements {
235 index_of_first_unequal_element,
236 expected_value_of_first_unequal_element,
237 actual_value_of_first_unequal_element,
238 } => {
239 match margin_factor {
240 Some(margin_factor) => {
241 match multiplier_factor {
242 Some(multiplier_factor) => {
243 assert!(
244 false,
245 "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}",
246 );
247 },
248 None => {
249 assert!(
250 false,
251 "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}",
252 );
253 },
254 };
255 },
256 None => {
257 match multiplier_factor {
258 Some(multiplier_factor) => {
259 assert!(
260 false,
261 "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}",
262 );
263 },
264 None => {
265 panic!("VIOLATION: This should not occur, and may only result from an improperly written implementor of `ApproximateEqualityEvaluator`");
266 }
267 };
268 },
269 };
270 },
271 };
272 }
273 };
274 ($expected:expr, $actual:expr) => {
275 let evaluator = $crate::zero_margin_or_multiplier($crate::constants::DEFAULT_MULTIPLIER, $crate::constants::DEFAULT_MARGIN);
276
277 assert_vector_eq_approx!($expected, $actual, evaluator);
278 };
279}
280
281/// Asserts that two vectors are not approximately equal.
282///
283/// # Forms
284///
285/// * `assert_vector_ne_approx!(expected, actual)` — stock
286/// [`zero_margin_or_multiplier`] evaluator;
287/// * `assert_vector_ne_approx!(expected, actual, evaluator)` — custom
288/// [`traits::ApproximateEqualityEvaluator`];
289///
290/// `expected` and `actual` may be slices, arrays, or [`Vec`]; element
291/// types must implement [`traits::TestableAsF64`].
292///
293/// # Panics
294///
295/// Panics when lengths match and every element pair is equal under the
296/// evaluator ([`VectorComparisonResult::ExactlyEqual`] or
297/// [`VectorComparisonResult::ApproximatelyEqual`]).
298#[macro_export]
299macro_rules! assert_vector_ne_approx {
300 ($expected:expr, $actual:expr, $evaluator:expr) => {
301 /*
302 let expected_param = &$expected;
303 let actual_param = &$actual;
304 */
305 let expected = &$expected;
306 let actual = &$actual;
307 let evaluator : &dyn $crate::traits::ApproximateEqualityEvaluator = &$evaluator;
308
309 // scope to protect against multiple `use`s of crate type(s)
310 {
311 use $crate::VectorComparisonResult as CR;
312
313 let (comparison_result, margin_factor, multiplier_factor) = $crate::evaluate_vector_eq_approx(&expected, &actual, evaluator);
314
315 match comparison_result {
316 CR::DifferentLengths { ..} | CR::UnequalElements {..} => (),
317 CR::ExactlyEqual | CR::ApproximatelyEqual => {
318 match margin_factor {
319 Some(margin_factor) => {
320 match multiplier_factor {
321 Some(multiplier_factor) => {
322 assert!(
323 false,
324 "assertion failed: failed to verify approximate inequality for vectors; margin_factor={margin_factor}, multiplier_factor={multiplier_factor}",
325 );
326 },
327 None => {
328 assert!(
329 false,
330 "assertion failed: failed to verify approximate inequality for vectors; margin_factor={margin_factor}",
331 );
332 },
333 };
334 },
335 None => {
336 match multiplier_factor {
337 Some(multiplier_factor) => {
338 assert!(
339 false,
340 "assertion failed: failed to verify approximate inequality for vectors; multiplier_factor={multiplier_factor}",
341 );
342 },
343 None => {
344 assert!(
345 false,
346 "assertion failed: failed to verify approximate inequality for vectors",
347 );
348 }
349 };
350 }
351 };
352 },
353 };
354 }
355 };
356 ($expected:expr, $actual:expr) => {
357 let evaluator =
358 $crate::zero_margin_or_multiplier($crate::constants::DEFAULT_MULTIPLIER, $crate::constants::DEFAULT_MARGIN);
359
360 assert_vector_ne_approx!($expected, $actual, evaluator);
361 };
362}
363
364// ///////////////////////////// end of file //////////////////////////// //