Merge branch 'release-4-6' into master
[alexxy/gromacs.git] / src / testutils / testasserts.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2013, by the GROMACS development team, led by
5  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
6  * others, as listed in the AUTHORS file in the top-level source
7  * directory and at http://www.gromacs.org.
8  *
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.
13  *
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.
18  *
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.
23  *
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.
31  *
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.
34  */
35 /*! \libinternal \file
36  * \brief
37  * Improved exception assertions for unit tests.
38  *
39  * This file provides assert macros to replace (ASSERT|EXPECT)(_NO)?_THROW
40  * from Google Test.  They behave otherwise the same as the Google Test ones,
41  * but also print details of any unexpected exceptions.  This makes it much
42  * easier to see at one glance what went wrong.
43  *
44  * \if internal
45  * \todo
46  * The implementation is somewhat ugly, and accesses some Google Test
47  * internals.  Could be nice to clean it up a bit.
48  * \endif
49  *
50  * \author Teemu Murtola <teemu.murtola@gmail.com>
51  * \inlibraryapi
52  * \ingroup module_testutils
53  */
54 #ifndef GMX_TESTUTILS_TESTASSERTS_H
55 #define GMX_TESTUTILS_TESTASSERTS_H
56
57 #include <gtest/gtest.h>
58
59 #include "gromacs/utility/exceptions.h"
60
61 /*! \cond internal */
62 /*! \internal
63  * \brief
64  * Internal implementation macro for exception assertations.
65  *
66  * \param statement          Statements to execute.
67  * \param expected_exception Exception type that \p statement should throw.
68  * \param fail               Function/macro to call on failure.
69  *
70  * The implementation is copied and adjusted from
71  * include/gtest/internal/gtest-internal.h in Google Test 1.6.0.
72  */
73 #define GMX_TEST_THROW_(statement, expected_exception, fail) \
74     GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
75     if (::testing::AssertionResult gmx_ar = ::testing::AssertionSuccess()) { \
76         bool gmx_caught_expected = false; \
77         try { \
78             GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
79         } \
80         catch (expected_exception const &) { \
81             gmx_caught_expected = true; \
82         } \
83         catch (std::exception const &ex) { \
84             gmx_ar << "Expected: " #statement " throws an exception of type " \
85             << #expected_exception ".\n  Actual: it throws a different type.\n" \
86             << "Exception details:\n" << ::gmx::formatException(ex); \
87             goto GTEST_CONCAT_TOKEN_(gmx_label_testthrow_, __LINE__); \
88         } \
89         catch (...) { \
90             gmx_ar << "Expected: " #statement " throws an exception of type " \
91             << #expected_exception ".\n  Actual: it throws a different type."; \
92             goto GTEST_CONCAT_TOKEN_(gmx_label_testthrow_, __LINE__); \
93         } \
94         if (!gmx_caught_expected) { \
95             gmx_ar << "Expected: " #statement " throws an exception of type " \
96             << #expected_exception ".\n  Actual: it throws nothing."; \
97             goto GTEST_CONCAT_TOKEN_(gmx_label_testthrow_, __LINE__); \
98         } \
99     } else \
100         GTEST_CONCAT_TOKEN_(gmx_label_testthrow_, __LINE__) : \
101             fail(gmx_ar.message())
102
103 /*! \internal
104  * \brief
105  * Internal implementation macro for exception assertations.
106  *
107  * \param statement          Statements to execute.
108  * \param fail               Function/macro to call on failure.
109  *
110  * The implementation is copied and adjusted from
111  * include/gtest/internal/gtest-internal.h in Google Test 1.6.0.
112  */
113 #define GMX_TEST_NO_THROW_(statement, fail) \
114     GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
115     if (::testing::AssertionResult gmx_ar = ::testing::AssertionSuccess()) { \
116         try { \
117             GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
118         } \
119         catch (std::exception const &ex) { \
120             gmx_ar << "Expected: " #statement " doesn't throw an exception.\n" \
121             << "  Actual: it throws.\n" \
122             << "Exception details:\n" << ::gmx::formatException(ex); \
123             goto GTEST_CONCAT_TOKEN_(gmx_label_testnothrow_, __LINE__); \
124         } \
125         catch (...) { \
126             gmx_ar << "Expected: " #statement " doesn't throw an exception.\n" \
127             << "  Actual: it throws."; \
128             goto GTEST_CONCAT_TOKEN_(gmx_label_testnothrow_, __LINE__); \
129         } \
130     } else \
131         GTEST_CONCAT_TOKEN_(gmx_label_testnothrow_, __LINE__) : \
132             fail(gmx_ar.message())
133 //! \endcond
134
135 /*! \brief
136  * Asserts that a statement throws a given exception.
137  *
138  * See Google Test documentation on EXPECT_THROW.
139  * This macro works the same, but additionally prints details of unexpected
140  * exceptions.
141  */
142 #define EXPECT_THROW_GMX(statement, expected_exception) \
143     GMX_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
144 /*! \brief
145  * Asserts that a statement does not throw.
146  *
147  * See Google Test documentation on EXPECT_NO_THROW.
148  * This macro works the same, but additionally prints details of unexpected
149  * exceptions.
150  */
151 #define EXPECT_NO_THROW_GMX(statement) \
152     GMX_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
153 /*! \brief
154  * Asserts that a statement throws a given exception.
155  *
156  * See Google Test documentation on ASSERT_THROW.
157  * This macro works the same, but additionally prints details of unexpected
158  * exceptions.
159  */
160 #define ASSERT_THROW_GMX(statement, expected_exception) \
161     GMX_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
162 /*! \brief
163  * Asserts that a statement does not throw.
164  *
165  * See Google Test documentation on ASSERT_NO_THROW.
166  * This macro works the same, but additionally prints details of unexpected
167  * exceptions.
168  */
169 #define ASSERT_NO_THROW_GMX(statement) \
170     GMX_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
171
172 #endif