Coverage Report

Created: 2023-12-13 14:58

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