2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2019, 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.
37 * Tests for gmx::InMemorySerializer and InMemoryDeserializer.
39 * \author Christian Blau <blau@kth.se>
40 * \ingroup module_utility
45 #include "gromacs/utility/inmemoryserializer.h"
47 #include <gmock/gmock.h>
48 #include <gtest/gtest.h>
57 std::int32_t int32Value_
;
62 std::int64_t int64Value_
;
66 //! Constants used for testing endian swap operations
68 constexpr std::int16_t c_int16Value
= static_cast<std::int16_t>(0x7A2B);
69 constexpr std::int16_t c_int16ValueSwapped
= static_cast<std::int16_t>(0x2B7A);
70 constexpr std::int32_t c_int32Value
= static_cast<std::int32_t>(0x78ABCDEF);
71 constexpr std::int32_t c_int32ValueSwapped
= static_cast<std::int32_t>(0xEFCDAB78);
72 constexpr std::int64_t c_int64Value
= static_cast<std::int64_t>(0x78ABCDEF12345678);
73 constexpr std::int64_t c_int64ValueSwapped
= static_cast<std::int64_t>(0x78563412EFCDAB78);
75 constexpr const IntAndFloat32 c_intAndFloat32
{ c_int32Value
};
76 constexpr const IntAndFloat64 c_intAndFloat64
{ c_int64Value
};
78 constexpr const IntAndFloat32 c_intAndFloat32Swapped
{ c_int32ValueSwapped
};
79 constexpr const IntAndFloat64 c_intAndFloat64Swapped
{ c_int64ValueSwapped
};
82 //! Return the integer used for testing, depending on the size of int.
83 constexpr int integerSizeDependentTestingValue()
85 return sizeof(int) == 4 ? c_int32Value
: sizeof(int) == 8 ? c_int64Value
: c_int16Value
;
88 //! Return the endianess-swapped integer used for testing, depending on the size of int.
89 constexpr int integerSizeDependentTestingValueEndianessSwapped()
91 return sizeof(int) == 4 ? c_int32ValueSwapped
92 : sizeof(int) == 8 ? c_int64ValueSwapped
: c_int16ValueSwapped
;
95 class InMemorySerializerTest
: public ::testing::Test
98 struct SerializerValues
101 unsigned char unsignedCharValue_
;
103 unsigned short unsignedShortValue_
;
104 std::int32_t int32Value_
;
106 std::int64_t int64Value_
;
112 void serialize(ISerializer
* serializer
, SerializerValues
* values
)
114 EXPECT_FALSE(serializer
->reading());
115 doValues(serializer
, values
);
118 SerializerValues
deserialize(ISerializer
* serializer
)
120 EXPECT_TRUE(serializer
->reading());
121 SerializerValues result
;
122 doValues(serializer
, &result
);
126 void checkSerializerValuesforEquality(const SerializerValues
& lhs
, const SerializerValues
& rhs
)
128 EXPECT_EQ(lhs
.boolValue_
, rhs
.boolValue_
);
129 EXPECT_EQ(lhs
.unsignedCharValue_
, rhs
.unsignedCharValue_
);
130 EXPECT_EQ(lhs
.charValue_
, rhs
.charValue_
);
131 EXPECT_EQ(lhs
.intValue_
, rhs
.intValue_
);
132 EXPECT_EQ(lhs
.int32Value_
, rhs
.int32Value_
);
133 EXPECT_EQ(lhs
.int64Value_
, rhs
.int64Value_
);
134 EXPECT_EQ(lhs
.unsignedShortValue_
, rhs
.unsignedShortValue_
);
135 EXPECT_EQ(lhs
.realValue_
, rhs
.realValue_
);
136 EXPECT_EQ(lhs
.floatValue_
, rhs
.floatValue_
);
137 EXPECT_EQ(lhs
.doubleValue_
, rhs
.doubleValue_
);
141 void doValues(ISerializer
* serializer
, SerializerValues
* values
)
143 serializer
->doBool(&values
->boolValue_
);
144 serializer
->doUChar(&values
->unsignedCharValue_
);
145 serializer
->doChar(&values
->charValue_
);
146 serializer
->doInt(&values
->intValue_
);
147 serializer
->doInt32(&values
->int32Value_
);
148 serializer
->doInt64(&values
->int64Value_
);
149 serializer
->doUShort(&values
->unsignedShortValue_
);
150 serializer
->doReal(&values
->realValue_
);
151 serializer
->doFloat(&values
->floatValue_
);
152 serializer
->doDouble(&values
->doubleValue_
);
156 SerializerValues defaultValues_
= { true,
159 static_cast<unsigned short>(c_int16Value
),
161 c_intAndFloat32
.floatValue_
,
163 c_intAndFloat64
.doubleValue_
,
164 integerSizeDependentTestingValue(),
165 std::is_same
<real
, double>::value
166 ? static_cast<real
>(c_intAndFloat64
.doubleValue_
)
167 : static_cast<real
>(c_intAndFloat32
.floatValue_
) };
169 SerializerValues endianessSwappedValues_
= {
173 static_cast<unsigned short>(c_int16ValueSwapped
),
175 c_intAndFloat32Swapped
.floatValue_
,
177 c_intAndFloat64Swapped
.doubleValue_
,
178 integerSizeDependentTestingValueEndianessSwapped(),
179 std::is_same
<real
, float>::value
? static_cast<real
>(c_intAndFloat32Swapped
.floatValue_
)
180 : static_cast<real
>(c_intAndFloat64Swapped
.doubleValue_
)
184 TEST_F(InMemorySerializerTest
, Roundtrip
)
186 InMemorySerializer serializer
;
187 SerializerValues values
= defaultValues_
;
188 serialize(&serializer
, &values
);
190 auto buffer
= serializer
.finishAndGetBuffer();
192 InMemoryDeserializer
deserializer(buffer
, std::is_same
<real
, double>::value
);
194 SerializerValues deserialisedValues
= deserialize(&deserializer
);
196 checkSerializerValuesforEquality(values
, deserialisedValues
);
199 TEST_F(InMemorySerializerTest
, RoundtripWithEndianessSwap
)
201 InMemorySerializer
serializerWithSwap(EndianSwapBehavior::Swap
);
202 SerializerValues values
= defaultValues_
;
203 serialize(&serializerWithSwap
, &values
);
205 auto buffer
= serializerWithSwap
.finishAndGetBuffer();
207 InMemoryDeserializer
deserializerWithSwap(buffer
, std::is_same
<real
, double>::value
,
208 EndianSwapBehavior::Swap
);
210 SerializerValues deserialisedValues
= deserialize(&deserializerWithSwap
);
212 checkSerializerValuesforEquality(values
, deserialisedValues
);
215 TEST_F(InMemorySerializerTest
, SerializerExplicitEndianessSwap
)
217 InMemorySerializer
serializerWithSwap(EndianSwapBehavior::Swap
);
218 SerializerValues values
= defaultValues_
;
219 serialize(&serializerWithSwap
, &values
);
221 auto buffer
= serializerWithSwap
.finishAndGetBuffer();
223 InMemoryDeserializer
deserializerWithOutSwap(buffer
, std::is_same
<real
, double>::value
);
225 SerializerValues deserialisedValues
= deserialize(&deserializerWithOutSwap
);
226 checkSerializerValuesforEquality(endianessSwappedValues_
, deserialisedValues
);
229 TEST_F(InMemorySerializerTest
, DeserializerExplicitEndianessSwap
)
231 InMemorySerializer serializer
;
232 SerializerValues values
= defaultValues_
;
233 serialize(&serializer
, &values
);
235 auto buffer
= serializer
.finishAndGetBuffer();
237 InMemoryDeserializer
deserializerWithSwap(buffer
, std::is_same
<real
, double>::value
,
238 EndianSwapBehavior::Swap
);
240 SerializerValues deserialisedValues
= deserialize(&deserializerWithSwap
);
241 checkSerializerValuesforEquality(endianessSwappedValues_
, deserialisedValues
);
244 TEST_F(InMemorySerializerTest
, SizeIsCorrect
)
246 InMemorySerializer serializer
;
247 // These types all have well-defined widths in bytes,
248 // which we can test below.
249 serializer
.doBool(&defaultValues_
.boolValue_
); // 1 bytes
250 serializer
.doChar(&defaultValues_
.charValue_
); // 1 bytes
251 serializer
.doInt32(&defaultValues_
.int32Value_
); // 4 bytes
252 serializer
.doInt64(&defaultValues_
.int64Value_
); // 8 bytes
253 serializer
.doFloat(&defaultValues_
.floatValue_
); // 4 bytes
254 serializer
.doDouble(&defaultValues_
.doubleValue_
); // 8 bytes
255 std::vector
<char> charBuffer
= { 'a', 'b', 'c' };
256 serializer
.doCharArray(charBuffer
.data(), charBuffer
.size()); // 3 bytes
257 serializer
.doOpaque(charBuffer
.data(), charBuffer
.size()); // 3 bytes
258 std::vector
<int32_t> int32Buffer
= { 0x1BCDEF78, 0x654321FE };
259 serializer
.doInt32Array(int32Buffer
.data(), int32Buffer
.size()); // 8 bytes
260 std::vector
<int64_t> int64Buffer
= { 0x1BCDEF78654321FE, 0x3726ABFEAB34716C };
261 serializer
.doInt64Array(int64Buffer
.data(), int64Buffer
.size()); // 16 bytes
262 auto buffer
= serializer
.finishAndGetBuffer();
263 EXPECT_EQ(buffer
.size(), 56);