2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2015,2016,2017, 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.
36 * \brief Tests for gmx::ArrayRef.
38 * \author Mark Abraham <mark.j.abraham@gmail.com>
39 * \ingroup module_utility
43 #include "gromacs/utility/arrayref.h"
47 #include <gtest/gtest.h>
49 #include "gromacs/utility/basedefinitions.h"
50 #include "gromacs/utility/real.h"
58 TEST(EmptyArrayRefTest
, IsEmpty
)
60 EmptyArrayRef emptyArray
= {};
61 ArrayRef
<real
> empty(emptyArray
);
63 EXPECT_EQ(0U, empty
.size());
64 EXPECT_TRUE(empty
.empty());
67 TEST(EmptyConstArrayRefTest
, IsEmpty
)
69 EmptyArrayRef emptyArray
= {};
70 ArrayRef
<const real
> empty(emptyArray
);
72 EXPECT_EQ(0U, empty
.size());
73 EXPECT_TRUE(empty
.empty());
76 #ifdef GTEST_HAS_TYPED_TEST
78 //! Define the types that end up being available as TypeParam in the test cases for both kinds of ArrayRef
79 typedef ::testing::Types
<
81 ArrayRef
<unsigned char>,
83 ArrayRef
<unsigned int>,
85 ArrayRef
<unsigned long>,
86 ArrayRef
<gmx_int64_t
>,
87 ArrayRef
<gmx_uint64_t
>,
91 ArrayRef
<const unsigned char>,
93 ArrayRef
<const unsigned int>,
95 ArrayRef
<const unsigned long>,
96 ArrayRef
<const gmx_int64_t
>,
97 ArrayRef
<const gmx_uint64_t
>,
98 ArrayRef
<const float>,
99 ArrayRef
<const double>
102 /*! \brief Permit all the tests to run on all kinds of ArrayRefs
104 * The main objective is to verify that all the different kinds of
105 * construction lead to the expected result. */
106 template <typename TypeParam
>
107 class ArrayRefTest
: public ::testing::Test
110 typedef TypeParam ArrayRefType
;
111 typedef typename
ArrayRefType::value_type ValueType
;
112 typedef typename
std::remove_const
<ValueType
>::type NonConstValueType
;
114 /*! \brief Run the same tests all the time
116 * Note that test cases must call this->runTests(), because
117 * that's how the derived-class templates that implement
118 * type-parameterized tests actually work. */
119 void runTests(ValueType
*a
,
122 ArrayRefType
&arrayRef
)
124 ASSERT_EQ(aSize
, arrayRef
.size());
125 ASSERT_FALSE(arrayRef
.empty());
126 EXPECT_EQ(aData
, arrayRef
.data());
127 EXPECT_EQ(a
[0], arrayRef
.front());
128 EXPECT_EQ(a
[aSize
-1], arrayRef
.back());
129 for (size_t i
= 0; i
!= aSize
; ++i
)
131 EXPECT_EQ(a
[i
], arrayRef
[i
]);
136 TYPED_TEST_CASE(ArrayRefTest
, ArrayRefTypes
);
138 /* Welcome back to the past. While you can declare a static array[] of
139 templated type in a class, in C++98, you have to define it outside
140 the class, and when you do, the compiler knows the declaration is
141 incomplete and can't match the types to actual functions. So,
142 declaring locals is the only choice available, so we need macros to
143 avoid duplication. Lovely. */
144 #define DEFINE_ARRAY(a, aSize) \
145 typename TestFixture::ValueType (a)[] = { \
146 static_cast<typename TestFixture::ValueType>(1.2), \
147 static_cast<typename TestFixture::ValueType>(2.4), \
148 static_cast<typename TestFixture::ValueType>(3.1) \
150 size_t (aSize) = sizeof((a)) / sizeof(typename TestFixture::ValueType);
152 #define DEFINE_NON_CONST_ARRAY(a, aSize) \
153 typename TestFixture::NonConstValueType (a)[] = { \
154 static_cast<typename TestFixture::ValueType>(1.2), \
155 static_cast<typename TestFixture::ValueType>(2.4), \
156 static_cast<typename TestFixture::ValueType>(3.1) \
158 size_t (aSize) = sizeof((a)) / sizeof(typename TestFixture::ValueType);
161 TYPED_TEST(ArrayRefTest
, MakeWithAssignmentWorks
)
163 DEFINE_ARRAY(a
, aSize
);
164 typename
TestFixture::ArrayRefType arrayRef
= a
;
165 this->runTests(a
, aSize
, a
, arrayRef
);
168 TYPED_TEST(ArrayRefTest
, MakeWithNonConstAssignmentWorks
)
170 DEFINE_NON_CONST_ARRAY(a
, aSize
);
171 typename
TestFixture::ArrayRefType arrayRef
= a
;
172 this->runTests(a
, aSize
, a
, arrayRef
);
175 TYPED_TEST(ArrayRefTest
, ConstructWithTemplateConstructorWorks
)
177 DEFINE_ARRAY(a
, aSize
);
178 typename
TestFixture::ArrayRefType
arrayRef(a
);
179 this->runTests(a
, aSize
, a
, arrayRef
);
182 TYPED_TEST(ArrayRefTest
, ConstructWithNonConstTemplateConstructorWorks
)
184 DEFINE_NON_CONST_ARRAY(a
, aSize
);
185 typename
TestFixture::ArrayRefType
arrayRef(a
);
186 this->runTests(a
, aSize
, a
, arrayRef
);
189 TYPED_TEST(ArrayRefTest
, ConstructFromPointersWorks
)
191 DEFINE_ARRAY(a
, aSize
);
192 typename
TestFixture::ArrayRefType
arrayRef(a
, a
+ aSize
);
193 this->runTests(a
, aSize
, a
, arrayRef
);
196 TYPED_TEST(ArrayRefTest
, ConstructFromNonConstPointersWorks
)
198 DEFINE_NON_CONST_ARRAY(a
, aSize
);
199 typename
TestFixture::ArrayRefType
arrayRef(a
, a
+ aSize
);
200 this->runTests(a
, aSize
, a
, arrayRef
);
203 template<bool c
, typename T
>
204 using makeConstIf_t
= typename
std::conditional
<c
, const T
, T
>::type
;
206 TYPED_TEST(ArrayRefTest
, ConstructFromVectorWorks
)
208 DEFINE_ARRAY(a
, aSize
);
209 makeConstIf_t
<std::is_const
<typename
TestFixture::ValueType
>::value
,
210 std::vector
<typename
TestFixture::NonConstValueType
> > v(a
, a
+ aSize
);
211 typename
TestFixture::ArrayRefType
arrayRef(v
);
212 this->runTests(a
, v
.size(), v
.data(), arrayRef
);
215 TYPED_TEST(ArrayRefTest
, ConstructFromNonConstVectorWorks
)
217 DEFINE_ARRAY(a
, aSize
);
218 std::vector
<typename
TestFixture::NonConstValueType
> v(a
, a
+ aSize
);
219 typename
TestFixture::ArrayRefType
arrayRef(v
);
220 this->runTests(a
, v
.size(), v
.data(), arrayRef
);
223 //! Helper struct for the case actually used in mdrun signalling
224 template <typename T
>
232 /*! \brief Test of the case actually used in mdrun signalling
234 * There, we take a non-const struct-field array of static length and
235 * make an ArrayRef to it using the template constructor that is
236 * supposed to infer the length from the static size. This has
237 * been a problem (for a compiler that we no longer support),
241 TYPED_TEST(ArrayRefTest
, ConstructFromStructFieldWithTemplateConstructorWorks
)
243 DEFINE_ARRAY(a
, aSize
);
244 Helper
<typename
TestFixture::NonConstValueType
> h
;
246 for (int i
= 0; i
!= h
.size
; ++i
)
250 typename
TestFixture::ArrayRefType
arrayRef(h
.a
);
251 this->runTests(h
.a
, h
.size
, h
.a
, arrayRef
);
254 #else // GTEST_HAS_TYPED_TEST
256 /* A dummy test that at least signals that something is missing if one runs the
257 * unit test executable itself.
259 TEST(DISABLED_ArrayRefTest
, GenericTests
)
262 << "Tests for generic ArrayRef functionality require support for "
263 << "Google Test typed tests, which was not available when the tests "
267 #endif // GTEST_HAS_TYPED_TEST