09dc6101574d3e5ccd170c78ccb12a88074b2e98
[alexxy/gromacs.git] / src / gromacs / utility / tests / alignedallocator.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2015,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.
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 /*! \internal \file
36  * \brief Tests for gmx::AlignedAllocator
37  *
38  * \author Erik Lindahl <erik.lindahl@gmail.com>
39  * \author Mark Abraham <mark.j.abraham@gmail.com>
40  * \ingroup module_utility
41  */
42
43 #include "gmxpre.h"
44
45 #include "gromacs/utility/alignedallocator.h"
46
47 #include <vector>
48
49 #include <gtest/gtest.h>
50
51 #include "gromacs/math/vectypes.h"
52 #include "gromacs/utility/real.h"
53
54 namespace gmx
55 {
56
57 //! Templated test fixture.
58 template <typename T>
59 class AllocatorTest : public ::testing::Test
60 {
61     public:
62         /*! \brief Bitmask for testing the alignment.
63          *
64          * e.g. for 128-byte alignment the mask is 128-1 - all of
65          * these bits should be zero in pointers that have the
66          * intended alignment. */
67         std::size_t mask_ = T::allocation_policy::alignment()-1;
68 };
69
70 //! Declare allocator types to test.
71 using AllocatorTypesToTest = ::testing::Types<AlignedAllocator<real>,
72                                               PageAlignedAllocator<real>,
73                                               AlignedAllocator<int>,
74                                               PageAlignedAllocator<int>,
75                                               AlignedAllocator<RVec>,
76                                               PageAlignedAllocator<RVec>
77                                               >;
78 TYPED_TEST_CASE(AllocatorTest, AllocatorTypesToTest);
79
80 // NB need to use this->mask_ because of GoogleTest quirks
81
82 TYPED_TEST(AllocatorTest, AllocatorAlignAllocatesWithAlignment)
83 {
84     using pointer = typename TypeParam::pointer;
85     TypeParam a;
86     pointer   p = a.allocate(1000);
87
88     EXPECT_EQ(0, reinterpret_cast<std::size_t>(p) & this->mask_);
89     a.deallocate(p, 1000);
90 }
91
92
93 TYPED_TEST(AllocatorTest, VectorAllocatesAndResizesWithAlignment)
94 {
95     using value_type = typename TypeParam::value_type;
96     std::vector<value_type, TypeParam> v(10);
97     EXPECT_EQ(0, reinterpret_cast<std::size_t>(v.data()) & this->mask_);
98
99     // Reserve a few times to check things work ok, making sure we
100     // will trigger several reallocations on common vector
101     // implementations.
102     for (std::size_t i = 1000; i <= 10000; i += 1000)
103     {
104         v.resize(i);
105         EXPECT_EQ(0, reinterpret_cast<std::size_t>(v.data()) & this->mask_);
106     }
107 }
108
109 TYPED_TEST(AllocatorTest, VectorAllocatesAndReservesWithAlignment)
110 {
111     using value_type = typename TypeParam::value_type;
112     std::vector<value_type, TypeParam> v(10);
113     EXPECT_EQ(0, reinterpret_cast<std::size_t>(v.data()) & this->mask_);
114
115     // Reserve a few times to check things work ok, making sure we
116     // will trigger several reallocations on common vector
117     // implementations.
118     for (std::size_t i = 1000; i <= 10000; i += 1000)
119     {
120         v.reserve(i);
121         EXPECT_EQ(0, reinterpret_cast<std::size_t>(v.data()) & this->mask_);
122     }
123 }
124
125 TYPED_TEST(AllocatorTest, StatelessAllocatorUsesNoMemory)
126 {
127     using value_type = typename TypeParam::value_type;
128     EXPECT_EQ(sizeof(std::vector<value_type>),
129               sizeof(std::vector<value_type, TypeParam>));
130 }
131
132 }