Skip to main content

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