test/zserio/AnyHolderTest.cpp
Line | Count | Source |
1 | | #include <vector> |
2 | | #include <memory> |
3 | | #include <tuple> |
4 | | |
5 | | #include "zserio/AnyHolder.h" |
6 | | #include "zserio/pmr/MemoryResource.h" |
7 | | #include "zserio/pmr/PolymorphicAllocator.h" |
8 | | |
9 | | #include "TrackingAllocator.h" |
10 | | |
11 | | #include "gtest/gtest.h" |
12 | | |
13 | | namespace zserio |
14 | | { |
15 | | |
16 | | namespace |
17 | | { |
18 | | |
19 | | class SmallObject |
20 | | { |
21 | | public: |
22 | 2 | SmallObject() : m_value(0) {} |
23 | | |
24 | 52 | bool operator==(const SmallObject& other) const { return m_value == other.m_value; } |
25 | | |
26 | | private: |
27 | | int m_value; |
28 | | }; |
29 | | |
30 | | struct BigObject |
31 | | { |
32 | 10 | BigObject() = default; |
33 | | |
34 | 13 | BigObject(NoInitT, const BigObject&) {} |
35 | | |
36 | | bool operator==(const BigObject& other) const |
37 | 60 | { |
38 | 60 | return std::tie(value1, value2, value3, value4) == |
39 | 60 | std::tie(other.value1, other.value2, other.value3, other.value4); |
40 | 60 | } |
41 | | |
42 | | uint64_t value1 = 1; |
43 | | uint64_t value2 = 2; |
44 | | uint64_t value3 = 3; |
45 | | uint64_t value4 = 4; |
46 | | }; |
47 | | |
48 | | } // namespace |
49 | | |
50 | | class AnyHolderTest : public ::testing::Test |
51 | | { |
52 | | protected: |
53 | | template <typename T, typename ALLOC> |
54 | | void testAnyHolder(const T& value, const ALLOC& allocator) |
55 | 8 | { |
56 | 8 | testEmptyConstructor<ALLOC>(); |
57 | 8 | testAllocatorConstructor(allocator); |
58 | 8 | testLvalueConstructor(value, allocator); |
59 | 8 | testLvalueConstructorNoInit(value, allocator); |
60 | 8 | testRvalueConstructor(value, allocator); |
61 | 8 | testRvalueConstructorNoInit(value, allocator); |
62 | 8 | testCopyConstructor(value, allocator); |
63 | 8 | testCopyConstructorNoInit(value, allocator); |
64 | 8 | testCopyConstructorWithAllocator(value, allocator); |
65 | 8 | testCopyConstructorWithAllocatorNoInit(value, allocator); |
66 | 8 | testCopyAssignmentOperator(value, allocator); |
67 | 8 | testCopyAssignmentOperatorNoInit(value, allocator); |
68 | 8 | testMoveConstructor(value, allocator); |
69 | 8 | testMoveConstructorNoInit(value, allocator); |
70 | 8 | testMoveConstructorWithAllocator(value, allocator); |
71 | 8 | testMoveConstructorWithAllocatorNoInit(value, allocator); |
72 | 8 | testMoveAssignmentOperator(value, allocator); |
73 | 8 | testMoveAssignmentOperatorNoInit(value, allocator); |
74 | 8 | testMoveAssignmentValueOperator(value, allocator); |
75 | 8 | testReset(value, allocator); |
76 | 8 | testSetGet(value, allocator); |
77 | 8 | testIsType(value, allocator); |
78 | 8 | testHasValue(value, allocator); |
79 | 8 | } |
80 | | |
81 | | private: |
82 | | template <typename ALLOC> |
83 | | void testEmptyConstructor() |
84 | 8 | { |
85 | 8 | AnyHolder<ALLOC> any; |
86 | 8 | ASSERT_FALSE(any.hasValue()); |
87 | 8 | } |
88 | | |
89 | | template <typename ALLOC> |
90 | | void testAllocatorConstructor(const ALLOC& allocator) |
91 | 8 | { |
92 | 8 | AnyHolder<ALLOC> any(allocator); |
93 | 8 | ASSERT_FALSE(any.hasValue()); |
94 | 8 | ASSERT_EQ(allocator, any.get_allocator()); |
95 | 8 | } |
96 | | |
97 | | template <typename T, typename ALLOC> |
98 | | void testLvalueConstructor(const T& value, const ALLOC& allocator) |
99 | 8 | { |
100 | 8 | const void* origAddress = &value; |
101 | 8 | AnyHolder<ALLOC> any(value, allocator); |
102 | | |
103 | 8 | const T& anyValue = any.template get<T>(); |
104 | 8 | ASSERT_NE(origAddress, &anyValue); |
105 | 8 | ASSERT_EQ(value, anyValue); |
106 | 8 | } |
107 | | |
108 | | template <typename T, typename ALLOC> |
109 | | void testLvalueConstructorNoInit(const T& value, const ALLOC& allocator) |
110 | 8 | { |
111 | 8 | const void* origAddress = &value; |
112 | 8 | AnyHolder<ALLOC> any(NoInit, value, allocator); |
113 | | |
114 | 8 | const T& anyValue = any.template get<T>(); |
115 | 8 | ASSERT_NE(origAddress, &anyValue); |
116 | 8 | ASSERT_EQ(value, anyValue); |
117 | 8 | } |
118 | | |
119 | | template <typename ALLOC> |
120 | | void testRvalueConstructor(const std::vector<int>& value, const ALLOC& allocator) |
121 | 2 | { |
122 | 2 | std::vector<int> origValue(value); |
123 | 2 | const void* origAddress = origValue.data(); |
124 | 2 | AnyHolder<ALLOC> any(std::move(origValue), allocator); |
125 | | |
126 | 2 | const std::vector<int>& anyValue = any.template get<std::vector<int>>(); |
127 | 2 | ASSERT_EQ(origAddress, anyValue.data()); |
128 | 2 | ASSERT_EQ(value, anyValue); |
129 | 2 | } |
130 | | |
131 | | template <typename T, typename ALLOC> |
132 | | void testRvalueConstructor(const T& value, const ALLOC& allocator) |
133 | 6 | { |
134 | 6 | T origValue(value); |
135 | 6 | AnyHolder<ALLOC> any(std::move(origValue), allocator); |
136 | | |
137 | 6 | const T& anyValue = any.template get<T>(); |
138 | 6 | ASSERT_EQ(value, anyValue); |
139 | 6 | } |
140 | | |
141 | | template <typename ALLOC> |
142 | | void testRvalueConstructorNoInit(const std::vector<int>& value, const ALLOC& allocator) |
143 | 2 | { |
144 | 2 | std::vector<int> origValue(value); |
145 | 2 | const void* origAddress = origValue.data(); |
146 | 2 | AnyHolder<ALLOC> any(NoInit, std::move(origValue), allocator); |
147 | | |
148 | 2 | const std::vector<int>& anyValue = any.template get<std::vector<int>>(); |
149 | 2 | ASSERT_EQ(origAddress, anyValue.data()); |
150 | 2 | ASSERT_EQ(value, anyValue); |
151 | 2 | } |
152 | | |
153 | | template <typename T, typename ALLOC> |
154 | | void testRvalueConstructorNoInit(const T& value, const ALLOC& allocator) |
155 | 6 | { |
156 | 6 | T origValue(value); |
157 | 6 | AnyHolder<ALLOC> any(NoInit, std::move(origValue), allocator); |
158 | | |
159 | 6 | const T& anyValue = any.template get<T>(); |
160 | 6 | ASSERT_EQ(value, anyValue); |
161 | 6 | } |
162 | | |
163 | | template <typename T, typename ALLOC> |
164 | | void testCopyConstructor(const T& value, const ALLOC& allocator) |
165 | 8 | { |
166 | 8 | AnyHolder<ALLOC> any(allocator); |
167 | | |
168 | | // copy empty holder |
169 | 8 | AnyHolder<ALLOC> anyEmptyCopy(any); |
170 | 8 | ASSERT_FALSE(anyEmptyCopy.hasValue()); |
171 | | |
172 | | // copy filled holder |
173 | 8 | any.set(value); |
174 | 8 | AnyHolder<ALLOC> anyCopy(any); |
175 | 8 | ASSERT_EQ(value, anyCopy.template get<T>()); |
176 | 8 | } |
177 | | |
178 | | template <typename T, typename ALLOC> |
179 | | void testCopyConstructorNoInit(const T& value, const ALLOC& allocator) |
180 | 8 | { |
181 | 8 | AnyHolder<ALLOC> any(allocator); |
182 | | |
183 | | // copy empty holder |
184 | 8 | AnyHolder<ALLOC> anyEmptyCopy(NoInit, any); |
185 | 8 | ASSERT_FALSE(anyEmptyCopy.hasValue()); |
186 | | |
187 | | // copy filled holder |
188 | 8 | any.set(value); |
189 | 8 | AnyHolder<ALLOC> anyCopy(NoInit, any); |
190 | 8 | ASSERT_EQ(value, anyCopy.template get<T>()); |
191 | 8 | } |
192 | | |
193 | | template <typename T, typename ALLOC> |
194 | | void testCopyConstructorWithAllocator(const T& value, const ALLOC& allocator) |
195 | 8 | { |
196 | 8 | AnyHolder<ALLOC> any(allocator); |
197 | | |
198 | | // copy empty holder |
199 | 8 | AnyHolder<ALLOC> anyEmptyCopy(any); |
200 | 8 | ASSERT_FALSE(anyEmptyCopy.hasValue()); |
201 | | |
202 | | // copy filled holder |
203 | 8 | any.set(value); |
204 | 8 | const size_t numAllocations = allocator.numAllocs(); |
205 | 8 | const ALLOC newAllocator; |
206 | 8 | AnyHolder<ALLOC> anyCopy(any, newAllocator); |
207 | 8 | ASSERT_EQ(value, anyCopy.template get<T>()); |
208 | 8 | ASSERT_EQ(numAllocations, allocator.numAllocs()); // no allocation and deallocations in old allocator |
209 | 8 | } |
210 | | |
211 | | template <typename T, typename ALLOC> |
212 | | void testCopyConstructorWithAllocatorNoInit(const T& value, const ALLOC& allocator) |
213 | 8 | { |
214 | 8 | AnyHolder<ALLOC> any(allocator); |
215 | | |
216 | | // copy empty holder |
217 | 8 | AnyHolder<ALLOC> anyEmptyCopy(NoInit, any); |
218 | 8 | ASSERT_FALSE(anyEmptyCopy.hasValue()); |
219 | | |
220 | | // copy filled holder |
221 | 8 | any.set(value); |
222 | 8 | const size_t numAllocations = allocator.numAllocs(); |
223 | 8 | const ALLOC newAllocator; |
224 | 8 | AnyHolder<ALLOC> anyCopy(NoInit, any, newAllocator); |
225 | 8 | ASSERT_EQ(value, anyCopy.template get<T>()); |
226 | 8 | ASSERT_EQ(numAllocations, allocator.numAllocs()); // no allocation and deallocations in old allocator |
227 | 8 | } |
228 | | |
229 | | template <typename T, typename ALLOC> |
230 | | void testCopyAssignmentOperator(const T& value, const ALLOC& allocator) |
231 | 8 | { |
232 | 8 | AnyHolder<ALLOC> any(allocator); |
233 | | |
234 | | // assignment empty holder |
235 | 8 | AnyHolder<ALLOC> anyEmpty; |
236 | 8 | anyEmpty = any; |
237 | 8 | ASSERT_FALSE(anyEmpty.hasValue()); |
238 | | |
239 | | // assignment filled holder to itself |
240 | 8 | any.set(value); |
241 | 8 | AnyHolder<ALLOC>& anyRef(any); |
242 | 8 | anyRef = any; |
243 | 8 | ASSERT_EQ(value, anyRef.template get<T>()); |
244 | | |
245 | | // assignment filled holder |
246 | 8 | AnyHolder<ALLOC> anyCopy; |
247 | 8 | anyCopy = any; |
248 | 8 | ASSERT_EQ(value, anyCopy.template get<T>()); |
249 | 8 | } |
250 | | |
251 | | template <typename T, typename ALLOC> |
252 | | void testCopyAssignmentOperatorNoInit(const T& value, const ALLOC& allocator) |
253 | 8 | { |
254 | 8 | AnyHolder<ALLOC> any(allocator); |
255 | | |
256 | | // assignment empty holder |
257 | 8 | AnyHolder<ALLOC> anyEmpty; |
258 | 8 | anyEmpty.assign(NoInit, any); |
259 | 8 | ASSERT_FALSE(anyEmpty.hasValue()); |
260 | | |
261 | | // assignment filled holder to itself |
262 | 8 | any.set(value); |
263 | 8 | AnyHolder<ALLOC>& anyRef(any); |
264 | 8 | anyRef.assign(NoInit, any); |
265 | 8 | ASSERT_EQ(value, anyRef.template get<T>()); |
266 | | |
267 | | // assignment filled holder |
268 | 8 | AnyHolder<ALLOC> anyCopy; |
269 | 8 | anyCopy.assign(NoInit, any); |
270 | 8 | ASSERT_EQ(value, anyCopy.template get<T>()); |
271 | 8 | } |
272 | | |
273 | | template <typename T, typename ALLOC> |
274 | | void testMoveConstructor(const T& value, const ALLOC& allocator) |
275 | 8 | { |
276 | 8 | { |
277 | | // move empty holder |
278 | 8 | AnyHolder<ALLOC> any(allocator); |
279 | 8 | AnyHolder<ALLOC> anyMove(std::move(any)); |
280 | 8 | ASSERT_FALSE(anyMove.hasValue()); |
281 | 8 | } |
282 | | |
283 | 8 | { |
284 | | // move filled holder |
285 | 8 | AnyHolder<ALLOC> any(allocator); |
286 | 8 | any.set(value); |
287 | 8 | const size_t numAllocations = allocator.numAllocs(); |
288 | 8 | AnyHolder<ALLOC> anyMove(std::move(any)); |
289 | 8 | ASSERT_EQ(value, anyMove.template get<T>()); |
290 | 8 | ASSERT_EQ(numAllocations, allocator.numAllocs()); // no allocations and deallocations |
291 | 8 | } |
292 | 8 | } |
293 | | |
294 | | template <typename T, typename ALLOC> |
295 | | void testMoveConstructorNoInit(const T& value, const ALLOC& allocator) |
296 | 8 | { |
297 | 8 | { |
298 | | // move empty holder |
299 | 8 | AnyHolder<ALLOC> any(allocator); |
300 | 8 | AnyHolder<ALLOC> anyMove(NoInit, std::move(any)); |
301 | 8 | ASSERT_FALSE(anyMove.hasValue()); |
302 | 8 | } |
303 | | |
304 | 8 | { |
305 | | // move filled holder |
306 | 8 | AnyHolder<ALLOC> any(allocator); |
307 | 8 | any.set(value); |
308 | 8 | const size_t numAllocations = allocator.numAllocs(); |
309 | 8 | AnyHolder<ALLOC> anyMove(NoInit, std::move(any)); |
310 | 8 | ASSERT_EQ(value, anyMove.template get<T>()); |
311 | 8 | ASSERT_EQ(numAllocations, allocator.numAllocs()); // no allocations and deallocations |
312 | 8 | } |
313 | 8 | } |
314 | | |
315 | | template <typename T, typename ALLOC> |
316 | | void testMoveConstructorWithAllocator(const T& value, const ALLOC& allocator) |
317 | 8 | { |
318 | 8 | { |
319 | | // empty holder with the same allocator |
320 | 8 | AnyHolder<ALLOC> any(allocator); |
321 | 8 | AnyHolder<ALLOC> anyMove(std::move(any)); |
322 | 8 | ASSERT_FALSE(anyMove.hasValue()); |
323 | 8 | } |
324 | | |
325 | 8 | { |
326 | | // empty holder with the different allocator |
327 | 8 | AnyHolder<ALLOC> any(allocator); |
328 | 8 | const ALLOC newAllocator; |
329 | 8 | AnyHolder<ALLOC> anyMove(std::move(any), newAllocator); |
330 | 8 | ASSERT_FALSE(anyMove.hasValue()); |
331 | 8 | } |
332 | | |
333 | 8 | { |
334 | | // filled holder with the same allocator |
335 | 8 | AnyHolder<ALLOC> any(allocator); |
336 | 8 | any.set(value); |
337 | 8 | const size_t numAllocations = allocator.numAllocs(); |
338 | 8 | AnyHolder<ALLOC> anyMove(std::move(any), allocator); |
339 | 8 | ASSERT_EQ(value, anyMove.template get<T>()); |
340 | 8 | ASSERT_EQ(numAllocations, allocator.numAllocs()); // no allocations and deallocations |
341 | 8 | } |
342 | | |
343 | 8 | { |
344 | | // filled holder with the different allocator |
345 | 8 | AnyHolder<ALLOC> any(allocator); |
346 | 8 | any.set(value); |
347 | 8 | const size_t numAllocations = allocator.numAllocs(); |
348 | 8 | const ALLOC newAllocator; |
349 | 8 | AnyHolder<ALLOC> anyMove(std::move(any), newAllocator); |
350 | 8 | ASSERT_EQ(value, anyMove.template get<T>()); |
351 | 8 | ASSERT_TRUE(numAllocations >= allocator.numAllocs()); // no furher allocations |
352 | 8 | } |
353 | 8 | } |
354 | | |
355 | | template <typename T, typename ALLOC> |
356 | | void testMoveConstructorWithAllocatorNoInit(const T& value, const ALLOC& allocator) |
357 | 8 | { |
358 | 8 | { |
359 | | // empty holder with the same allocator |
360 | 8 | AnyHolder<ALLOC> any(allocator); |
361 | 8 | AnyHolder<ALLOC> anyMove(NoInit, std::move(any)); |
362 | 8 | ASSERT_FALSE(anyMove.hasValue()); |
363 | 8 | } |
364 | | |
365 | 8 | { |
366 | | // empty holder with the different allocator |
367 | 8 | AnyHolder<ALLOC> any(allocator); |
368 | 8 | const ALLOC newAllocator; |
369 | 8 | AnyHolder<ALLOC> anyMove(NoInit, std::move(any), newAllocator); |
370 | 8 | ASSERT_FALSE(anyMove.hasValue()); |
371 | 8 | } |
372 | | |
373 | 8 | { |
374 | | // filled holder with the same allocator |
375 | 8 | AnyHolder<ALLOC> any(allocator); |
376 | 8 | any.set(value); |
377 | 8 | const size_t numAllocations = allocator.numAllocs(); |
378 | 8 | AnyHolder<ALLOC> anyMove(NoInit, std::move(any), allocator); |
379 | 8 | ASSERT_EQ(value, anyMove.template get<T>()); |
380 | 8 | ASSERT_EQ(numAllocations, allocator.numAllocs()); // no allocations and deallocations |
381 | 8 | } |
382 | | |
383 | 8 | { |
384 | | // filled holder with the different allocator |
385 | 8 | AnyHolder<ALLOC> any(allocator); |
386 | 8 | any.set(value); |
387 | 8 | const size_t numAllocations = allocator.numAllocs(); |
388 | 8 | const ALLOC newAllocator; |
389 | 8 | AnyHolder<ALLOC> anyMove(NoInit, std::move(any), newAllocator); |
390 | 8 | ASSERT_EQ(value, anyMove.template get<T>()); |
391 | 8 | ASSERT_TRUE(numAllocations >= allocator.numAllocs()); // no furher allocations |
392 | 8 | } |
393 | 8 | } |
394 | | |
395 | | template <typename T, typename ALLOC> |
396 | | void testMoveAssignmentOperator(const T& value, const ALLOC& allocator) |
397 | 8 | { |
398 | 8 | { |
399 | | // assignment empty holder |
400 | 8 | AnyHolder<ALLOC> any(allocator); |
401 | 8 | AnyHolder<ALLOC> anyMove; |
402 | 8 | anyMove = std::move(any); |
403 | 8 | ASSERT_FALSE(anyMove.hasValue()); |
404 | 8 | } |
405 | | |
406 | 8 | { |
407 | | // assignment filled holder to itself |
408 | 8 | AnyHolder<ALLOC> any(allocator); |
409 | 8 | any.set(value); |
410 | 8 | const size_t numAllocations = allocator.numAllocs(); |
411 | 8 | AnyHolder<ALLOC>& anyRef = any; |
412 | 8 | anyRef = std::move(any); |
413 | 8 | ASSERT_EQ(value, anyRef.template get<T>()); |
414 | 8 | ASSERT_EQ(numAllocations, allocator.numAllocs()); // no allocations and deallocations |
415 | 8 | } |
416 | | |
417 | 8 | { |
418 | | // assignment filled holder |
419 | 8 | AnyHolder<ALLOC> any(allocator); |
420 | 8 | any.set(value); |
421 | 8 | const size_t numAllocations = allocator.numAllocs(); |
422 | 8 | AnyHolder<ALLOC> anyMove; |
423 | 8 | anyMove = std::move(any); |
424 | 8 | ASSERT_EQ(value, anyMove.template get<T>()); |
425 | 8 | ASSERT_TRUE(numAllocations >= allocator.numAllocs()); // no furher allocations |
426 | 8 | } |
427 | 8 | } |
428 | | |
429 | | template <typename T, typename ALLOC> |
430 | | void testMoveAssignmentOperatorNoInit(const T& value, const ALLOC& allocator) |
431 | 8 | { |
432 | 8 | { |
433 | | // assignment empty holder |
434 | 8 | AnyHolder<ALLOC> any(allocator); |
435 | 8 | AnyHolder<ALLOC> anyMove; |
436 | 8 | anyMove.assign(NoInit, std::move(any)); |
437 | 8 | ASSERT_FALSE(anyMove.hasValue()); |
438 | 8 | } |
439 | | |
440 | 8 | { |
441 | | // assignment filled holder to itself |
442 | 8 | AnyHolder<ALLOC> any(allocator); |
443 | 8 | any.set(value); |
444 | 8 | const size_t numAllocations = allocator.numAllocs(); |
445 | 8 | AnyHolder<ALLOC>& anyRef = any; |
446 | 8 | anyRef.assign(NoInit, std::move(any)); |
447 | 8 | ASSERT_EQ(value, anyRef.template get<T>()); |
448 | 8 | ASSERT_EQ(numAllocations, allocator.numAllocs()); // no allocations and deallocations |
449 | 8 | } |
450 | | |
451 | 8 | { |
452 | | // assignment filled holder |
453 | 8 | AnyHolder<ALLOC> any(allocator); |
454 | 8 | any.set(value); |
455 | 8 | const size_t numAllocations = allocator.numAllocs(); |
456 | 8 | AnyHolder<ALLOC> anyMove; |
457 | 8 | anyMove.assign(NoInit, std::move(any)); |
458 | 8 | ASSERT_EQ(value, anyMove.template get<T>()); |
459 | 8 | ASSERT_TRUE(numAllocations >= allocator.numAllocs()); // no furher allocations |
460 | 8 | } |
461 | 8 | } |
462 | | |
463 | | template <typename T, typename ALLOC> |
464 | | void testMoveAssignmentValueOperator(const T& value, const ALLOC& allocator) |
465 | 8 | { |
466 | 8 | { |
467 | | // assignment empty holder |
468 | 8 | const T valueCopy(value); |
469 | 8 | AnyHolder<ALLOC> any(allocator); |
470 | 8 | const size_t numAllocations = allocator.numAllocs(); |
471 | 8 | AnyHolder<ALLOC> anyMove; |
472 | 8 | anyMove = std::move(valueCopy); |
473 | 8 | ASSERT_EQ(value, anyMove.template get<T>()); |
474 | 8 | ASSERT_EQ(numAllocations, allocator.numAllocs()); // no allocations and deallocations |
475 | 8 | } |
476 | | |
477 | 8 | { |
478 | | // assignment filled holder |
479 | 8 | const T valueCopy(value); |
480 | 8 | AnyHolder<ALLOC> any(allocator); |
481 | 8 | any.set(value); |
482 | 8 | const size_t numAllocations = allocator.numAllocs(); |
483 | 8 | AnyHolder<ALLOC> anyMove; |
484 | 8 | anyMove = std::move(valueCopy); |
485 | 8 | ASSERT_EQ(value, anyMove.template get<T>()); |
486 | 8 | ASSERT_EQ(numAllocations, allocator.numAllocs()); // no allocations and deallocations |
487 | 8 | } |
488 | 8 | } |
489 | | |
490 | | template <typename T, typename ALLOC> |
491 | | void testReset(const T& value, const ALLOC& allocator) |
492 | 8 | { |
493 | 8 | AnyHolder<ALLOC> any(value, allocator); |
494 | 8 | ASSERT_TRUE(any.hasValue()); |
495 | | |
496 | 8 | any.reset(); |
497 | 8 | ASSERT_FALSE(any.hasValue()); |
498 | | |
499 | 8 | any = value; |
500 | 8 | ASSERT_TRUE(any.hasValue()); |
501 | 8 | ASSERT_EQ(value, any.template get<T>()); |
502 | 8 | } |
503 | | |
504 | | template <typename T, typename ALLOC> |
505 | | void testSetGet(const T& value, const ALLOC& allocator) |
506 | 8 | { |
507 | 8 | AnyHolder<ALLOC> any(allocator); |
508 | 8 | ASSERT_THROW(any.template get<int>(), zserio::CppRuntimeException); |
509 | | |
510 | 8 | any.set(value); |
511 | 8 | ASSERT_EQ(value, any.template get<T>()); |
512 | | |
513 | 8 | const int intValue = 0xDEAD; |
514 | 8 | any.set(intValue); |
515 | 8 | ASSERT_EQ(intValue, any.template get<int>()); |
516 | 8 | ASSERT_THROW(any.template get<float>(), CppRuntimeException); |
517 | | |
518 | 8 | const float floatValue = 3.14F; |
519 | 8 | any.set(floatValue); |
520 | 8 | ASSERT_THROW(any.template get<int>(), CppRuntimeException); |
521 | 8 | ASSERT_EQ(floatValue, any.template get<float>()); |
522 | | |
523 | 8 | const BigObject bigObjectValue; |
524 | 8 | any.set(bigObjectValue); |
525 | 8 | ASSERT_THROW(any.template get<int>(), CppRuntimeException); |
526 | 8 | ASSERT_EQ(bigObjectValue, any.template get<BigObject>()); |
527 | 8 | } |
528 | | |
529 | | template <typename T, typename ALLOC> |
530 | | void testIsType(const T& value, const ALLOC& allocator) |
531 | 8 | { |
532 | 8 | AnyHolder<ALLOC> any(allocator); |
533 | 8 | ASSERT_FALSE(any.template isType<int>()); |
534 | | |
535 | 8 | any.set(value); |
536 | 8 | ASSERT_TRUE(any.template isType<T>()); |
537 | | |
538 | 8 | const int intValue = 0xDEAD; |
539 | 8 | any.set(intValue); |
540 | 8 | ASSERT_TRUE(any.template isType<int>()); |
541 | | |
542 | 8 | const float floatValue = 3.14F; |
543 | 8 | any.set(floatValue); |
544 | 8 | ASSERT_TRUE(any.template isType<float>()); |
545 | 8 | ASSERT_FALSE(any.template isType<int>()); |
546 | 8 | } |
547 | | |
548 | | template <typename T, typename ALLOC> |
549 | | void testHasValue(const T& value, const ALLOC& allocator) |
550 | 8 | { |
551 | 8 | AnyHolder<ALLOC> any(allocator); |
552 | 8 | ASSERT_FALSE(any.hasValue()); |
553 | | |
554 | 8 | any.set(value); |
555 | 8 | ASSERT_TRUE(any.hasValue()); |
556 | | |
557 | 8 | const int intValue = 0xDEAD; |
558 | 8 | any.set(intValue); |
559 | 8 | ASSERT_TRUE(any.hasValue()); |
560 | | |
561 | 8 | any.reset(); |
562 | 8 | ASSERT_FALSE(any.hasValue()); |
563 | 8 | } |
564 | | }; |
565 | | |
566 | | TEST_F(AnyHolderTest, integerPropagatingAllocator) |
567 | 1 | { |
568 | 1 | const int value = 0xDEAD; |
569 | 1 | const TrackingAllocator<uint8_t> allocator; |
570 | 1 | testAnyHolder(value, allocator); |
571 | 1 | } |
572 | | |
573 | | TEST_F(AnyHolderTest, integerNonPropagatingAllocator) |
574 | 1 | { |
575 | 1 | const int value = 0xDEAD; |
576 | 1 | const TrackingAllocatorNonProp<uint8_t> allocator; |
577 | 1 | testAnyHolder(value, allocator); |
578 | 1 | } |
579 | | |
580 | | TEST_F(AnyHolderTest, vectorPropagatingAllocator) |
581 | 1 | { |
582 | 1 | const std::vector<int> value{1, 2, 3}; |
583 | 1 | const TrackingAllocator<uint8_t> allocator; |
584 | 1 | testAnyHolder(value, allocator); |
585 | 1 | } |
586 | | |
587 | | TEST_F(AnyHolderTest, vectorNonPropagatingAllocator) |
588 | 1 | { |
589 | 1 | const std::vector<int> value{1, 2, 3}; |
590 | 1 | const TrackingAllocatorNonProp<uint8_t> allocator; |
591 | 1 | testAnyHolder(value, allocator); |
592 | 1 | } |
593 | | |
594 | | TEST_F(AnyHolderTest, smallObjectPropagatingAllocator) |
595 | 1 | { |
596 | 1 | const SmallObject value; |
597 | 1 | const TrackingAllocator<uint8_t> allocator; |
598 | 1 | testAnyHolder(value, allocator); |
599 | 1 | } |
600 | | |
601 | | TEST_F(AnyHolderTest, smallObjectNonPropagatingAllocator) |
602 | 1 | { |
603 | 1 | const SmallObject value; |
604 | 1 | const TrackingAllocatorNonProp<uint8_t> allocator; |
605 | 1 | testAnyHolder(value, allocator); |
606 | 1 | } |
607 | | |
608 | | TEST_F(AnyHolderTest, bigObjectPropagatingAllocator) |
609 | 1 | { |
610 | 1 | const BigObject value; |
611 | 1 | const TrackingAllocator<uint8_t> allocator; |
612 | 1 | testAnyHolder(value, allocator); |
613 | 1 | } |
614 | | |
615 | | TEST_F(AnyHolderTest, bigObjectNonPropagatingAllocator) |
616 | 1 | { |
617 | 1 | const BigObject value; |
618 | 1 | const TrackingAllocatorNonProp<uint8_t> allocator; |
619 | 1 | testAnyHolder(value, allocator); |
620 | 1 | } |
621 | | |
622 | | TEST_F(AnyHolderTest, unexceptedCallsHeapHolder) |
623 | 1 | { |
624 | 1 | const TrackingAllocator<uint8_t> allocator; |
625 | 1 | detail::HeapHolder<BigObject, TrackingAllocator<uint8_t>>* holder = |
626 | 1 | detail::HeapHolder<BigObject, TrackingAllocator<uint8_t>>::create(allocator); |
627 | 1 | ASSERT_THROW(holder->clone(nullptr), CppRuntimeException); |
628 | 1 | ASSERT_THROW(holder->clone(NoInit, nullptr), CppRuntimeException); |
629 | 1 | ASSERT_THROW(holder->move(nullptr), CppRuntimeException); |
630 | 1 | ASSERT_THROW(holder->move(NoInit, nullptr), CppRuntimeException); |
631 | 1 | holder->destroy(allocator); |
632 | 1 | } |
633 | | |
634 | | TEST_F(AnyHolderTest, unexceptedCallsNonHeapHolder) |
635 | 1 | { |
636 | 1 | const TrackingAllocator<uint8_t> allocator; |
637 | 1 | using MaxInPlaceType = std::aligned_storage<3 * sizeof(void*), alignof(void*)>::type; |
638 | 1 | MaxInPlaceType inPlace = MaxInPlaceType(); |
639 | 1 | detail::NonHeapHolder<uint8_t, TrackingAllocator<uint8_t>>* holder = |
640 | 1 | detail::NonHeapHolder<uint8_t, TrackingAllocator<uint8_t>>::create(&inPlace); |
641 | 1 | ASSERT_THROW(holder->clone(allocator), CppRuntimeException); |
642 | 1 | ASSERT_THROW(holder->clone(NoInit, allocator), CppRuntimeException); |
643 | 1 | ASSERT_THROW(holder->move(allocator), CppRuntimeException); |
644 | 1 | ASSERT_THROW(holder->move(NoInit, allocator), CppRuntimeException); |
645 | 1 | holder->destroy(allocator); |
646 | 1 | } |
647 | | |
648 | | } // namespace zserio |