Coverage Report

Created: 2023-12-13 14:58

test/zserio/HeapOptionalHolderTest.cpp
Line
Count
Source
1
#include "zserio/OptionalHolder.h"
2
#include "zserio/pmr/PolymorphicAllocator.h"
3
4
#include "TrackingAllocator.h"
5
6
#include "gtest/gtest.h"
7
8
namespace zserio
9
{
10
11
namespace
12
{
13
14
class DummyObject
15
{
16
public:
17
2
    DummyObject() : m_value(0), m_isNoInit(false) {}
18
7
    explicit DummyObject(int value) : m_value(value), m_isNoInit(false) {}
19
4
    explicit DummyObject(NoInitT, const DummyObject& other) : m_value(other.m_value), m_isNoInit(true) {}
20
10
    int getValue() const { return m_value; }
21
2
    void setValue(int value) { m_value = value; }
22
23
11
    bool isNoInit() const { return m_isNoInit; }
24
25
3
    bool operator==(const DummyObject& other) const { return m_value == other.m_value; }
26
27
private:
28
    int m_value;
29
    bool m_isNoInit;
30
};
31
32
} // namespace
33
34
class HeapOptionalHolderTest : public ::testing::Test
35
{
36
protected:
37
};
38
39
TEST_F(HeapOptionalHolderTest, emptyConstructor)
40
1
{
41
1
    TrackingAllocator<int> alloc;
42
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optional{alloc};
43
1
    ASSERT_EQ(alloc, optional.get_allocator());
44
1
}
45
46
TEST_F(HeapOptionalHolderTest, nullOptConstructor)
47
1
{
48
1
    {
49
1
        NullOptType nullOpt{int()};
50
1
        TrackingAllocator<int> alloc;
51
1
        HeapOptionalHolder<int, TrackingAllocator<int>> optional{nullOpt, alloc};
52
1
        ASSERT_EQ(alloc, optional.get_allocator());
53
1
    }
54
55
1
    {
56
1
        TrackingAllocator<int> alloc;
57
1
        HeapOptionalHolder<int, TrackingAllocator<int>> optional{NullOpt, alloc};
58
1
        ASSERT_EQ(alloc, optional.get_allocator());
59
1
    }
60
1
}
61
62
TEST_F(HeapOptionalHolderTest, lvalueConstructor)
63
1
{
64
1
    TrackingAllocator<std::vector<int>> alloc;
65
66
1
    std::vector<int> values{1, 2, 3};
67
1
    void* origAddress = values.data();
68
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optional{values, alloc};
69
1
    ASSERT_NE(origAddress, (*optional).data());
70
1
    ASSERT_EQ(values, *optional);
71
72
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalFromList{
73
1
            {1, 2, 3}, alloc};
74
1
    std::vector<int> listValues{1, 2, 3};
75
1
    ASSERT_EQ(listValues, *optionalFromList);
76
77
1
    ASSERT_GE(alloc.numAllocs(), 2U);
78
1
}
79
80
TEST_F(HeapOptionalHolderTest, rvalueConstructor)
81
1
{
82
1
    TrackingAllocator<std::vector<int>> alloc;
83
84
1
    std::vector<int> values{1, 2, 3};
85
1
    std::vector<int> origValues{ values };
86
1
    void* origAddress = values.data();
87
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optional{
88
1
            std::move(values), alloc};
89
1
    ASSERT_EQ(origAddress, (*optional).data());
90
1
    ASSERT_EQ(origValues, *optional);
91
92
1
    ASSERT_GE(alloc.numAllocs(), 1U);
93
1
}
94
95
TEST_F(HeapOptionalHolderTest, forwardingConstructor)
96
1
{
97
1
    TrackingAllocator<std::vector<int>> alloc;
98
99
1
    std::vector<int> src = {0, 13, 42};
100
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optional{
101
1
            alloc, src.begin(), src.end()};
102
1
    ASSERT_EQ(src, *optional);
103
104
1
    ASSERT_GE(alloc.numAllocs(), 1U);
105
1
}
106
107
TEST_F(HeapOptionalHolderTest, copyConstructor)
108
1
{
109
1
    TrackingAllocator<int> alloc;
110
1
    TrackingAllocator<std::vector<int>> allocVec = alloc;
111
112
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optional(alloc);
113
1
    ASSERT_THROW(*optional, CppRuntimeException);
114
1
    const int intValue = 0xDEAD;
115
1
    optional = intValue;
116
117
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalCopy(optional);
118
1
    ASSERT_EQ(intValue, *optionalCopy);
119
1
    ASSERT_EQ(optional.get_allocator(), optionalCopy.get_allocator());
120
121
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObject(DummyObject{10});
122
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObjectCopy = optionalObject;
123
1
    ASSERT_EQ(optionalObject, optionalObjectCopy);
124
1
    ASSERT_EQ(optionalObject.get_allocator(), optionalObjectCopy.get_allocator());
125
126
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVector{
127
1
            std::vector<int>{1, 2, 3}, allocVec};
128
1
    void* origAddress = (*optionalVector).data();
129
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVectorCopy{
130
1
            optionalVector};
131
1
    ASSERT_NE(origAddress, (*optionalVectorCopy).data());
132
1
    ASSERT_EQ(*optionalVector, *optionalVectorCopy);
133
1
    ASSERT_EQ(optionalVector.get_allocator(), optionalVectorCopy.get_allocator());
134
135
1
    ASSERT_GE(alloc.numAllocs(), 2U);
136
137
1
    TrackingAllocatorNonProp<int> allocNp;
138
1
    HeapOptionalHolder<int, TrackingAllocatorNonProp<int>> optionalNp(allocNp);
139
1
    HeapOptionalHolder<int, TrackingAllocatorNonProp<int>> optionalNpCopy = optionalNp;
140
1
    ASSERT_NE(optionalNp.get_allocator(), optionalNpCopy.get_allocator());
141
1
}
142
143
TEST_F(HeapOptionalHolderTest, copyConstructorNoInit)
144
1
{
145
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObject;
146
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObjectCopy{NoInit,
147
1
        optionalEmptyObject};
148
1
    ASSERT_EQ(optionalEmptyObject, optionalEmptyObjectCopy);
149
150
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObject(DummyObject{10});
151
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObjectCopy{NoInit, optionalObject};
152
1
    ASSERT_EQ(optionalObject, optionalObjectCopy);
153
1
    ASSERT_FALSE(optionalObject->isNoInit());
154
1
    ASSERT_TRUE(optionalObjectCopy->isNoInit());
155
1
}
156
157
TEST_F(HeapOptionalHolderTest, copyConstructorAllocator)
158
1
{
159
1
    TrackingAllocator<int> alloc1;
160
1
    TrackingAllocator<std::vector<int>> allocVec1 = alloc1;
161
1
    TrackingAllocator<int> alloc2;
162
1
    TrackingAllocator<std::vector<int>> allocVec2 = alloc2;
163
164
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optional(alloc1);
165
1
    ASSERT_THROW(*optional, CppRuntimeException);
166
167
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalCopy(optional, alloc2);
168
1
    ASSERT_NE(optional.get_allocator(), optionalCopy.get_allocator());
169
1
    ASSERT_EQ(optional.get_allocator(), alloc1);
170
1
    ASSERT_EQ(optionalCopy.get_allocator(), alloc2);
171
172
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVector{
173
1
            std::vector<int>{1, 2, 3}, allocVec1};
174
1
    void* origAddress = (*optionalVector).data();
175
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVectorCopy{
176
1
            optionalVector, allocVec2};
177
1
    ASSERT_NE(origAddress, (*optionalVectorCopy).data());
178
1
    ASSERT_EQ(*optionalVector, *optionalVectorCopy);
179
1
    ASSERT_NE(optionalVector.get_allocator(), optionalVectorCopy.get_allocator());
180
1
    ASSERT_EQ(optionalVector.get_allocator(), allocVec1);
181
1
    ASSERT_EQ(optionalVectorCopy.get_allocator(), allocVec2);
182
183
1
    ASSERT_GE(alloc1.numAllocs(), 1U);
184
1
    ASSERT_GE(alloc2.numAllocs(), 1U);
185
1
}
186
187
TEST_F(HeapOptionalHolderTest, moveConstructor)
188
1
{
189
1
    TrackingAllocator<int> alloc;
190
191
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optional(13, alloc);
192
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalMoved(std::move(optional));
193
194
1
    ASSERT_EQ(*optionalMoved, 13);
195
1
    ASSERT_EQ(optionalMoved.get_allocator(), alloc);
196
1
    ASSERT_FALSE(optional.hasValue());
197
1
    ASSERT_EQ(alloc.numAllocs(), 1U);
198
1
}
199
200
TEST_F(HeapOptionalHolderTest, moveConstructorNoInit)
201
1
{
202
1
    TrackingAllocator<DummyObject> allocEmpty;
203
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObject(allocEmpty);
204
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObjectMoved{NoInit,
205
1
        std::move(optionalEmptyObject)};
206
1
    ASSERT_FALSE(optionalEmptyObjectMoved.hasValue());
207
208
1
    TrackingAllocator<DummyObject> alloc;
209
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObject(DummyObject{10}, alloc);
210
1
    ASSERT_EQ(10, optionalObject->getValue());
211
1
    ASSERT_FALSE(optionalObject->isNoInit());
212
213
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObjectMoved{NoInit,
214
1
        std::move(optionalObject)};
215
1
    ASSERT_EQ(10, optionalObjectMoved->getValue());
216
    // memory with object has been moved in optional holder, object move constructor has not been called
217
1
    ASSERT_FALSE(optionalObjectMoved->isNoInit());
218
1
}
219
220
TEST_F(HeapOptionalHolderTest, moveConstructorAllocator)
221
1
{
222
1
    TrackingAllocator<int> alloc;
223
1
    TrackingAllocator<int> alloc2;
224
225
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalDiff(13, alloc);
226
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalDiffMoved(std::move(optionalDiff), alloc2);
227
1
    ASSERT_EQ(*optionalDiffMoved, 13);
228
1
    ASSERT_EQ(optionalDiffMoved.get_allocator(), alloc2);
229
230
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalSame(13, alloc);
231
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalSameMoved(std::move(optionalSame), alloc);
232
1
    ASSERT_EQ(*optionalSameMoved, 13);
233
1
    ASSERT_EQ(optionalSameMoved.get_allocator(), alloc);
234
235
1
    HeapOptionalHolder<int, TrackingAllocator<int>> emptyOptional(alloc);
236
1
    HeapOptionalHolder<int, TrackingAllocator<int>> emptyMoved(std::move(emptyOptional), alloc2);
237
1
    ASSERT_FALSE(emptyOptional.hasValue());
238
1
    ASSERT_FALSE(emptyMoved.hasValue());
239
1
    ASSERT_EQ(emptyOptional.get_allocator(), alloc);
240
1
    ASSERT_EQ(emptyMoved.get_allocator(), alloc2);
241
242
1
    ASSERT_EQ(alloc.numAllocs(), 2U);
243
1
    ASSERT_EQ(alloc2.numAllocs(), 1U);
244
1
}
245
246
TEST_F(HeapOptionalHolderTest, moveValueConstructorAllocatorNoInit)
247
1
{
248
1
    TrackingAllocator<DummyObject> alloc;
249
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObjectMoved{NoInit, DummyObject{10},
250
1
                alloc};
251
1
    ASSERT_EQ(10, optionalObjectMoved->getValue());
252
1
    ASSERT_TRUE(optionalObjectMoved->isNoInit());
253
1
    ASSERT_EQ(optionalObjectMoved.get_allocator(), alloc);
254
1
    ASSERT_GE(alloc.numAllocs(), 1U);
255
1
}
256
257
TEST_F(HeapOptionalHolderTest, copyAssignmentOperator)
258
1
{
259
1
    TrackingAllocator<int> alloc;
260
1
    TrackingAllocator<std::vector<int>> allocVec = alloc;
261
262
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optional(alloc);
263
1
    ASSERT_THROW(*optional, CppRuntimeException);
264
1
    const int intValue = 0xDEAD;
265
1
    optional = intValue;
266
267
1
    HeapOptionalHolder<int, TrackingAllocator<int>>& optionalRef(optional);
268
1
    optionalRef = optional;
269
1
    ASSERT_EQ(intValue, *optionalRef);
270
271
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalCopy;
272
1
    optionalCopy = optional;
273
1
    ASSERT_EQ(intValue, *optionalCopy);
274
1
    ASSERT_EQ(optional.get_allocator(), optionalCopy.get_allocator());
275
1
    ASSERT_EQ(optional.get_allocator(), alloc);
276
277
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVector{
278
1
            std::vector<int>{1, 2, 3}, allocVec};
279
1
    void* origAddress = (*optionalVector).data();
280
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVectorCopy;
281
1
    optionalVectorCopy = optionalVector;
282
1
    ASSERT_NE(origAddress, (*optionalVectorCopy).data());
283
1
    ASSERT_EQ(*optionalVector, *optionalVectorCopy);
284
1
    ASSERT_EQ(optionalVector.get_allocator(), optionalVectorCopy.get_allocator());
285
1
    ASSERT_EQ(optionalVector.get_allocator(), allocVec);
286
287
1
    ASSERT_GE(alloc.numAllocs(), 4U);
288
289
1
    TrackingAllocatorNonProp<int> allocNp;
290
1
    HeapOptionalHolder<int, TrackingAllocatorNonProp<int>> optionalNp(13, allocNp);
291
1
    HeapOptionalHolder<int, TrackingAllocatorNonProp<int>> optionalNpCopy;
292
1
    optionalNpCopy = optionalNp;
293
1
    ASSERT_NE(optionalNp.get_allocator(), optionalNpCopy.get_allocator());
294
295
1
    HeapOptionalHolder<int> optionalInt(123);
296
1
    const HeapOptionalHolder<int>& optionalIntRef = optionalInt;
297
1
    const HeapOptionalHolder<int> &optionalIntRef2 = (optionalInt = optionalIntRef);
298
1
    ASSERT_EQ(123, *optionalInt);
299
1
    ASSERT_EQ(optionalInt, optionalIntRef2);
300
1
}
301
302
TEST_F(HeapOptionalHolderTest, copyAssignmentOperatorNoInit)
303
1
{
304
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObject;
305
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObjectCopy;
306
1
    optionalEmptyObjectCopy.assign(NoInit, optionalEmptyObject);
307
1
    ASSERT_EQ(optionalEmptyObject, optionalEmptyObjectCopy);
308
309
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObject(DummyObject{10});
310
1
    optionalObject.assign(NoInit, optionalObject);
311
312
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObjectCopy;
313
1
    optionalObjectCopy.assign(NoInit, optionalObject);
314
1
    ASSERT_EQ(optionalObject, optionalObjectCopy);
315
1
    ASSERT_FALSE(optionalObject->isNoInit());
316
1
    ASSERT_TRUE(optionalObjectCopy->isNoInit());
317
1
}
318
319
TEST_F(HeapOptionalHolderTest, moveAssignmentOperator)
320
1
{
321
1
    TrackingAllocator<std::vector<int>> allocVec;
322
323
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVector{
324
1
            std::vector<int>{1, 2, 3}, allocVec};
325
1
    std::vector<int> origValues{*optionalVector};
326
1
    void* origAddress = (*optionalVector).data();
327
328
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVectorCopy =
329
1
            optionalVector;
330
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>>& optionalVectorRef =
331
1
            optionalVectorCopy;
332
1
    optionalVectorRef = std::move(optionalVectorCopy);
333
1
    ASSERT_TRUE(optionalVectorRef.hasValue());
334
335
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVectorMoved;
336
1
    optionalVectorMoved = std::move(optionalVector);
337
1
    ASSERT_EQ(origAddress, (*optionalVectorMoved).data());
338
1
    ASSERT_EQ(origValues, *optionalVectorMoved);
339
1
    ASSERT_EQ(optionalVector.get_allocator(), optionalVectorMoved.get_allocator());
340
1
    ASSERT_EQ(optionalVector.get_allocator(), allocVec);
341
342
1
    ASSERT_GE(allocVec.numAllocs(), 1U);
343
344
1
    TrackingAllocatorNonProp<int> allocNp;
345
1
    HeapOptionalHolder<int, TrackingAllocatorNonProp<int>> optionalNp(13, allocNp);
346
1
    HeapOptionalHolder<int, TrackingAllocatorNonProp<int>> optionalNpMoved;
347
1
    optionalNpMoved = std::move(optionalNp);
348
1
    ASSERT_TRUE(optionalNp.hasValue());
349
1
    ASSERT_TRUE(optionalNpMoved.hasValue());
350
1
    ASSERT_NE(optionalNp.get_allocator(), optionalNpMoved.get_allocator());
351
352
1
    HeapOptionalHolder<int> optionalInt(123);
353
1
    HeapOptionalHolder<int>& optionalIntRef = optionalInt;
354
1
    const HeapOptionalHolder<int> &optionalIntRef2 = (optionalInt = std::move(optionalIntRef));
355
1
    ASSERT_EQ(123, *optionalInt);
356
1
    ASSERT_EQ(optionalInt, optionalIntRef2);
357
1
}
358
359
TEST_F(HeapOptionalHolderTest, moveAssignmentOperatorNoInit)
360
1
{
361
1
    TrackingAllocator<DummyObject> allocEmpty;
362
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObject(allocEmpty);
363
364
1
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObjectMoved;
365
1
    optionalEmptyObjectMoved.assign(NoInit, std::move(optionalEmptyObject));
366
1
    ASSERT_FALSE(optionalEmptyObjectMoved.hasValue());
367
368
1
    {
369
1
        TrackingAllocator<DummyObject> alloc;
370
1
        HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObject(DummyObject{10}, alloc);
371
1
        ASSERT_EQ(10, optionalObject->getValue());
372
1
        ASSERT_FALSE(optionalObject->isNoInit());
373
1
        optionalObject.assign(NoInit, std::move(optionalObject));
374
375
1
        HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObjectMoved;
376
1
        optionalObjectMoved.assign(NoInit, std::move(optionalObject));
377
1
        ASSERT_EQ(10, optionalObjectMoved->getValue());
378
        // memory with object has been moved in optional holder, object move constructor has not been called
379
1
        ASSERT_FALSE(optionalObjectMoved->isNoInit());
380
1
    }
381
382
1
    {
383
1
        TrackingAllocatorNonProp<DummyObject> alloc;
384
1
        HeapOptionalHolder<DummyObject, TrackingAllocatorNonProp<DummyObject>> optionalObject(DummyObject{10},
385
1
                alloc);
386
1
        ASSERT_EQ(10, optionalObject->getValue());
387
1
        ASSERT_FALSE(optionalObject->isNoInit());
388
1
        optionalObject.assign(NoInit, std::move(optionalObject));
389
390
1
        HeapOptionalHolder<DummyObject, TrackingAllocatorNonProp<DummyObject>> optionalObjectMoved;
391
1
        optionalObjectMoved.assign(NoInit, std::move(optionalObject));
392
1
        ASSERT_EQ(10, optionalObjectMoved->getValue());
393
1
        ASSERT_TRUE(optionalObjectMoved->isNoInit());
394
1
    }
395
1
}
396
397
TEST_F(HeapOptionalHolderTest, lvalueAssignmentOperator)
398
1
{
399
1
    TrackingAllocator<std::vector<int>> allocVec;
400
401
1
    std::vector<int> values{1, 2, 3};
402
1
    void* origAddress = values.data();
403
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optional(allocVec);
404
1
    optional = values;
405
1
    ASSERT_NE(origAddress, (*optional).data());
406
1
    ASSERT_EQ(values, *optional);
407
1
    ASSERT_EQ(optional.get_allocator(), allocVec);
408
409
1
    ASSERT_GE(allocVec.numAllocs(), 1U);
410
411
1
    TrackingAllocatorNonProp<std::vector<int>> allocVecNp;
412
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocatorNonProp<std::vector<int>>> optionalNp(allocVecNp);
413
1
    optionalNp = values;
414
1
    ASSERT_NE(origAddress, (*optionalNp).data());
415
1
    ASSERT_EQ(values, *optionalNp);
416
1
    ASSERT_EQ(optionalNp.get_allocator(), allocVecNp);
417
418
1
    ASSERT_GE(allocVecNp.numAllocs(), 1U);
419
1
}
420
421
TEST_F(HeapOptionalHolderTest, rvalueAssignmentOperator)
422
1
{
423
1
    TrackingAllocator<std::vector<int>> allocVec;
424
425
1
    std::vector<int> values{1, 2, 3};
426
1
    std::vector<int> origValues{ values };
427
1
    void* origAddress = values.data();
428
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optional(allocVec);
429
1
    optional = std::move(values);
430
1
    ASSERT_EQ(origAddress, (*optional).data());
431
1
    ASSERT_EQ(origValues, *optional);
432
1
    ASSERT_EQ(optional.get_allocator(), allocVec);
433
434
1
    ASSERT_GE(allocVec.numAllocs(), 1U);
435
436
1
    TrackingAllocatorNonProp<std::vector<int>> allocVecNp;
437
1
    values = origValues;
438
1
    origAddress = values.data();
439
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocatorNonProp<std::vector<int>>> optionalNp(allocVecNp);
440
1
    optionalNp = std::move(values);
441
1
    ASSERT_EQ(origAddress, (*optionalNp).data());
442
1
    ASSERT_EQ(origValues, *optionalNp);
443
1
    ASSERT_EQ(optionalNp.get_allocator(), allocVecNp);
444
445
1
    ASSERT_GE(allocVecNp.numAllocs(), 1U);
446
1
}
447
448
TEST_F(HeapOptionalHolderTest, reset)
449
1
{
450
1
    TrackingAllocator<std::vector<int>> allocVec;
451
452
1
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optional{
453
1
            std::vector<int>{1, 2, 3}, allocVec};
454
1
    ASSERT_TRUE(optional.hasValue());
455
1
    ASSERT_EQ(1, (*optional)[0]);
456
1
    ASSERT_EQ(allocVec.numAllocs(), 1U);
457
458
1
    optional.reset();
459
1
    ASSERT_EQ(allocVec.numAllocs(), 0);
460
1
    ASSERT_FALSE(optional.hasValue());
461
462
1
    optional = std::vector<int>{3, 2, 1};
463
1
    ASSERT_EQ(allocVec.numAllocs(), 1U);
464
1
    ASSERT_TRUE(optional.hasValue());
465
1
    ASSERT_EQ(3, (*optional)[0]);
466
467
1
    optional.reset();
468
1
    ASSERT_EQ(allocVec.numAllocs(), 0);
469
1
    ASSERT_FALSE(optional.hasValue());
470
1
}
471
472
TEST_F(HeapOptionalHolderTest, hasValue)
473
1
{
474
1
    HeapOptionalHolder<int> optionalInt;
475
1
    ASSERT_THROW(*optionalInt, CppRuntimeException);
476
1
    ASSERT_EQ(false, optionalInt.hasValue());
477
478
1
    optionalInt = 0xDEAD;
479
1
    ASSERT_EQ(true, optionalInt.hasValue());
480
1
}
481
482
TEST_F(HeapOptionalHolderTest, setGet)
483
1
{
484
1
    HeapOptionalHolder<int> optionalInt;
485
1
    ASSERT_THROW(*optionalInt, CppRuntimeException);
486
1
    const int intValue = 0xDEAD;
487
1
    optionalInt = intValue;
488
1
    ASSERT_EQ(intValue, *optionalInt);
489
490
1
    HeapOptionalHolder<float> optionalFloat;
491
1
    ASSERT_THROW(*optionalFloat, CppRuntimeException);
492
1
    const float floatValue = 3.14F;
493
1
    optionalFloat = floatValue;
494
1
    ASSERT_EQ(floatValue, optionalFloat.value());
495
496
1
    HeapOptionalHolder<DummyObject> optionalObject;
497
1
    ASSERT_THROW(*optionalObject, CppRuntimeException);
498
1
    DummyObject objectValue;
499
1
    objectValue.setValue(intValue);
500
1
    optionalObject = objectValue;
501
1
    const DummyObject& readObjectValue = *optionalObject;
502
1
    ASSERT_EQ(intValue, readObjectValue.getValue());
503
1
    ASSERT_EQ(intValue, optionalObject->getValue());
504
505
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalAlloc;
506
1
    ASSERT_THROW(*optionalAlloc, CppRuntimeException);
507
1
}
508
509
TEST_F(HeapOptionalHolderTest, operatorEquality)
510
1
{
511
1
    HeapOptionalHolder<int> optional1;
512
1
    optional1 = 0xDEAD;
513
1
    HeapOptionalHolder<int> optional2;
514
1
    optional2 = 0xDEAD;
515
1
    HeapOptionalHolder<int> optional3;
516
1
    optional3 = 0xBEEF;
517
1
    HeapOptionalHolder<int> optional4;
518
1
    HeapOptionalHolder<int> optional5;
519
1
    HeapOptionalHolder<int> optional6;
520
521
1
    ASSERT_TRUE(optional1 == optional1);
522
1
    ASSERT_TRUE(optional1 == optional2);
523
1
    ASSERT_FALSE(optional1 == optional3);
524
1
    ASSERT_FALSE(optional1 == optional4);
525
1
    ASSERT_TRUE(optional5 == optional6);
526
1
    ASSERT_FALSE(optional5 == optional1);
527
528
1
    TrackingAllocator<int> alloc1;
529
1
    TrackingAllocator<int> alloc2;
530
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optional7(12345, alloc1);
531
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optional8(12345, alloc2);
532
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optional9(alloc2);
533
1
    HeapOptionalHolder<int, TrackingAllocator<int>> optional10(alloc2);
534
1
    ASSERT_EQ(alloc1.numAllocs(), 1);
535
1
    ASSERT_EQ(alloc2.numAllocs(), 1);
536
1
    ASSERT_TRUE(optional7 == optional8);
537
1
    ASSERT_TRUE(optional9 == optional9);
538
1
    ASSERT_TRUE(optional9== optional10);
539
1
    ASSERT_FALSE(optional7 == optional10);
540
1
}
541
542
TEST_F(HeapOptionalHolderTest, operatorLessThan)
543
1
{
544
1
    HeapOptionalHolder<int> optionalEmpty1;
545
1
    HeapOptionalHolder<int> optionalEmpty2;
546
1
    HeapOptionalHolder<int> optional1(1);
547
1
    HeapOptionalHolder<int> optional2(2);
548
549
1
    ASSERT_FALSE(optionalEmpty1 < optionalEmpty2);
550
1
    ASSERT_TRUE(optionalEmpty1 < optional1);
551
1
    ASSERT_FALSE(optional1 < optionalEmpty1);
552
1
    ASSERT_TRUE(optional1 < optional2);
553
1
    ASSERT_FALSE(optional2 < optional1);
554
1
}
555
556
TEST_F(HeapOptionalHolderTest, constGet)
557
1
{
558
1
    const int intValue = 0xDEAD;
559
1
    HeapOptionalHolder<int> optional;
560
1
    optional = intValue;
561
1
    const HeapOptionalHolder<int> constOptional(optional);
562
1
    ASSERT_EQ(intValue, *constOptional);
563
1
    ASSERT_EQ(intValue, constOptional.value());
564
565
1
    DummyObject objectValue;
566
1
    objectValue.setValue(intValue);
567
1
    HeapOptionalHolder<DummyObject> optionalObject{ objectValue };
568
1
    ASSERT_EQ(intValue, optionalObject->getValue());
569
1
}
570
571
} // namespace zserio