1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2013,2014,2015,2016,2017 by the GROMACS development team.
5  * Copyright (c) 2018,2019,2020, by the GROMACS development team, led by
6  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7  * and including many others, as listed in the AUTHORS file in the
8  * top-level source directory and at http://www.gromacs.org.
9  *
10  * GROMACS is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * as published by the Free Software Foundation; either version 2.1
13  * of the License, or (at your option) any later version.
14  *
15  * GROMACS is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with GROMACS; if not, see
22  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
24  *
25  * If you want to redistribute modifications to GROMACS, please
26  * consider that scientific software is very special. Version
27  * control is crucial - bugs must be traceable. We will be happy to
28  * consider code for inclusion in the official distribution, but
29  * derived work must not be called official GROMACS. Details are found
30  * in the README & COPYING files - if they are missing, get the
31  * official version at http://www.gromacs.org.
32  *
33  * To help us fund GROMACS development, we humbly ask that you cite
34  * the research papers on the package. Check out http://www.gromacs.org.
35  */
36 /*! \libinternal \file
37  * \brief
38  * Extra assertions for unit tests.
39  *
40  * This file provides assertion macros that extend/replace Google Test
41  * assertions for:
42  *  - exceptions
43  *  - floating-point comparison
44  *  - comparison against NULL
45  *  - death tests
46  *
47  * \if internal
48  * \todo
49  * The implementation is somewhat ugly, and accesses some Google Test
50  * internals.  Could be nice to clean it up a bit.
51  * \endif
52  *
53  * \author Teemu Murtola <teemu.murtola@gmail.com>
54  * \inlibraryapi
55  * \ingroup module_testutils
56  */
57 #ifndef GMX_TESTUTILS_TESTASSERTS_H
58 #define GMX_TESTUTILS_TESTASSERTS_H
59 
60 #include "config.h"
61 
62 #include <string>
63 
64 #include <gtest/gtest.h>
65 
66 #include "gromacs/utility/basedefinitions.h"
67 #include "gromacs/utility/exceptions.h"
68 #include "gromacs/utility/real.h"
69 
70 namespace gmx
71 {
72 namespace test
73 {
74 
75 namespace internal
76 {
77 //! \cond internal
78 /*! \internal
79  * \brief
80  * Called for an expected exception from EXPECT_THROW_GMX().
81  *
82  * \param[in] ex  Exception that was thrown.
83  */
84 void processExpectedException(const std::exception& ex);
85 //! \endcond
86 } // namespace internal
87 
88 //! \libinternal \addtogroup module_testutils
89 //! \{
90 
91 /*! \name Assertions for exceptions
92  *
93  * These macros replace `(ASSERT|EXPECT)(_NO)?_THROW` from Google Test.
94  * They are used exactly like the Google Test ones, but also print details of
95  * any unexpected exceptions using \Gromacs-specific routines.
96  * This makes it much easier to see at one glance what went wrong.
97  * See Google Test documentation for details on how to use the macros.
98  */
99 //! \{
100 
101 //! \cond internal
102 /*! \brief
103  * Internal implementation macro for exception assertations.
104  *
105  * \param statement          Statements to execute.
106  * \param expected_exception Exception type that \p statement should throw.
107  * \param fail               Function/macro to call on failure.
108  *
109  * The implementation is copied and adjusted from
110  * include/gtest/internal/gtest-internal.h in Google Test 1.6.0.
111  */
112 #define GMX_TEST_THROW_(statement, expected_exception, fail)                           \
113     GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                      \
114     if (::testing::AssertionResult gmx_ar = ::testing::AssertionSuccess())             \
115     {                                                                                  \
116         bool gmx_caught_expected = false;                                              \
117         try                                                                            \
118         {                                                                              \
119             GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);                 \
120         }                                                                              \
121         catch (expected_exception const& ex)                                           \
122         {                                                                              \
123             gmx_caught_expected = true;                                                \
124             ::gmx::test::internal::processExpectedException(ex);                       \
125         }                                                                              \
126         catch (std::exception const& ex)                                               \
127         {                                                                              \
128             gmx_ar << "Expected: " #statement " throws an exception of type "          \
129                    << #expected_exception ".\n  Actual: it throws a different type.\n" \
130                    << "Exception details:\n"                                           \
131                    << ::gmx::formatExceptionMessageToString(ex);                       \
132             goto GTEST_CONCAT_TOKEN_(gmx_label_testthrow_, __LINE__);                  \
133         }                                                                              \
134         catch (...)                                                                    \
135         {                                                                              \
136             gmx_ar << "Expected: " #statement " throws an exception of type "          \
137                    << #expected_exception ".\n  Actual: it throws a different type.";  \
138             goto GTEST_CONCAT_TOKEN_(gmx_label_testthrow_, __LINE__);                  \
139         }                                                                              \
140         if (!gmx_caught_expected)                                                      \
141         {                                                                              \
142             gmx_ar << "Expected: " #statement " throws an exception of type "          \
143                    << #expected_exception ".\n  Actual: it throws nothing.";           \
144             goto GTEST_CONCAT_TOKEN_(gmx_label_testthrow_, __LINE__);                  \
145         }                                                                              \
146     }                                                                                  \
147     else                                                                               \
148         GTEST_CONCAT_TOKEN_(gmx_label_testthrow_, __LINE__) : fail(gmx_ar.message())
149 
150 /*! \brief
151  * Internal implementation macro for exception assertations.
152  *
153  * \param statement          Statements to execute.
154  * \param fail               Function/macro to call on failure.
155  *
156  * The implementation is copied and adjusted from
157  * include/gtest/internal/gtest-internal.h in Google Test 1.6.0.
158  */
159 #define GMX_TEST_NO_THROW_(statement, fail)                                    \
160     GTEST_AMBIGUOUS_ELSE_BLOCKER_                                              \
161     if (::testing::AssertionResult gmx_ar = ::testing::AssertionSuccess())     \
162     {                                                                          \
163         try                                                                    \
164         {                                                                      \
165             GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement);         \
166         }                                                                      \
167         catch (std::exception const& ex)                                       \
168         {                                                                      \
169             gmx_ar << "Expected: " #statement " doesn't throw an exception.\n" \
170                    << "  Actual: it throws.\n"                                 \
171                    << "Exception details:\n"                                   \
172                    << ::gmx::formatExceptionMessageToString(ex);               \
173             goto GTEST_CONCAT_TOKEN_(gmx_label_testnothrow_, __LINE__);        \
174         }                                                                      \
175         catch (...)                                                            \
176         {                                                                      \
177             gmx_ar << "Expected: " #statement " doesn't throw an exception.\n" \
178                    << "  Actual: it throws.";                                  \
179             goto GTEST_CONCAT_TOKEN_(gmx_label_testnothrow_, __LINE__);        \
180         }                                                                      \
181     }                                                                          \
182     else                                                                       \
183         GTEST_CONCAT_TOKEN_(gmx_label_testnothrow_, __LINE__) : fail(gmx_ar.message())
184 //! \endcond
185 
186 /*! \brief
187  * Asserts that a statement throws a given exception.
188  *
189  * \hideinitializer
190  */
191 #define EXPECT_THROW_GMX(statement, expected_exception) \
192     GMX_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
193 /*! \brief
194  * Asserts that a statement does not throw.
195  *
196  * \hideinitializer
197  */
198 #define EXPECT_NO_THROW_GMX(statement) GMX_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
199 /*! \brief
200  * Asserts that a statement throws a given exception.
201  *
202  * \hideinitializer
203  */
204 #define ASSERT_THROW_GMX(statement, expected_exception) \
205     GMX_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
206 /*! \brief
207  * Asserts that a statement does not throw.
208  *
209  * \hideinitializer
210  */
211 #define ASSERT_NO_THROW_GMX(statement) GMX_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
212 
213 /*! \brief
214  * Wrapper around EXPECT_DEATH_IF_SUPPORTED gtest macro for thread safe execution.
215  *
216  * Makes sure that tests that are supposed to trigger an assertion are only executed
217  * in a threadsafe environment, and not when when running under e.g. MPI.
218  *
219  * \hideinitializer
220  */
221 #define GMX_EXPECT_DEATH_IF_SUPPORTED(expr, msg) \
222     if (!GMX_LIB_MPI)                            \
223     {                                            \
224         EXPECT_DEATH_IF_SUPPORTED(expr, msg);    \
225     }
226 
227 /*! \brief
228  * Wrapper around ASSERT_DEATH_IF_SUPPORTED gtest macro for thread safe execution.
229  *
230  * Makes sure that tests that are supposed to trigger an assertion are only executed
231  * in a threadsafe environment when running under e.g. MPI.
232  *
233  * \hideinitializer
234  */
235 #define GMX_ASSERT_DEATH_IF_SUPPORTED(expr, msg) \
236     if (!GMX_LIB_MPI)                            \
237     {                                            \
238         ASSERT_DEATH_IF_SUPPORTED(expr, msg);    \
239     }
240 
241 //! \}
242 
243 /*! \libinternal \brief
244  * Computes and represents a floating-point difference value.
245  *
246  * Methods in this class do not throw, except for toString(), which may throw
247  * std::bad_alloc.
248  *
249  * \see FloatingPointTolerance
250  */
251 class FloatingPointDifference
252 {
253 public:
254     /*! \brief Initializes a single-precision difference.
255      *
256      *  \param ref    First term in difference
257      *  \param value  Second term in difference
258      *
259      *  For absolute and ULP differences the two parameters are equivalent,
260      *  since the difference is symmetric. For relative differences
261      *  the first term is interpreted as the reference value, from which
262      *  we extract the magnitude to compare with.
263      */
264     FloatingPointDifference(float ref, float value);
265 
266     /*! \brief Initializes a double-precision difference.
267      *
268      *  \param ref    First term in difference
269      *  \param value  Second term in difference
270      *
271      *  For absolute and ULP differences the two parameters are equivalent,
272      *  since the difference is symmetric. For relative differences
273      *  the first term is interpreted as the reference value, from which
274      *  we extract the magnitude to compare with.
275      */
276     FloatingPointDifference(double ref, double value);
277 
278     /*! \brief
279      * Whether one or both of the compared values were NaN.
280      *
281      * If this returns `true`, other accessors return meaningless values.
282      */
283     bool isNaN() const;
284     //! Returns the difference as an absolute number (always non-negative).
asAbsolute()285     double asAbsolute() const { return absoluteDifference_; }
286     /*! \brief
287      * Returns the difference as ULPs (always non-negative).
288      *
289      * The ULPs are calculated for the type that corresponds to the
290      * constructor used to initialize the difference.
291      * The ULP difference between 0.0 and -0.0 is zero.
292      */
asUlps()293     uint64_t asUlps() const { return ulpDifference_; }
294     /*! \brief
295      * Whether the compared values were of different sign.
296      *
297      * 0.0 and -0.0 are treated as positive and negative, respectively.
298      */
signsDiffer()299     bool signsDiffer() const { return bSignDifference_; }
300     /*! \brief
301      * Whether the difference is between single- or double-precision
302      * numbers.
303      */
isDouble()304     bool isDouble() const { return bDouble_; }
305     //! Formats the difference as a string for assertion failure messages.
306     std::string toString() const;
307 
308     //! Returns the magnitude of the original second term of the difference.
termMagnitude()309     double termMagnitude() const { return termMagnitude_; }
310 
311 private:
312     //! Save the magnitude of the reference value for relative (i.e., not ULP) tolerance
313     double termMagnitude_;
314     //! Stores the absolute difference, or NaN if one or both values were NaN.
315     double   absoluteDifference_;
316     uint64_t ulpDifference_;
317     bool     bSignDifference_;
318     /*! \brief
319      * Whether the difference was computed for single or double precision.
320      *
321      * This sets the units for `ulpDifference_`.
322      */
323     bool bDouble_;
324 };
325 
326 /*! \libinternal \brief
327  * Specifies a floating-point comparison tolerance and checks whether a
328  * difference is within the tolerance.
329  *
330  * The related functions section lists methods that can be construct methods
331  * using less parameters than the full constructor, and with more obvious
332  * semantics.  These should be preferred over using the constructor directly.
333  *
334  * Several types of tolerances are possible:
335  *  - _absolute tolerance_: difference between the values must be smaller than
336  *    the given tolerance for the check to pass.
337  *    Setting the absolute tolerance to zero disables the absolute tolerance
338  *    check.
339  *  - _relative tolerance_: the absolute difference between the numbers must
340  *    be smaller than the tolerance multiplied by the first number. Setting
341  *    the relative tolerance to zero disables this check.
342  *  - _ULP tolerance_: ULP (units of least precision) difference between the
343  *    values must be smaller than the given tolerance for the check to pass.
344  *    Setting the ULP tolerance to zero requires exact match.
345  *    Setting the ULP tolerance to UINT64_MAX disables the ULP check.
346  *    `0.0` and `-0.0` are treated as equal for the ULP check.
347  *  - _sign check_: if set, any values that are of different signs fail the
348  *    check (note that this also applies to `0.0` and `-0.0`: a value with a
349  *    different sign than the zero will fail the check).
350  *
351  * Either an absolute, relative, or ULP tolerance must always be specified.
352  * If several of them are specified, then the check passes if either of the
353  * tolerances is satisfied.
354  *
355  * Any combination of absolute, relative, and ULP tolerance can be combined with
356  * the sign check.  In this case, the sign check must succeed for the check to
357  * pass, even if other tolerances are satisfied.
358  *
359  * The tolerances can be specified separately for single and double precision
360  * comparison.  Different initialization functions have different semantics on
361  * how the provided tolerance values are interpreted; check their
362  * documentation.
363  *
364  * Methods in this class do not throw, except for toString(), which may throw
365  * std::bad_alloc.
366  *
367  * \todo
368  * The factory methods that take ULP difference could be better formulated as
369  * methods that take the acceptable number of incorrect bits and/or the number
370  * of accurate bits.
371  *
372  * \see FloatingPointDifference
373  */
374 class FloatingPointTolerance
375 {
376 public:
377     /*! \brief
378      * Creates a tolerance with the specified values.
379      *
380      * \param[in]  singleAbsoluteTolerance
381      *     Allowed absolute difference in a single-precision number.
382      * \param[in]  doubleAbsoluteTolerance
383      *     Allowed absolute difference in a double-precision number.
384      * \param[in]  singleRelativeTolerance
385      *     Allowed relative difference in a single-precision number.
386      * \param[in]  doubleRelativeTolerance
387      *     Allowed relative difference in a double-precision number.
388      * \param[in]  singleUlpTolerance
389      *     Allowed ULP difference in a single-precision number.
390      * \param[in]  doubleUlpTolerance
391      *     Allowed ULP difference in a double-precision number.
392      * \param[in]  bSignMustMatch
393      *     Whether sign mismatch fails the comparison.
394      */
FloatingPointTolerance(float singleAbsoluteTolerance,double doubleAbsoluteTolerance,float singleRelativeTolerance,double doubleRelativeTolerance,uint64_t singleUlpTolerance,uint64_t doubleUlpTolerance,bool bSignMustMatch)395     FloatingPointTolerance(float    singleAbsoluteTolerance,
396                            double   doubleAbsoluteTolerance,
397                            float    singleRelativeTolerance,
398                            double   doubleRelativeTolerance,
399                            uint64_t singleUlpTolerance,
400                            uint64_t doubleUlpTolerance,
401                            bool     bSignMustMatch) :
402         singleAbsoluteTolerance_(singleAbsoluteTolerance),
403         doubleAbsoluteTolerance_(doubleAbsoluteTolerance),
404         singleRelativeTolerance_(singleRelativeTolerance),
405         doubleRelativeTolerance_(doubleRelativeTolerance),
406         singleUlpTolerance_(singleUlpTolerance),
407         doubleUlpTolerance_(doubleUlpTolerance),
408         bSignMustMatch_(bSignMustMatch)
409     {
410     }
411 
412     /*! \brief
413      * Checks whether a difference is within the specified tolerance.
414      *
415      * NaNs are always treated outside the tolerance.
416      */
417     bool isWithin(const FloatingPointDifference& difference) const;
418 
419     //! Formats the tolerance as a string for assertion failure messages.
420     std::string toString(const FloatingPointDifference& difference) const;
421 
422 private:
423     float    singleAbsoluteTolerance_;
424     double   doubleAbsoluteTolerance_;
425     float    singleRelativeTolerance_;
426     double   doubleRelativeTolerance_;
427     uint64_t singleUlpTolerance_;
428     uint64_t doubleUlpTolerance_;
429     bool     bSignMustMatch_;
430 };
431 
432 /*! \brief
433  * Creates a tolerance that only allows a specified ULP difference.
434  *
435  * The tolerance uses the given ULP value for both precisions, i.e., double
436  * precision will have much stricter tolerance.
437  *
438  * \related FloatingPointTolerance
439  */
ulpTolerance(uint64_t ulpDiff)440 static inline FloatingPointTolerance ulpTolerance(uint64_t ulpDiff)
441 {
442     return FloatingPointTolerance(0.0, 0.0, 0.0, 0.0, ulpDiff, ulpDiff, false);
443 }
444 
445 /*! \brief
446  * Creates a tolerance that allows a difference in two compared values that is
447  * relative to the given magnitude.
448  *
449  * \param[in] magnitude  Magnitude of the numbers the computation operates in.
450  * \param[in] tolerance  Relative tolerance permitted (e.g. 1e-4).
451  *
452  * In addition to setting an relative tolerance for both
453  * precisions, this sets the absolute tolerance such that values close to zero
454  * (in general, smaller than \p magnitude) do not fail the check if they
455  * differ by less than \p tolerance evaluated at \p magnitude.  This accounts
456  * for potential loss of precision for small values, and should be used when
457  * accuracy of values much less than \p magnitude do not matter for
458  * correctness.
459  *
460  * \related FloatingPointTolerance
461  */
462 FloatingPointTolerance relativeToleranceAsFloatingPoint(double magnitude, double tolerance);
463 
464 /*! \brief
465  * Creates a tolerance that allows a precision-dependent difference in two
466  * compared values that is relative to the given magnitude.
467  *
468  * \param[in] magnitude        Magnitude of the numbers the computation
469  *     operates in.
470  * \param[in] singleTolerance  Relative tolerance permitted (e.g. 1e-4)
471  *     in single precision.
472  * \param[in] doubleTolerance  Relative tolerance permitted (e.g. 1e-4)
473  *     in double precision.
474  *
475  * In addition to setting an relative tolerance for both
476  * precisions, this sets the absolute tolerance such that values close to zero
477  * (in general, smaller than \p magnitude) do not fail the check if they
478  * differ by less than \p tolerance evaluated at \p magnitude.  This accounts
479  * for potential loss of precision for small values, and should be used when
480  * accuracy of values much less than \p magnitude do not matter for
481  * correctness.
482  *
483  * \related FloatingPointTolerance
484  */
485 FloatingPointTolerance relativeToleranceAsPrecisionDependentFloatingPoint(double magnitude,
486                                                                           float  singleTolerance,
487                                                                           double doubleTolerance);
488 
489 /*! \brief
490  * Creates a tolerance that allows a precision-dependent relative difference in
491  * a complex computation.
492  *
493  * \param[in] magnitude      Magnitude of the numbers the computation operates in.
494  * \param[in] singleUlpDiff  Expected accuracy of single-precision
495  *     computation (in ULPs).
496  * \param[in] doubleUlpDiff  Expected accuracy of double-precision
497  *     computation (in ULPs).
498  *
499  * This works as relativeToleranceAsUlp(), but allows setting the ULP
500  * difference separately for the different precisions.  This supports
501  * cases where the double-precision calculation can acceptably has a higher ULP
502  * difference, but relaxing the single-precision tolerance would lead to an
503  * unnecessarily loose test.
504  *
505  * \related FloatingPointTolerance
506  */
relativeToleranceAsPrecisionDependentUlp(double magnitude,uint64_t singleUlpDiff,uint64_t doubleUlpDiff)507 static inline FloatingPointTolerance relativeToleranceAsPrecisionDependentUlp(double   magnitude,
508                                                                               uint64_t singleUlpDiff,
509                                                                               uint64_t doubleUlpDiff)
510 {
511     return FloatingPointTolerance(float(magnitude) * singleUlpDiff * GMX_FLOAT_EPS,
512                                   magnitude * doubleUlpDiff * GMX_DOUBLE_EPS, 0.0, 0.0,
513                                   singleUlpDiff, doubleUlpDiff, false);
514 }
515 
516 /*! \brief
517  * Creates a tolerance that allows a specified absolute difference.
518  *
519  * \related FloatingPointTolerance
520  */
absoluteTolerance(double tolerance)521 static inline FloatingPointTolerance absoluteTolerance(double tolerance)
522 {
523     return FloatingPointTolerance(float(tolerance), tolerance, 0.0, 0.0, UINT64_MAX, UINT64_MAX, false);
524 }
525 
526 /*! \brief
527  * Creates a tolerance that allows a relative difference in a complex
528  * computation.
529  *
530  * \param[in] magnitude  Magnitude of the numbers the computation operates in.
531  * \param[in] ulpDiff    Expected accuracy of the computation (in ULPs).
532  *
533  * In addition to setting the ULP tolerance as ulpTolerance(), this sets the
534  * absolute tolerance such that values close to zero (in general, smaller than
535  * \p magnitude) do not fail the check if they differ by less than \p ulpDiff
536  * evaluated at \p magnitude.  This accounts for potential loss of precision
537  * for small values, and should be used when accuracy of values much less than
538  * \p magnitude do not matter for correctness.
539  *
540  * \related FloatingPointTolerance
541  */
relativeToleranceAsUlp(double magnitude,uint64_t ulpDiff)542 static inline FloatingPointTolerance relativeToleranceAsUlp(double magnitude, uint64_t ulpDiff)
543 {
544     return relativeToleranceAsPrecisionDependentUlp(magnitude, ulpDiff, ulpDiff);
545 }
546 
547 namespace detail
548 {
549 //! Default tolerance in ULPs for two floating-point values to compare equal.
550 constexpr uint64_t g_defaultUlpTolerance = 4;
551 } // namespace detail
552 
553 /*! \brief
554  * Returns the default tolerance for comparing `real` numbers.
555  *
556  * \related FloatingPointTolerance
557  */
defaultRealTolerance()558 static inline FloatingPointTolerance defaultRealTolerance()
559 {
560     return relativeToleranceAsUlp(1.0, detail::g_defaultUlpTolerance);
561 }
562 
563 
564 /*! \brief
565  * Returns the default tolerance for comparing single-precision numbers when
566  * compared by \Gromacs built in either precision mode.
567  *
568  * This permits a checker compiled with any \Gromacs precision to compare
569  * equal or not in the same way.
570  *
571  * \related FloatingPointTolerance
572  */
defaultFloatTolerance()573 static inline FloatingPointTolerance defaultFloatTolerance()
574 {
575     return relativeToleranceAsPrecisionDependentUlp(
576             1.0, detail::g_defaultUlpTolerance,
577             static_cast<uint64_t>(detail::g_defaultUlpTolerance * (GMX_FLOAT_EPS / GMX_DOUBLE_EPS)));
578 }
579 
580 /*! \name Assertions for floating-point comparison
581  *
582  * These routines extend `(EXPECT|ASSERT)_(FLOAT|DOUBLE)_EQ` and
583  * `(EXPECT|ASSERT)_NEAR` from Google Test to provide more flexible assertions
584  * for floating-point values.
585  *
586  * See gmx::test::FloatingPointTolerance for the possible ways to specify the
587  * tolerance, and gmx::test::FloatingPointDifference for some additional
588  * details of the difference calculation.
589  */
590 //! \{
591 
592 //! \cond internal
593 /*! \internal \brief
594  * Assertion predicate formatter for comparing two floating-point values.
595  */
596 template<typename FloatType>
assertEqualWithinTolerance(const char * expr1,const char * expr2,const char *,FloatType value1,FloatType value2,const FloatingPointTolerance & tolerance)597 static inline ::testing::AssertionResult assertEqualWithinTolerance(const char* expr1,
598                                                                     const char* expr2,
599                                                                     const char* /*exprTolerance*/,
600                                                                     FloatType value1,
601                                                                     FloatType value2,
602                                                                     const FloatingPointTolerance& tolerance)
603 {
604     FloatingPointDifference diff(value1, value2);
605     if (tolerance.isWithin(diff))
606     {
607         return ::testing::AssertionSuccess();
608     }
609     return ::testing::AssertionFailure() << "  Value of: " << expr2 << std::endl
610                                          << "    Actual: " << value2 << std::endl
611                                          << "  Expected: " << expr1 << std::endl
612                                          << "  Which is: " << value1 << std::endl
613                                          << "Difference: " << diff.toString() << std::endl
614                                          << " Tolerance: " << tolerance.toString(diff);
615 }
616 //! \endcond
617 
618 /*! \brief
619  * Asserts that two single-precision values are within the given tolerance.
620  *
621  * \hideinitializer
622  */
623 #define EXPECT_FLOAT_EQ_TOL(value1, value2, tolerance) \
624     EXPECT_PRED_FORMAT3(::gmx::test::assertEqualWithinTolerance<float>, value1, value2, tolerance)
625 /*! \brief
626  * Asserts that two double-precision values are within the given tolerance.
627  *
628  * \hideinitializer
629  */
630 #define EXPECT_DOUBLE_EQ_TOL(value1, value2, tolerance) \
631     EXPECT_PRED_FORMAT3(::gmx::test::assertEqualWithinTolerance<double>, value1, value2, tolerance)
632 /*! \def EXPECT_REAL_EQ_TOL
633  * \brief
634  * Asserts that two `real` values are within the given tolerance.
635  *
636  * \hideinitializer
637  */
638 /*! \brief
639  * Asserts that two single-precision values are within the given tolerance.
640  *
641  * \hideinitializer
642  */
643 #define ASSERT_FLOAT_EQ_TOL(value1, value2, tolerance) \
644     ASSERT_PRED_FORMAT3(::gmx::test::assertEqualWithinTolerance<float>, value1, value2, tolerance)
645 /*! \brief
646  * Asserts that two double-precision values are within the given tolerance.
647  *
648  * \hideinitializer
649  */
650 #define ASSERT_DOUBLE_EQ_TOL(value1, value2, tolerance) \
651     ASSERT_PRED_FORMAT3(::gmx::test::assertEqualWithinTolerance<double>, value1, value2, tolerance)
652 /*! \def ASSERT_REAL_EQ_TOL
653  * \brief
654  * Asserts that two `real` values are within the given tolerance.
655  *
656  * \hideinitializer
657  */
658 
659 #if GMX_DOUBLE
660 #    define EXPECT_REAL_EQ_TOL(value1, value2, tolerance) \
661         EXPECT_DOUBLE_EQ_TOL(value1, value2, tolerance)
662 #    define ASSERT_REAL_EQ_TOL(value1, value2, tolerance) \
663         ASSERT_DOUBLE_EQ_TOL(value1, value2, tolerance)
664 #else
665 #    define EXPECT_REAL_EQ_TOL(value1, value2, tolerance) \
666         EXPECT_FLOAT_EQ_TOL(value1, value2, tolerance)
667 #    define ASSERT_REAL_EQ_TOL(value1, value2, tolerance) \
668         ASSERT_FLOAT_EQ_TOL(value1, value2, tolerance)
669 #endif
670 
671 //! EXPECT_REAL_EQ_TOL with default tolerance
672 #define EXPECT_REAL_EQ(value1, value2) \
673     EXPECT_REAL_EQ_TOL(value1, value2, ::gmx::test::defaultRealTolerance())
674 //! ASSERT_REAL_EQ_TOL with default tolerance
675 #define ASSERT_REAL_EQ(value1, value2) \
676     ASSERT_REAL_EQ_TOL(value1, value2, ::gmx::test::defaultRealTolerance())
677 //! \}
678 
679 //! \cond internal
680 /*! \internal \brief
681  * Helper method for `(EXPECT|ASSERT)_PLAIN`.
682  */
plainAssertHelper(const char *,const::testing::AssertionResult & expr)683 static inline ::testing::AssertionResult plainAssertHelper(const char* /*expr*/,
684                                                            const ::testing::AssertionResult& expr)
685 {
686     return expr;
687 }
688 //! \endcond
689 
690 /*! \brief
691  * Assert for predicates that return AssertionResult and produce a full failure
692  * message.
693  *
694  * `expr` should evaluate to AssertionResult, and on failure the message from
695  * the result is used as-is, unlike in EXPECT_TRUE().
696  *
697  * \hideinitializer
698  */
699 #define EXPECT_PLAIN(expr) EXPECT_PRED_FORMAT1(plainAssertHelper, expr)
700 /*! \brief
701  * Assert for predicates that return AssertionResult and produce a full failure
702  * message.
703  *
704  * `expr` should evaluate to AssertionResult, and on failure the message from
705  * the result is used as-is, unlike in ASSERT_TRUE().
706  *
707  * \hideinitializer
708  */
709 #define ASSERT_PLAIN(expr) ASSERT_PRED_FORMAT1(plainAssertHelper, expr)
710 
711 //! \}
712 
713 } // namespace test
714 } // namespace gmx
715 
716 #endif
717