GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: test/zserio/HeapOptionalHolderTest.cpp Lines: 374 374 100.0 %
Date: 2023-12-13 14:51:09 Branches: 956 3064 31.2 %

Line Branch Exec 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
48
class HeapOptionalHolderTest : public ::testing::Test
35
{
36
protected:
37
};
38
39


802
TEST_F(HeapOptionalHolderTest, emptyConstructor)
40
{
41
2
    TrackingAllocator<int> alloc;
42
2
    HeapOptionalHolder<int, TrackingAllocator<int>> optional{alloc};
43




1
    ASSERT_EQ(alloc, optional.get_allocator());
44
}
45
46


802
TEST_F(HeapOptionalHolderTest, nullOptConstructor)
47
{
48
    {
49
        NullOptType nullOpt{int()};
50
2
        TrackingAllocator<int> alloc;
51
2
        HeapOptionalHolder<int, TrackingAllocator<int>> optional{nullOpt, alloc};
52




1
        ASSERT_EQ(alloc, optional.get_allocator());
53
    }
54
55
    {
56
2
        TrackingAllocator<int> alloc;
57
2
        HeapOptionalHolder<int, TrackingAllocator<int>> optional{NullOpt, alloc};
58




1
        ASSERT_EQ(alloc, optional.get_allocator());
59
    }
60
}
61
62


802
TEST_F(HeapOptionalHolderTest, lvalueConstructor)
63
{
64
2
    TrackingAllocator<std::vector<int>> alloc;
65
66

2
    std::vector<int> values{1, 2, 3};
67
1
    void* origAddress = values.data();
68

2
    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
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalFromList{
73

2
            {1, 2, 3}, alloc};
74

2
    std::vector<int> listValues{1, 2, 3};
75



1
    ASSERT_EQ(listValues, *optionalFromList);
76
77



1
    ASSERT_GE(alloc.numAllocs(), 2U);
78
}
79
80


802
TEST_F(HeapOptionalHolderTest, rvalueConstructor)
81
{
82
2
    TrackingAllocator<std::vector<int>> alloc;
83
84

2
    std::vector<int> values{1, 2, 3};
85

2
    std::vector<int> origValues{ values };
86
1
    void* origAddress = values.data();
87
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optional{
88

2
            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
}
94
95


802
TEST_F(HeapOptionalHolderTest, forwardingConstructor)
96
{
97
2
    TrackingAllocator<std::vector<int>> alloc;
98
99

2
    std::vector<int> src = {0, 13, 42};
100
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optional{
101

2
            alloc, src.begin(), src.end()};
102



1
    ASSERT_EQ(src, *optional);
103
104



1
    ASSERT_GE(alloc.numAllocs(), 1U);
105
}
106
107


802
TEST_F(HeapOptionalHolderTest, copyConstructor)
108
{
109

2
    TrackingAllocator<int> alloc;
110

2
    TrackingAllocator<std::vector<int>> allocVec = alloc;
111
112
2
    HeapOptionalHolder<int, TrackingAllocator<int>> optional(alloc);
113









2
    ASSERT_THROW(*optional, CppRuntimeException);
114
1
    const int intValue = 0xDEAD;
115
1
    optional = intValue;
116
117

2
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalCopy(optional);
118



1
    ASSERT_EQ(intValue, *optionalCopy);
119




1
    ASSERT_EQ(optional.get_allocator(), optionalCopy.get_allocator());
120
121

2
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObject(DummyObject{10});
122

2
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObjectCopy = optionalObject;
123



1
    ASSERT_EQ(optionalObject, optionalObjectCopy);
124




1
    ASSERT_EQ(optionalObject.get_allocator(), optionalObjectCopy.get_allocator());
125
126
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVector{
127

2
            std::vector<int>{1, 2, 3}, allocVec};
128
1
    void* origAddress = (*optionalVector).data();
129
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVectorCopy{
130

2
            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

2
    TrackingAllocatorNonProp<int> allocNp;
138
2
    HeapOptionalHolder<int, TrackingAllocatorNonProp<int>> optionalNp(allocNp);
139

2
    HeapOptionalHolder<int, TrackingAllocatorNonProp<int>> optionalNpCopy = optionalNp;
140




1
    ASSERT_NE(optionalNp.get_allocator(), optionalNpCopy.get_allocator());
141
}
142
143


802
TEST_F(HeapOptionalHolderTest, copyConstructorNoInit)
144
{
145
2
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObject;
146
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObjectCopy{NoInit,
147

2
        optionalEmptyObject};
148



1
    ASSERT_EQ(optionalEmptyObject, optionalEmptyObjectCopy);
149
150

2
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObject(DummyObject{10});
151

2
    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
}
156
157


802
TEST_F(HeapOptionalHolderTest, copyConstructorAllocator)
158
{
159

2
    TrackingAllocator<int> alloc1;
160

2
    TrackingAllocator<std::vector<int>> allocVec1 = alloc1;
161

2
    TrackingAllocator<int> alloc2;
162

2
    TrackingAllocator<std::vector<int>> allocVec2 = alloc2;
163
164
2
    HeapOptionalHolder<int, TrackingAllocator<int>> optional(alloc1);
165









2
    ASSERT_THROW(*optional, CppRuntimeException);
166
167

2
    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
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVector{
173

2
            std::vector<int>{1, 2, 3}, allocVec1};
174
1
    void* origAddress = (*optionalVector).data();
175
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVectorCopy{
176

2
            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
}
186
187


802
TEST_F(HeapOptionalHolderTest, moveConstructor)
188
{
189
2
    TrackingAllocator<int> alloc;
190
191

2
    HeapOptionalHolder<int, TrackingAllocator<int>> optional(13, alloc);
192
2
    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
}
199
200


802
TEST_F(HeapOptionalHolderTest, moveConstructorNoInit)
201
{
202
2
    TrackingAllocator<DummyObject> allocEmpty;
203
2
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObject(allocEmpty);
204
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObjectMoved{NoInit,
205

2
        std::move(optionalEmptyObject)};
206



1
    ASSERT_FALSE(optionalEmptyObjectMoved.hasValue());
207
208

2
    TrackingAllocator<DummyObject> alloc;
209

2
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObject(DummyObject{10}, alloc);
210



1
    ASSERT_EQ(10, optionalObject->getValue());
211



1
    ASSERT_FALSE(optionalObject->isNoInit());
212
213
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObjectMoved{NoInit,
214

2
        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
}
219
220


802
TEST_F(HeapOptionalHolderTest, moveConstructorAllocator)
221
{
222
2
    TrackingAllocator<int> alloc;
223

2
    TrackingAllocator<int> alloc2;
224
225

2
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalDiff(13, alloc);
226

2
    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

2
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalSame(13, alloc);
231

2
    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
2
    HeapOptionalHolder<int, TrackingAllocator<int>> emptyOptional(alloc);
236

2
    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
}
245
246


802
TEST_F(HeapOptionalHolderTest, moveValueConstructorAllocatorNoInit)
247
{
248
2
    TrackingAllocator<DummyObject> alloc;
249
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObjectMoved{NoInit, DummyObject{10},
250

2
                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
}
256
257


802
TEST_F(HeapOptionalHolderTest, copyAssignmentOperator)
258
{
259

2
    TrackingAllocator<int> alloc;
260

2
    TrackingAllocator<std::vector<int>> allocVec = alloc;
261
262
2
    HeapOptionalHolder<int, TrackingAllocator<int>> optional(alloc);
263









2
    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

2
    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
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVector{
278

2
            std::vector<int>{1, 2, 3}, allocVec};
279
1
    void* origAddress = (*optionalVector).data();
280

2
    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

2
    TrackingAllocatorNonProp<int> allocNp;
290

2
    HeapOptionalHolder<int, TrackingAllocatorNonProp<int>> optionalNp(13, allocNp);
291

2
    HeapOptionalHolder<int, TrackingAllocatorNonProp<int>> optionalNpCopy;
292
1
    optionalNpCopy = optionalNp;
293




1
    ASSERT_NE(optionalNp.get_allocator(), optionalNpCopy.get_allocator());
294
295

2
    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
}
301
302


802
TEST_F(HeapOptionalHolderTest, copyAssignmentOperatorNoInit)
303
{
304
2
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObject;
305

2
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObjectCopy;
306
1
    optionalEmptyObjectCopy.assign(NoInit, optionalEmptyObject);
307



1
    ASSERT_EQ(optionalEmptyObject, optionalEmptyObjectCopy);
308
309

2
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalObject(DummyObject{10});
310
1
    optionalObject.assign(NoInit, optionalObject);
311
312

2
    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
}
318
319


802
TEST_F(HeapOptionalHolderTest, moveAssignmentOperator)
320
{
321
2
    TrackingAllocator<std::vector<int>> allocVec;
322
323
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVector{
324

2
            std::vector<int>{1, 2, 3}, allocVec};
325

2
    std::vector<int> origValues{*optionalVector};
326
1
    void* origAddress = (*optionalVector).data();
327
328
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optionalVectorCopy =
329

2
            optionalVector;
330
    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

2
    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

2
    TrackingAllocatorNonProp<int> allocNp;
345

2
    HeapOptionalHolder<int, TrackingAllocatorNonProp<int>> optionalNp(13, allocNp);
346

2
    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

2
    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
}
358
359


802
TEST_F(HeapOptionalHolderTest, moveAssignmentOperatorNoInit)
360
{
361
2
    TrackingAllocator<DummyObject> allocEmpty;
362
2
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObject(allocEmpty);
363
364

2
    HeapOptionalHolder<DummyObject, TrackingAllocator<DummyObject>> optionalEmptyObjectMoved;
365
1
    optionalEmptyObjectMoved.assign(NoInit, std::move(optionalEmptyObject));
366



1
    ASSERT_FALSE(optionalEmptyObjectMoved.hasValue());
367
368
    {
369
2
        TrackingAllocator<DummyObject> alloc;
370

2
        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

2
        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
    }
381
382
    {
383

2
        TrackingAllocatorNonProp<DummyObject> alloc;
384
        HeapOptionalHolder<DummyObject, TrackingAllocatorNonProp<DummyObject>> optionalObject(DummyObject{10},
385

2
                alloc);
386



1
        ASSERT_EQ(10, optionalObject->getValue());
387



1
        ASSERT_FALSE(optionalObject->isNoInit());
388
1
        optionalObject.assign(NoInit, std::move(optionalObject));
389
390

2
        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
    }
395
}
396
397


802
TEST_F(HeapOptionalHolderTest, lvalueAssignmentOperator)
398
{
399
2
    TrackingAllocator<std::vector<int>> allocVec;
400
401

2
    std::vector<int> values{1, 2, 3};
402
1
    void* origAddress = values.data();
403
2
    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

2
    TrackingAllocatorNonProp<std::vector<int>> allocVecNp;
412
2
    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
}
420
421


802
TEST_F(HeapOptionalHolderTest, rvalueAssignmentOperator)
422
{
423
2
    TrackingAllocator<std::vector<int>> allocVec;
424
425

2
    std::vector<int> values{1, 2, 3};
426

2
    std::vector<int> origValues{ values };
427
1
    void* origAddress = values.data();
428
2
    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

2
    TrackingAllocatorNonProp<std::vector<int>> allocVecNp;
437
1
    values = origValues;
438
1
    origAddress = values.data();
439
2
    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
}
447
448


802
TEST_F(HeapOptionalHolderTest, reset)
449
{
450
2
    TrackingAllocator<std::vector<int>> allocVec;
451
452
    HeapOptionalHolder<std::vector<int>, TrackingAllocator<std::vector<int>>> optional{
453

2
            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
}
471
472


802
TEST_F(HeapOptionalHolderTest, hasValue)
473
{
474
2
    HeapOptionalHolder<int> optionalInt;
475









2
    ASSERT_THROW(*optionalInt, CppRuntimeException);
476



1
    ASSERT_EQ(false, optionalInt.hasValue());
477
478
1
    optionalInt = 0xDEAD;
479



1
    ASSERT_EQ(true, optionalInt.hasValue());
480
}
481
482


802
TEST_F(HeapOptionalHolderTest, setGet)
483
{
484
2
    HeapOptionalHolder<int> optionalInt;
485









2
    ASSERT_THROW(*optionalInt, CppRuntimeException);
486
1
    const int intValue = 0xDEAD;
487
1
    optionalInt = intValue;
488




1
    ASSERT_EQ(intValue, *optionalInt);
489
490
2
    HeapOptionalHolder<float> optionalFloat;
491









2
    ASSERT_THROW(*optionalFloat, CppRuntimeException);
492
1
    const float floatValue = 3.14F;
493
1
    optionalFloat = floatValue;
494




1
    ASSERT_EQ(floatValue, optionalFloat.value());
495
496
2
    HeapOptionalHolder<DummyObject> optionalObject;
497









2
    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

2
    HeapOptionalHolder<int, TrackingAllocator<int>> optionalAlloc;
506










2
    ASSERT_THROW(*optionalAlloc, CppRuntimeException);
507
}
508
509


802
TEST_F(HeapOptionalHolderTest, operatorEquality)
510
{
511
2
    HeapOptionalHolder<int> optional1;
512
1
    optional1 = 0xDEAD;
513
2
    HeapOptionalHolder<int> optional2;
514
1
    optional2 = 0xDEAD;
515
2
    HeapOptionalHolder<int> optional3;
516
1
    optional3 = 0xBEEF;
517
2
    HeapOptionalHolder<int> optional4;
518
2
    HeapOptionalHolder<int> optional5;
519
2
    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

2
    TrackingAllocator<int> alloc1;
529

2
    TrackingAllocator<int> alloc2;
530

2
    HeapOptionalHolder<int, TrackingAllocator<int>> optional7(12345, alloc1);
531

2
    HeapOptionalHolder<int, TrackingAllocator<int>> optional8(12345, alloc2);
532
2
    HeapOptionalHolder<int, TrackingAllocator<int>> optional9(alloc2);
533
2
    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
}
541
542


802
TEST_F(HeapOptionalHolderTest, operatorLessThan)
543
{
544
2
    HeapOptionalHolder<int> optionalEmpty1;
545
2
    HeapOptionalHolder<int> optionalEmpty2;
546

2
    HeapOptionalHolder<int> optional1(1);
547

2
    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
}
555
556


802
TEST_F(HeapOptionalHolderTest, constGet)
557
{
558
1
    const int intValue = 0xDEAD;
559
2
    HeapOptionalHolder<int> optional;
560
1
    optional = intValue;
561

2
    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

2
    HeapOptionalHolder<DummyObject> optionalObject{ objectValue };
568




1
    ASSERT_EQ(intValue, optionalObject->getValue());
569
}
570
571

2394
} // namespace zserio