test/zserio/InplaceOptionalHolderTest.cpp
Line | Count | Source |
1 | | #include <vector> |
2 | | |
3 | | #include "gtest/gtest.h" |
4 | | #include "zserio/OptionalHolder.h" |
5 | | |
6 | | namespace zserio |
7 | | { |
8 | | |
9 | | namespace |
10 | | { |
11 | | |
12 | | class DummyObject |
13 | | { |
14 | | public: |
15 | | DummyObject() : |
16 | | m_value(0), |
17 | | m_isNoInit(false) |
18 | 2 | {} |
19 | | explicit DummyObject(int value) : |
20 | | m_value(value), |
21 | | m_isNoInit(false) |
22 | 6 | {} |
23 | | explicit DummyObject(NoInitT, const DummyObject& other) : |
24 | | m_value(other.m_value), |
25 | | m_isNoInit(true) |
26 | 5 | {} |
27 | | int getValue() const |
28 | 8 | { |
29 | 8 | return m_value; |
30 | 8 | } |
31 | | void setValue(int value) |
32 | 2 | { |
33 | 2 | m_value = value; |
34 | 2 | } |
35 | | |
36 | | bool isNoInit() const |
37 | 9 | { |
38 | 9 | return m_isNoInit; |
39 | 9 | } |
40 | | |
41 | | bool operator==(const DummyObject& other) const |
42 | 3 | { |
43 | 3 | return m_value == other.m_value; |
44 | 3 | } |
45 | | |
46 | | private: |
47 | | int m_value; |
48 | | bool m_isNoInit; |
49 | | }; |
50 | | |
51 | | } // namespace |
52 | | |
53 | | class InplaceOptionalHolderTest : public ::testing::Test |
54 | | { |
55 | | protected: |
56 | | }; |
57 | | |
58 | | TEST_F(InplaceOptionalHolderTest, emptyConstructor) |
59 | 1 | { |
60 | 1 | InplaceOptionalHolder<int> optional; |
61 | 1 | ASSERT_FALSE(optional.hasValue()); |
62 | 1 | } |
63 | | |
64 | | TEST_F(InplaceOptionalHolderTest, nullOptConstructor) |
65 | 1 | { |
66 | 1 | { |
67 | 1 | NullOptType nullOpt{int()}; |
68 | 1 | InplaceOptionalHolder<int> optional{nullOpt}; |
69 | 1 | ASSERT_FALSE(optional.hasValue()); |
70 | 1 | } |
71 | | |
72 | 1 | { |
73 | 1 | InplaceOptionalHolder<int> optional{NullOpt}; |
74 | 1 | ASSERT_FALSE(optional.hasValue()); |
75 | 1 | } |
76 | 1 | } |
77 | | |
78 | | TEST_F(InplaceOptionalHolderTest, lvalueConstructor) |
79 | 1 | { |
80 | 1 | std::vector<int> values{1, 2, 3}; |
81 | 1 | void* origAddress = values.data(); |
82 | 1 | InplaceOptionalHolder<std::vector<int>> optional{values}; |
83 | 1 | ASSERT_NE(origAddress, (*optional).data()); |
84 | 1 | ASSERT_EQ(values, *optional); |
85 | | |
86 | | // check initializer list |
87 | 1 | InplaceOptionalHolder<std::vector<int>> optionalFromList{{1, 2, 3}}; |
88 | 1 | std::vector<int> listValues{1, 2, 3}; |
89 | 1 | ASSERT_EQ(listValues, *optionalFromList); |
90 | 1 | } |
91 | | |
92 | | TEST_F(InplaceOptionalHolderTest, rvalueConstructor) |
93 | 1 | { |
94 | 1 | std::vector<int> values{1, 2, 3}; |
95 | 1 | std::vector<int> origValues{values}; |
96 | 1 | void* origAddress = values.data(); |
97 | 1 | InplaceOptionalHolder<std::vector<int>> optional{std::move(values)}; |
98 | 1 | ASSERT_EQ(origAddress, (*optional).data()); |
99 | 1 | ASSERT_EQ(origValues, *optional); |
100 | 1 | } |
101 | | |
102 | | TEST_F(InplaceOptionalHolderTest, copyConstructor) |
103 | 1 | { |
104 | 1 | InplaceOptionalHolder<int> optional; |
105 | 1 | ASSERT_THROW(*optional, CppRuntimeException); |
106 | 1 | const int intValue = 0xDEAD; |
107 | 1 | optional = intValue; |
108 | | |
109 | 1 | InplaceOptionalHolder<int> optionalCopy(optional); |
110 | 1 | ASSERT_EQ(intValue, *optionalCopy); |
111 | | |
112 | 1 | InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}}; |
113 | 1 | void* origAddress = (*optionalVector).data(); |
114 | 1 | InplaceOptionalHolder<std::vector<int>> optionalVectorCopy{optionalVector}; |
115 | 1 | ASSERT_NE(origAddress, (*optionalVectorCopy).data()); |
116 | 1 | ASSERT_EQ(*optionalVector, *optionalVectorCopy); |
117 | | |
118 | 1 | InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10}); |
119 | 1 | InplaceOptionalHolder<DummyObject> optionalObjectCopy = optionalObject; |
120 | 1 | ASSERT_EQ(optionalObject, optionalObjectCopy); |
121 | 1 | } |
122 | | |
123 | | TEST_F(InplaceOptionalHolderTest, copyConstructorNoInit) |
124 | 1 | { |
125 | 1 | InplaceOptionalHolder<DummyObject> optionalEmptyObject; |
126 | 1 | InplaceOptionalHolder<DummyObject> optionalEmptyObjectCopy{NoInit, optionalEmptyObject}; |
127 | 1 | ASSERT_EQ(optionalEmptyObject, optionalEmptyObjectCopy); |
128 | | |
129 | 1 | InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10}); |
130 | 1 | InplaceOptionalHolder<DummyObject> optionalObjectCopy{NoInit, optionalObject}; |
131 | 1 | ASSERT_EQ(optionalObject, optionalObjectCopy); |
132 | 1 | ASSERT_FALSE(optionalObject->isNoInit()); |
133 | 1 | ASSERT_TRUE(optionalObjectCopy->isNoInit()); |
134 | 1 | } |
135 | | |
136 | | TEST_F(InplaceOptionalHolderTest, copyAssignmentOperator) |
137 | 1 | { |
138 | 1 | InplaceOptionalHolder<int> optional; |
139 | 1 | ASSERT_THROW(*optional, CppRuntimeException); |
140 | 1 | const int intValue = 0xDEAD; |
141 | 1 | optional = intValue; |
142 | | |
143 | 1 | InplaceOptionalHolder<int>& optionalRef(optional); |
144 | 1 | optionalRef = optional; |
145 | 1 | ASSERT_EQ(intValue, *optionalRef); |
146 | | |
147 | 1 | InplaceOptionalHolder<int> optionalCopy; |
148 | 1 | optionalCopy = optional; |
149 | 1 | ASSERT_EQ(intValue, *optionalCopy); |
150 | | |
151 | 1 | InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}}; |
152 | 1 | void* origAddress = (*optionalVector).data(); |
153 | 1 | InplaceOptionalHolder<std::vector<int>> optionalVectorCopy; |
154 | 1 | optionalVectorCopy = optionalVector; |
155 | 1 | ASSERT_NE(origAddress, ((*optionalVectorCopy).data())); |
156 | 1 | ASSERT_EQ(*optionalVector, *optionalVectorCopy); |
157 | | |
158 | 1 | InplaceOptionalHolder<std::vector<int>> emptyOptionalVector; |
159 | 1 | InplaceOptionalHolder<std::vector<int>> emptyOptionalVectorCopy; |
160 | 1 | emptyOptionalVectorCopy = emptyOptionalVector; |
161 | 1 | ASSERT_EQ(false, emptyOptionalVectorCopy.hasValue()); |
162 | 1 | } |
163 | | |
164 | | TEST_F(InplaceOptionalHolderTest, copyAssignmentOperatorNoInit) |
165 | 1 | { |
166 | 1 | InplaceOptionalHolder<DummyObject> optionalEmptyObject; |
167 | 1 | InplaceOptionalHolder<DummyObject> optionalEmptyObjectCopy; |
168 | 1 | optionalEmptyObjectCopy.assign(NoInit, optionalEmptyObject); |
169 | 1 | ASSERT_EQ(optionalEmptyObject, optionalEmptyObjectCopy); |
170 | | |
171 | 1 | InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10}); |
172 | 1 | optionalObject.assign(NoInit, optionalObject); |
173 | | |
174 | 1 | InplaceOptionalHolder<DummyObject> optionalObjectCopy; |
175 | 1 | optionalObjectCopy.assign(NoInit, optionalObject); |
176 | 1 | ASSERT_EQ(optionalObject, optionalObjectCopy); |
177 | 1 | ASSERT_FALSE(optionalObject->isNoInit()); |
178 | 1 | ASSERT_TRUE(optionalObjectCopy->isNoInit()); |
179 | 1 | } |
180 | | |
181 | | TEST_F(InplaceOptionalHolderTest, moveConstructor) |
182 | 1 | { |
183 | 1 | InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}}; |
184 | 1 | std::vector<int> origValues{*optionalVector}; |
185 | 1 | void* origAddress = (*optionalVector).data(); |
186 | 1 | InplaceOptionalHolder<std::vector<int>> optionalVectorMoved{std::move(optionalVector)}; |
187 | 1 | ASSERT_EQ(origAddress, ((*optionalVectorMoved).data())); |
188 | 1 | ASSERT_EQ(origValues, *optionalVectorMoved); |
189 | | |
190 | 1 | InplaceOptionalHolder<std::vector<int>> emptyOptionalVector; |
191 | 1 | InplaceOptionalHolder<std::vector<int>> emptyOptionalVectorMoved{std::move(emptyOptionalVector)}; |
192 | 1 | ASSERT_EQ(false, emptyOptionalVectorMoved.hasValue()); |
193 | | |
194 | 1 | InplaceOptionalHolder<int> optionalInt{1}; |
195 | 1 | InplaceOptionalHolder<int> optionalIntMoved{std::move(optionalInt)}; |
196 | 1 | ASSERT_EQ(1, *optionalIntMoved); |
197 | | |
198 | 1 | InplaceOptionalHolder<int> emptyOptionalInt; |
199 | 1 | InplaceOptionalHolder<int> emptyOptionalIntMoved{std::move(emptyOptionalInt)}; |
200 | 1 | ASSERT_EQ(false, emptyOptionalIntMoved.hasValue()); |
201 | 1 | } |
202 | | |
203 | | TEST_F(InplaceOptionalHolderTest, moveConstructorNoInit) |
204 | 1 | { |
205 | 1 | InplaceOptionalHolder<DummyObject> optionalEmptyObject; |
206 | 1 | InplaceOptionalHolder<DummyObject> optionalEmptyObjectMoved{NoInit, std::move(optionalEmptyObject)}; |
207 | 1 | ASSERT_FALSE(optionalEmptyObjectMoved.hasValue()); |
208 | | |
209 | 1 | InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10}); |
210 | 1 | ASSERT_EQ(10, optionalObject->getValue()); |
211 | 1 | ASSERT_FALSE(optionalObject->isNoInit()); |
212 | | |
213 | 1 | InplaceOptionalHolder<DummyObject> optionalObjectMoved{NoInit, std::move(optionalObject)}; |
214 | 1 | ASSERT_EQ(10, optionalObjectMoved->getValue()); |
215 | 1 | ASSERT_TRUE(optionalObjectMoved->isNoInit()); |
216 | 1 | } |
217 | | |
218 | | TEST_F(InplaceOptionalHolderTest, moveValueConstructorNoInit) |
219 | 1 | { |
220 | 1 | InplaceOptionalHolder<DummyObject> optionalObjectMoved{NoInit, DummyObject{10}}; |
221 | 1 | ASSERT_EQ(10, optionalObjectMoved->getValue()); |
222 | 1 | ASSERT_TRUE(optionalObjectMoved->isNoInit()); |
223 | 1 | } |
224 | | |
225 | | TEST_F(InplaceOptionalHolderTest, forwardingConstructor) |
226 | 1 | { |
227 | 1 | { |
228 | 1 | InPlaceT inPlace{}; |
229 | 1 | std::vector<int> src = {0, 13, 42}; |
230 | 1 | InplaceOptionalHolder<std::vector<int>> optional{inPlace, src.begin(), src.end()}; |
231 | 1 | ASSERT_EQ(src, *optional); |
232 | 1 | } |
233 | | |
234 | 1 | { |
235 | 1 | std::vector<int> src = {0, 13, 42}; |
236 | 1 | InplaceOptionalHolder<std::vector<int>> optional{InPlace, src.begin(), src.end()}; |
237 | 1 | ASSERT_EQ(src, *optional); |
238 | 1 | } |
239 | 1 | } |
240 | | |
241 | | TEST_F(InplaceOptionalHolderTest, moveAssignmentOperator) |
242 | 1 | { |
243 | 1 | InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}}; |
244 | 1 | std::vector<int> origValues{*optionalVector}; |
245 | 1 | void* origAddress = (*optionalVector).data(); |
246 | | |
247 | 1 | InplaceOptionalHolder<std::vector<int>>& optionalVectorRef(optionalVector); |
248 | 1 | optionalVectorRef = std::move(optionalVector); |
249 | 1 | ASSERT_EQ(origAddress, (*optionalVectorRef).data()); |
250 | 1 | ASSERT_EQ(origValues, *optionalVectorRef); |
251 | | |
252 | 1 | InplaceOptionalHolder<std::vector<int>> optionalVectorMoved; |
253 | 1 | optionalVectorMoved = std::move(optionalVectorRef); |
254 | 1 | ASSERT_EQ(origAddress, (*optionalVectorMoved).data()); |
255 | 1 | ASSERT_EQ(origValues, *optionalVectorMoved); |
256 | | |
257 | 1 | InplaceOptionalHolder<std::vector<int>> emptyOptionalVector; |
258 | 1 | InplaceOptionalHolder<std::vector<int>> emptyOptionalVectorMoved; |
259 | 1 | emptyOptionalVectorMoved = std::move(emptyOptionalVector); |
260 | 1 | ASSERT_EQ(false, emptyOptionalVectorMoved.hasValue()); |
261 | 1 | } |
262 | | |
263 | | TEST_F(InplaceOptionalHolderTest, moveAssignmentOperatorNoInit) |
264 | 1 | { |
265 | 1 | InplaceOptionalHolder<DummyObject> optionalEmptyObject; |
266 | 1 | InplaceOptionalHolder<DummyObject> optionalEmptyObjectMoved; |
267 | 1 | optionalEmptyObjectMoved.assign(NoInit, std::move(optionalEmptyObject)); |
268 | 1 | ASSERT_FALSE(optionalEmptyObjectMoved.hasValue()); |
269 | | |
270 | 1 | InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10}); |
271 | 1 | ASSERT_EQ(10, optionalObject->getValue()); |
272 | 1 | ASSERT_FALSE(optionalObject->isNoInit()); |
273 | 1 | optionalObject.assign(NoInit, std::move(optionalObject)); |
274 | | |
275 | 1 | InplaceOptionalHolder<DummyObject> optionalObjectMoved; |
276 | 1 | optionalObjectMoved.assign(NoInit, std::move(optionalObject)); |
277 | 1 | ASSERT_EQ(10, optionalObjectMoved->getValue()); |
278 | | // memory with object has been moved in optional holder, object move constructor has not been called |
279 | 1 | ASSERT_TRUE(optionalObjectMoved->isNoInit()); |
280 | 1 | } |
281 | | |
282 | | TEST_F(InplaceOptionalHolderTest, lvalueAssignmentOperator) |
283 | 1 | { |
284 | 1 | std::vector<int> values{1, 2, 3}; |
285 | 1 | void* origAddress = values.data(); |
286 | 1 | InplaceOptionalHolder<std::vector<int>> optional; |
287 | 1 | optional = values; |
288 | 1 | ASSERT_NE(origAddress, (*optional).data()); |
289 | 1 | ASSERT_EQ(values, *optional); |
290 | 1 | } |
291 | | |
292 | | TEST_F(InplaceOptionalHolderTest, rvalueAssignmentOperator) |
293 | 1 | { |
294 | 1 | std::vector<int> values{1, 2, 3}; |
295 | 1 | std::vector<int> origValues{values}; |
296 | 1 | void* origAddress = values.data(); |
297 | 1 | InplaceOptionalHolder<std::vector<int>> optional; |
298 | 1 | optional = std::move(values); |
299 | 1 | ASSERT_EQ(origAddress, (*optional).data()); |
300 | 1 | ASSERT_EQ(origValues, *optional); |
301 | 1 | } |
302 | | |
303 | | TEST_F(InplaceOptionalHolderTest, reset) |
304 | 1 | { |
305 | 1 | InplaceOptionalHolder<std::vector<int>> optional{std::vector<int>{1, 2, 3}}; |
306 | 1 | ASSERT_TRUE(optional.hasValue()); |
307 | 1 | ASSERT_EQ(1, (*optional)[0]); |
308 | | |
309 | 1 | optional.reset(); |
310 | 1 | ASSERT_FALSE(optional.hasValue()); |
311 | | |
312 | 1 | optional = std::vector<int>{3, 2, 1}; |
313 | 1 | ASSERT_TRUE(optional.hasValue()); |
314 | 1 | ASSERT_EQ(3, (*optional)[0]); |
315 | | |
316 | 1 | optional.reset(); |
317 | 1 | ASSERT_FALSE(optional.hasValue()); |
318 | 1 | } |
319 | | |
320 | | TEST_F(InplaceOptionalHolderTest, operatorEquality) |
321 | 1 | { |
322 | 1 | InplaceOptionalHolder<int> optional1; |
323 | 1 | optional1 = 0xDEAD; |
324 | 1 | InplaceOptionalHolder<int> optional2; |
325 | 1 | optional2 = 0xDEAD; |
326 | 1 | InplaceOptionalHolder<int> optional3; |
327 | 1 | optional3 = 0xBEEF; |
328 | 1 | InplaceOptionalHolder<int> optional4; |
329 | 1 | InplaceOptionalHolder<int> optional5; |
330 | 1 | InplaceOptionalHolder<int> optional6; |
331 | | |
332 | 1 | ASSERT_TRUE(optional1 == optional1); |
333 | 1 | ASSERT_TRUE(optional1 == optional2); |
334 | 1 | ASSERT_FALSE(optional1 == optional3); |
335 | 1 | ASSERT_FALSE(optional1 == optional4); |
336 | 1 | ASSERT_TRUE(optional5 == optional6); |
337 | 1 | ASSERT_FALSE(optional5 == optional1); |
338 | 1 | } |
339 | | |
340 | | TEST_F(InplaceOptionalHolderTest, operatorLessThan) |
341 | 1 | { |
342 | 1 | InplaceOptionalHolder<int> optionalEmpty1; |
343 | 1 | InplaceOptionalHolder<int> optionalEmpty2; |
344 | 1 | InplaceOptionalHolder<int> optional1(1); |
345 | 1 | InplaceOptionalHolder<int> optional2(2); |
346 | | |
347 | 1 | ASSERT_FALSE(optionalEmpty1 < optionalEmpty2); |
348 | 1 | ASSERT_TRUE(optionalEmpty1 < optional1); |
349 | 1 | ASSERT_FALSE(optional1 < optionalEmpty1); |
350 | 1 | ASSERT_TRUE(optional1 < optional2); |
351 | 1 | ASSERT_FALSE(optional2 < optional1); |
352 | 1 | } |
353 | | |
354 | | TEST_F(InplaceOptionalHolderTest, setGet) |
355 | 1 | { |
356 | 1 | InplaceOptionalHolder<int> optionalInt; |
357 | 1 | ASSERT_THROW(*optionalInt, CppRuntimeException); |
358 | 1 | const int intValue = 0xDEAD; |
359 | 1 | optionalInt = intValue; |
360 | 1 | ASSERT_EQ(intValue, *optionalInt); |
361 | | |
362 | 1 | InplaceOptionalHolder<float> optionalFloat; |
363 | 1 | ASSERT_THROW(*optionalFloat, CppRuntimeException); |
364 | 1 | const float floatValue = 3.14F; |
365 | 1 | optionalFloat = floatValue; |
366 | 1 | ASSERT_EQ(floatValue, optionalFloat.value()); |
367 | | |
368 | 1 | InplaceOptionalHolder<DummyObject> optionalObject; |
369 | 1 | ASSERT_THROW(*optionalObject, CppRuntimeException); |
370 | 1 | DummyObject objectValue; |
371 | 1 | objectValue.setValue(intValue); |
372 | 1 | optionalObject = objectValue; |
373 | 1 | const DummyObject& readObjectValue = *optionalObject; |
374 | 1 | ASSERT_EQ(intValue, readObjectValue.getValue()); |
375 | 1 | ASSERT_EQ(intValue, optionalObject->getValue()); |
376 | 1 | } |
377 | | |
378 | | TEST_F(InplaceOptionalHolderTest, hasValue) |
379 | 1 | { |
380 | 1 | InplaceOptionalHolder<int> optionalInt; |
381 | 1 | ASSERT_THROW(*optionalInt, CppRuntimeException); |
382 | 1 | ASSERT_EQ(false, optionalInt.hasValue()); |
383 | | |
384 | 1 | optionalInt = 0xDEAD; |
385 | 1 | ASSERT_EQ(true, optionalInt.hasValue()); |
386 | 1 | } |
387 | | |
388 | | TEST_F(InplaceOptionalHolderTest, constGet) |
389 | 1 | { |
390 | 1 | const int intValue = 0xDEAD; |
391 | 1 | InplaceOptionalHolder<int> optional; |
392 | 1 | optional = intValue; |
393 | 1 | const InplaceOptionalHolder<int> constOptional(optional); |
394 | 1 | ASSERT_EQ(intValue, *constOptional); |
395 | 1 | ASSERT_EQ(intValue, constOptional.value()); |
396 | | |
397 | 1 | DummyObject objectValue; |
398 | 1 | objectValue.setValue(intValue); |
399 | 1 | InplaceOptionalHolder<DummyObject> optionalObject{objectValue}; |
400 | 1 | ASSERT_EQ(intValue, optionalObject->getValue()); |
401 | 1 | } |
402 | | |
403 | | } // namespace zserio |