2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2013,2014, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
35 /*! \libinternal \file
37 * Extra assertions for unit tests.
39 * This file provides assertion macros that extend/replace Google Test
42 * - floating-point comparison
46 * The implementation is somewhat ugly, and accesses some Google Test
47 * internals. Could be nice to clean it up a bit.
50 * \author Teemu Murtola <teemu.murtola@gmail.com>
52 * \ingroup module_testutils
54 #ifndef GMX_TESTUTILS_TESTASSERTS_H
55 #define GMX_TESTUTILS_TESTASSERTS_H
59 #include <gtest/gtest.h>
61 #include "gromacs/utility/basedefinitions.h"
62 #include "gromacs/utility/exceptions.h"
63 #include "gromacs/utility/real.h"
70 //! \libinternal \addtogroup module_testutils
73 /*! \name Assertions for exceptions
75 * These macros replace `(ASSERT|EXPECT)(_NO)?_THROW` from Google Test.
76 * They are used exactly like the Google Test ones, but also print details of
77 * any unexpected exceptions using \Gromacs-specific routines.
78 * This makes it much easier to see at one glance what went wrong.
79 * See Google Test documentation for details on how to use the macros.
85 * Internal implementation macro for exception assertations.
87 * \param statement Statements to execute.
88 * \param expected_exception Exception type that \p statement should throw.
89 * \param fail Function/macro to call on failure.
91 * The implementation is copied and adjusted from
92 * include/gtest/internal/gtest-internal.h in Google Test 1.6.0.
94 #define GMX_TEST_THROW_(statement, expected_exception, fail) \
95 GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
96 if (::testing::AssertionResult gmx_ar = ::testing::AssertionSuccess()) { \
97 bool gmx_caught_expected = false; \
99 GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
101 catch (expected_exception const &) { \
102 gmx_caught_expected = true; \
104 catch (std::exception const &ex) { \
105 gmx_ar << "Expected: " #statement " throws an exception of type " \
106 << #expected_exception ".\n Actual: it throws a different type.\n" \
107 << "Exception details:\n" << ::gmx::formatExceptionMessageToString(ex); \
108 goto GTEST_CONCAT_TOKEN_(gmx_label_testthrow_, __LINE__); \
111 gmx_ar << "Expected: " #statement " throws an exception of type " \
112 << #expected_exception ".\n Actual: it throws a different type."; \
113 goto GTEST_CONCAT_TOKEN_(gmx_label_testthrow_, __LINE__); \
115 if (!gmx_caught_expected) { \
116 gmx_ar << "Expected: " #statement " throws an exception of type " \
117 << #expected_exception ".\n Actual: it throws nothing."; \
118 goto GTEST_CONCAT_TOKEN_(gmx_label_testthrow_, __LINE__); \
121 GTEST_CONCAT_TOKEN_(gmx_label_testthrow_, __LINE__) : \
122 fail(gmx_ar.message())
125 * Internal implementation macro for exception assertations.
127 * \param statement Statements to execute.
128 * \param fail Function/macro to call on failure.
130 * The implementation is copied and adjusted from
131 * include/gtest/internal/gtest-internal.h in Google Test 1.6.0.
133 #define GMX_TEST_NO_THROW_(statement, fail) \
134 GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
135 if (::testing::AssertionResult gmx_ar = ::testing::AssertionSuccess()) { \
137 GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
139 catch (std::exception const &ex) { \
140 gmx_ar << "Expected: " #statement " doesn't throw an exception.\n" \
141 << " Actual: it throws.\n" \
142 << "Exception details:\n" << ::gmx::formatExceptionMessageToString(ex); \
143 goto GTEST_CONCAT_TOKEN_(gmx_label_testnothrow_, __LINE__); \
146 gmx_ar << "Expected: " #statement " doesn't throw an exception.\n" \
147 << " Actual: it throws."; \
148 goto GTEST_CONCAT_TOKEN_(gmx_label_testnothrow_, __LINE__); \
151 GTEST_CONCAT_TOKEN_(gmx_label_testnothrow_, __LINE__) : \
152 fail(gmx_ar.message())
156 * Asserts that a statement throws a given exception.
160 #define EXPECT_THROW_GMX(statement, expected_exception) \
161 GMX_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
163 * Asserts that a statement does not throw.
167 #define EXPECT_NO_THROW_GMX(statement) \
168 GMX_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
170 * Asserts that a statement throws a given exception.
174 #define ASSERT_THROW_GMX(statement, expected_exception) \
175 GMX_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
177 * Asserts that a statement does not throw.
181 #define ASSERT_NO_THROW_GMX(statement) \
182 GMX_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
186 /*! \libinternal \brief
187 * Computes and represents a floating-point difference value.
189 * Methods in this class do not throw, except for toString(), which may throw
192 * \see FloatingPointTolerance
194 class FloatingPointDifference
197 //! Initializes a single-precision difference.
198 FloatingPointDifference(float value1, float value2);
199 //! Initializes a double-precision difference.
200 FloatingPointDifference(double value1, double value2);
203 * Whether one or both of the compared values were NaN.
205 * If this returns `true`, other accessors return meaningless values.
208 //! Returns the difference as an absolute number (always non-negative).
209 double asAbsolute() const { return absoluteDifference_; }
211 * Returns the difference as ULPs (always non-negative).
213 * The ULPs are calculated for the type that corresponds to the
214 * constructor used to initialize the difference.
215 * The ULP difference between 0.0 and -0.0 is zero.
217 gmx_uint64_t asUlps() const { return ulpDifference_; }
219 * Whether the compared values were of different sign.
221 * 0.0 and -0.0 are treated as positive and negative, respectively.
223 bool signsDiffer() const { return bSignDifference_; }
225 //! Formats the difference as a string for assertion failure messages.
226 std::string toString() const;
229 //! Stores the absolute difference, or NaN if one or both values were NaN.
230 double absoluteDifference_;
231 gmx_uint64_t ulpDifference_;
232 bool bSignDifference_;
234 * Whether the difference was computed for single or double precision.
236 * This sets the units for `ulpDifference_`.
241 /*! \libinternal \brief
242 * Specifies a floating-point comparison tolerance and checks whether a
243 * difference is within the tolerance.
245 * Several types of tolerances are possible:
246 * - _absolute tolerance_: difference between the values must be smaller than
247 * the given tolerance for the check to pass.
248 * Setting the absolute tolerance to zero disables the absolute tolerance
250 * - _ULP tolerance_: ULP (units of least precision) difference between the
251 * values must be smaller than the given tolerance for the check to pass.
252 * Setting the ULP tolerance to zero requires exact match.
253 * Setting the ULP tolerance to negative disables the ULP check.
254 * `0.0` and `-0.0` are treated as equal for the ULP check.
255 * - _sign check_: if set, any values that are of different signs fail the
256 * check (note that this also applies to `0.0` and `-0.0`: a value with a
257 * different sign than the zero will fail the check).
259 * Either an absolute or a ULP tolerance must always be specified.
260 * If both are specified, then the check passes if either of the tolerances is
263 * Any combination of absolute and ULP tolerance can be combined with the sign
264 * check. In this case, the sign check must succeed for the check to pass,
265 * even if other tolerances are satisfied.
267 * Currently, the ULP tolerance is not in any particular precision, but the
268 * interpretation depends on the compared numbers: if floats are compared, then
269 * the ULP tolerance specifies single-precision ULPs, and if doubles are
270 * compared, then the same number is interpreted as double-precision ULPs.
272 * The related functions section lists methods that can be construct methods
273 * using less parameters than the full constructor, and with more obvious
276 * Methods in this class do not throw, except for toString(), which may throw
279 * \see FloatingPointDifference
281 class FloatingPointTolerance
285 * Creates a tolerance with the specified values.
287 * \param[in] absolute Allowed absolute difference.
288 * \param[in] ulp Allowed ULP difference.
289 * \param[in] bSignMustMatch Whether sign mismatch fails the comparison.
291 FloatingPointTolerance(double absolute, int ulp,
293 : absoluteTolerance_(absolute), ulpTolerance_(ulp),
294 bSignMustMatch_(bSignMustMatch)
299 * Checks whether a difference is within the specified tolerance.
301 * NaNs are always treated outside the tolerance.
303 bool isWithin(const FloatingPointDifference &difference) const;
305 //! Formats the tolerance as a string for assertion failure messages.
306 std::string toString() const;
309 double absoluteTolerance_;
311 bool bSignMustMatch_;
315 * Creates a tolerance that only allows a specified ULP difference.
317 * \related FloatingPointTolerance
319 static inline FloatingPointTolerance
320 ulpTolerance(gmx_int64_t ulpDiff)
322 return FloatingPointTolerance(0.0, ulpDiff, false);
326 * Creates a tolerance that allows a relative difference in a complex
329 * \param[in] magnitude Magnitude of the numbers the computation operates in.
330 * \param[in] ulpDiff Expected accuracy of the computation (in ULPs).
332 * In addition to setting the ULP tolerance, this sets the absolute tolerance
333 * such that values close to zero (in general, smaller than \p magnitude) do
334 * not fail the check if they differ by less than \p ulpDiff evaluated at
335 * \p magniture. This accounts for potential loss of precision for small
336 * values, and should be used when accuracy of values much less than
337 * \p magniture do not matter for correctness.
339 * \related FloatingPointTolerance
341 static inline FloatingPointTolerance
342 relativeRealTolerance(double magnitude, gmx_int64_t ulpDiff)
344 return FloatingPointTolerance(magnitude*ulpDiff*GMX_REAL_EPS, ulpDiff, false);
348 * Returns the default tolerance for comparing `real` numbers.
350 * \related FloatingPointTolerance
352 static inline FloatingPointTolerance defaultRealTolerance()
354 return relativeRealTolerance(1.0, 4);
357 /*! \name Assertions for floating-point comparison
359 * These routines extend `(EXPECT|ASSERT)_(FLOAT|DOUBLE)_EQ` and
360 * `(EXPECT|ASSERT)_NEAR` from Google Test to provide more flexible assertions
361 * for floating-point values.
363 * See gmx::test::FloatingPointTolerance for the possible ways to specify the
364 * tolerance, and gmx::test::FloatingPointDifference for some additional
365 * details of the difference calculation.
371 * Assertion predicate formatter for comparing two floating-point values.
373 template <typename FloatType>
374 static inline ::testing::AssertionResult assertEqualWithinTolerance(
375 const char *expr1, const char *expr2, const char * /*exprTolerance*/,
376 FloatType value1, FloatType value2,
377 const FloatingPointTolerance &tolerance)
379 FloatingPointDifference diff(value1, value2);
380 if (tolerance.isWithin(diff))
382 return ::testing::AssertionSuccess();
384 return ::testing::AssertionFailure()
385 << " Value of: " << expr2 << std::endl
386 << " Actual: " << value2 << std::endl
387 << " Expected: " << expr1 << std::endl
388 << " Which is: " << value1 << std::endl
389 << "Difference: " << diff.toString() << std::endl
390 << " Tolerance: " << tolerance.toString();
395 * Asserts that two single-precision values are within the given tolerance.
399 #define EXPECT_FLOAT_EQ_TOL(value1, value2, tolerance) \
400 EXPECT_PRED_FORMAT3(::gmx::test::assertEqualWithinTolerance<float>, \
401 value1, value2, tolerance)
403 * Asserts that two double-precision values are within the given tolerance.
407 #define EXPECT_DOUBLE_EQ_TOL(value1, value2, tolerance) \
408 EXPECT_PRED_FORMAT3(::gmx::test::assertEqualWithinTolerance<double>, \
409 value1, value2, tolerance)
410 /*! \def EXPECT_REAL_EQ_TOL
412 * Asserts that two `real` values are within the given tolerance.
417 * Asserts that two single-precision values are within the given tolerance.
421 #define ASSERT_FLOAT_EQ_TOL(value1, value2, tolerance) \
422 ASSERT_PRED_FORMAT3(::gmx::test::assertEqualWithinTolerance<float>, \
423 value1, value2, tolerance)
425 * Asserts that two double-precision values are within the given tolerance.
429 #define ASSERT_DOUBLE_EQ_TOL(value1, value2, tolerance) \
430 ASSERT_PRED_FORMAT3(::gmx::test::assertEqualWithinTolerance<double>, \
431 value1, value2, tolerance)
432 /*! \def ASSERT_REAL_EQ_TOL
434 * Asserts that two `real` values are within the given tolerance.
440 #define EXPECT_REAL_EQ_TOL(value1, value2, tolerance) \
441 EXPECT_DOUBLE_EQ_TOL(value1, value2, tolerance)
442 #define ASSERT_REAL_EQ_TOL(value1, value2, tolerance) \
443 ASSERT_DOUBLE_EQ_TOL(value1, value2, tolerance)
445 #define EXPECT_REAL_EQ_TOL(value1, value2, tolerance) \
446 EXPECT_FLOAT_EQ_TOL(value1, value2, tolerance)
447 #define ASSERT_REAL_EQ_TOL(value1, value2, tolerance) \
448 ASSERT_FLOAT_EQ_TOL(value1, value2, tolerance)
453 /*! \name Assertions for NULL comparison
455 * These macros should be used instead of `(EXPECT|ASSERT)_EQ(NULL, ...)`,
456 * because Google Test doesn't support the NULL comparison with xlC++ 12.1 on
462 * Asserts that a pointer is null.
464 * Works exactly like EXPECT_EQ comparing with a null pointer. */
465 #define EXPECT_NULL(val) EXPECT_EQ((void *) NULL, val)
467 * Asserts that a pointer is null.
469 * Works exactly like ASSERT_EQ comparing with a null pointer. */
470 #define ASSERT_NULL(val) ASSERT_EQ((void *) NULL, val)