Skip to main content

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 //////////////////////////// //