GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: test/zserio/InplaceOptionalHolderTest.cpp Lines: 244 244 100.0 %
Date: 2023-12-13 14:51:09 Branches: 570 1822 31.3 %

Line Branch Exec Source
1
#include <vector>
2
3
#include "zserio/OptionalHolder.h"
4
5
#include "gtest/gtest.h"
6
7
namespace zserio
8
{
9
10
namespace
11
{
12
13
class DummyObject
14
{
15
public:
16
2
    DummyObject() : m_value(0), m_isNoInit(false) {}
17
6
    explicit DummyObject(int value) : m_value(value), m_isNoInit(false) {}
18
5
    explicit DummyObject(NoInitT, const DummyObject& other) : m_value(other.m_value), m_isNoInit(true) {}
19
8
    int getValue() const { return m_value; }
20
2
    void setValue(int value) { m_value = value; }
21
22
9
    bool isNoInit() const { return m_isNoInit; }
23
24
3
    bool operator==(const DummyObject& other) const { return m_value == other.m_value; }
25
26
private:
27
    int m_value;
28
    bool m_isNoInit;
29
};
30
31
} // namespace
32
33
44
class InplaceOptionalHolderTest : public ::testing::Test
34
{
35
protected:
36
};
37
38


802
TEST_F(InplaceOptionalHolderTest, emptyConstructor)
39
{
40
2
    InplaceOptionalHolder<int> optional;
41



1
    ASSERT_FALSE(optional.hasValue());
42
}
43
44


802
TEST_F(InplaceOptionalHolderTest, nullOptConstructor)
45
{
46
    {
47
        NullOptType nullOpt{int()};
48
2
        InplaceOptionalHolder<int> optional{nullOpt};
49



1
        ASSERT_FALSE(optional.hasValue());
50
    }
51
52
    {
53
2
        InplaceOptionalHolder<int> optional{NullOpt};
54



1
        ASSERT_FALSE(optional.hasValue());
55
    }
56
}
57
58


802
TEST_F(InplaceOptionalHolderTest, lvalueConstructor)
59
{
60
2
    std::vector<int> values{1, 2, 3};
61
1
    void* origAddress = values.data();
62

2
    InplaceOptionalHolder<std::vector<int>> optional{values};
63



1
    ASSERT_NE(origAddress, (*optional).data());
64



1
    ASSERT_EQ(values, *optional);
65
66
    // check initializer list
67

2
    InplaceOptionalHolder<std::vector<int>> optionalFromList{{1, 2, 3}};
68

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




1
    ASSERT_EQ(listValues, *optionalFromList);
70
}
71
72


802
TEST_F(InplaceOptionalHolderTest, rvalueConstructor)
73
{
74
2
    std::vector<int> values{1, 2, 3};
75

2
    std::vector<int> origValues{values};
76
1
    void* origAddress = values.data();
77

2
    InplaceOptionalHolder<std::vector<int>> optional{std::move(values)};
78



1
    ASSERT_EQ(origAddress, (*optional).data());
79




1
    ASSERT_EQ(origValues, *optional);
80
}
81
82


802
TEST_F(InplaceOptionalHolderTest, copyConstructor)
83
{
84
2
    InplaceOptionalHolder<int> optional;
85









2
    ASSERT_THROW(*optional, CppRuntimeException);
86
1
    const int intValue = 0xDEAD;
87
1
    optional = intValue;
88
89

2
    InplaceOptionalHolder<int> optionalCopy(optional);
90



1
    ASSERT_EQ(intValue, *optionalCopy);
91
92

2
    InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}};
93
1
    void* origAddress = (*optionalVector).data();
94

2
    InplaceOptionalHolder<std::vector<int>> optionalVectorCopy{optionalVector};
95



1
    ASSERT_NE(origAddress, (*optionalVectorCopy).data());
96




1
    ASSERT_EQ(*optionalVector, *optionalVectorCopy);
97
98

2
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
99

2
    InplaceOptionalHolder<DummyObject> optionalObjectCopy = optionalObject;
100



1
    ASSERT_EQ(optionalObject, optionalObjectCopy);
101
}
102
103


802
TEST_F(InplaceOptionalHolderTest, copyConstructorNoInit)
104
{
105
2
    InplaceOptionalHolder<DummyObject> optionalEmptyObject;
106

2
    InplaceOptionalHolder<DummyObject> optionalEmptyObjectCopy{NoInit, optionalEmptyObject};
107



1
    ASSERT_EQ(optionalEmptyObject, optionalEmptyObjectCopy);
108
109

2
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
110

2
    InplaceOptionalHolder<DummyObject> optionalObjectCopy{NoInit, optionalObject};
111



1
    ASSERT_EQ(optionalObject, optionalObjectCopy);
112



1
    ASSERT_FALSE(optionalObject->isNoInit());
113




1
    ASSERT_TRUE(optionalObjectCopy->isNoInit());
114
}
115
116


802
TEST_F(InplaceOptionalHolderTest, copyAssignmentOperator)
117
{
118
2
    InplaceOptionalHolder<int> optional;
119









2
    ASSERT_THROW(*optional, CppRuntimeException);
120
1
    const int intValue = 0xDEAD;
121
1
    optional = intValue;
122
123
1
    InplaceOptionalHolder<int>& optionalRef(optional);
124
1
    optionalRef = optional;
125



1
    ASSERT_EQ(intValue, *optionalRef);
126
127
2
    InplaceOptionalHolder<int> optionalCopy;
128
1
    optionalCopy = optional;
129



1
    ASSERT_EQ(intValue, *optionalCopy);
130
131

2
    InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}};
132
1
    void* origAddress = (*optionalVector).data();
133
2
    InplaceOptionalHolder<std::vector<int>> optionalVectorCopy;
134
1
    optionalVectorCopy = optionalVector;
135



1
    ASSERT_NE(origAddress, ((*optionalVectorCopy).data()));
136




1
    ASSERT_EQ(*optionalVector, *optionalVectorCopy);
137
138
2
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVector;
139
2
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVectorCopy;
140
1
    emptyOptionalVectorCopy = emptyOptionalVector;
141



1
    ASSERT_EQ(false, emptyOptionalVectorCopy.hasValue());
142
}
143
144


802
TEST_F(InplaceOptionalHolderTest, copyAssignmentOperatorNoInit)
145
{
146
2
    InplaceOptionalHolder<DummyObject> optionalEmptyObject;
147
2
    InplaceOptionalHolder<DummyObject> optionalEmptyObjectCopy;
148
1
    optionalEmptyObjectCopy.assign(NoInit, optionalEmptyObject);
149



1
    ASSERT_EQ(optionalEmptyObject, optionalEmptyObjectCopy);
150
151

2
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
152
1
    optionalObject.assign(NoInit, optionalObject);
153
154
2
    InplaceOptionalHolder<DummyObject> optionalObjectCopy;
155
1
    optionalObjectCopy.assign(NoInit, optionalObject);
156



1
    ASSERT_EQ(optionalObject, optionalObjectCopy);
157



1
    ASSERT_FALSE(optionalObject->isNoInit());
158




1
    ASSERT_TRUE(optionalObjectCopy->isNoInit());
159
}
160
161


802
TEST_F(InplaceOptionalHolderTest, moveConstructor)
162
{
163

2
    InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}};
164

2
    std::vector<int> origValues{*optionalVector};
165
1
    void* origAddress = (*optionalVector).data();
166

2
    InplaceOptionalHolder<std::vector<int>> optionalVectorMoved{std::move(optionalVector)};
167



1
    ASSERT_EQ(origAddress, ((*optionalVectorMoved).data()));
168



1
    ASSERT_EQ(origValues, *optionalVectorMoved);
169
170
2
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVector;
171

2
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVectorMoved{std::move(emptyOptionalVector)};
172



1
    ASSERT_EQ(false, emptyOptionalVectorMoved.hasValue());
173
174

2
    InplaceOptionalHolder<int> optionalInt{1};
175

2
    InplaceOptionalHolder<int> optionalIntMoved{std::move(optionalInt)};
176



1
    ASSERT_EQ(1, *optionalIntMoved);
177
178
2
    InplaceOptionalHolder<int> emptyOptionalInt;
179

2
    InplaceOptionalHolder<int> emptyOptionalIntMoved{std::move(emptyOptionalInt)};
180



1
    ASSERT_EQ(false, emptyOptionalIntMoved.hasValue());
181
}
182
183


802
TEST_F(InplaceOptionalHolderTest, moveConstructorNoInit)
184
{
185
2
    InplaceOptionalHolder<DummyObject> optionalEmptyObject;
186

2
    InplaceOptionalHolder<DummyObject> optionalEmptyObjectMoved{NoInit, std::move(optionalEmptyObject)};
187



1
    ASSERT_FALSE(optionalEmptyObjectMoved.hasValue());
188
189

2
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
190



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



1
    ASSERT_FALSE(optionalObject->isNoInit());
192
193

2
    InplaceOptionalHolder<DummyObject> optionalObjectMoved{NoInit, std::move(optionalObject)};
194



1
    ASSERT_EQ(10, optionalObjectMoved->getValue());
195




1
    ASSERT_TRUE(optionalObjectMoved->isNoInit());
196
}
197
198


802
TEST_F(InplaceOptionalHolderTest, moveValueConstructorNoInit)
199
{
200
2
    InplaceOptionalHolder<DummyObject> optionalObjectMoved{NoInit, DummyObject{10}};
201



1
    ASSERT_EQ(10, optionalObjectMoved->getValue());
202




1
    ASSERT_TRUE(optionalObjectMoved->isNoInit());
203
}
204
205


802
TEST_F(InplaceOptionalHolderTest, forwardingConstructor)
206
{
207
    {
208
        InPlaceT inPlace{};
209
2
        std::vector<int> src = {0, 13, 42};
210

2
        InplaceOptionalHolder<std::vector<int>> optional{inPlace, src.begin(), src.end()};
211




1
        ASSERT_EQ(src, *optional);
212
    }
213
214
    {
215
2
        std::vector<int> src = {0, 13, 42};
216

2
        InplaceOptionalHolder<std::vector<int>> optional{InPlace, src.begin(), src.end()};
217




1
        ASSERT_EQ(src, *optional);
218
    }
219
}
220
221


802
TEST_F(InplaceOptionalHolderTest, moveAssignmentOperator)
222
{
223

2
    InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}};
224

2
    std::vector<int> origValues{*optionalVector};
225
1
    void* origAddress = (*optionalVector).data();
226
227
1
    InplaceOptionalHolder<std::vector<int>>& optionalVectorRef(optionalVector);
228
1
    optionalVectorRef = std::move(optionalVector);
229



1
    ASSERT_EQ(origAddress, (*optionalVectorRef).data());
230



1
    ASSERT_EQ(origValues, *optionalVectorRef);
231
232
2
    InplaceOptionalHolder<std::vector<int>> optionalVectorMoved;
233
1
    optionalVectorMoved = std::move(optionalVectorRef);
234



1
    ASSERT_EQ(origAddress, (*optionalVectorMoved).data());
235



1
    ASSERT_EQ(origValues, *optionalVectorMoved);
236
237
2
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVector;
238
2
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVectorMoved;
239
1
    emptyOptionalVectorMoved = std::move(emptyOptionalVector);
240



1
    ASSERT_EQ(false, emptyOptionalVectorMoved.hasValue());
241
}
242
243


802
TEST_F(InplaceOptionalHolderTest, moveAssignmentOperatorNoInit)
244
{
245
2
    InplaceOptionalHolder<DummyObject> optionalEmptyObject;
246
2
    InplaceOptionalHolder<DummyObject> optionalEmptyObjectMoved;
247
1
    optionalEmptyObjectMoved.assign(NoInit, std::move(optionalEmptyObject));
248



1
    ASSERT_FALSE(optionalEmptyObjectMoved.hasValue());
249
250

2
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
251



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



1
    ASSERT_FALSE(optionalObject->isNoInit());
253
1
    optionalObject.assign(NoInit, std::move(optionalObject));
254
255
2
    InplaceOptionalHolder<DummyObject> optionalObjectMoved;
256
1
    optionalObjectMoved.assign(NoInit, std::move(optionalObject));
257



1
    ASSERT_EQ(10, optionalObjectMoved->getValue());
258
    // memory with object has been moved in optional holder, object move constructor has not been called
259




1
    ASSERT_TRUE(optionalObjectMoved->isNoInit());
260
}
261
262


802
TEST_F(InplaceOptionalHolderTest, lvalueAssignmentOperator)
263
{
264
2
    std::vector<int> values{1, 2, 3};
265
1
    void* origAddress = values.data();
266
2
    InplaceOptionalHolder<std::vector<int>> optional;
267
1
    optional = values;
268



1
    ASSERT_NE(origAddress, (*optional).data());
269




1
    ASSERT_EQ(values, *optional);
270
}
271
272


802
TEST_F(InplaceOptionalHolderTest, rvalueAssignmentOperator)
273
{
274
2
    std::vector<int> values{1, 2, 3};
275

2
    std::vector<int> origValues{values};
276
1
    void* origAddress = values.data();
277
2
    InplaceOptionalHolder<std::vector<int>> optional;
278
1
    optional = std::move(values);
279



1
    ASSERT_EQ(origAddress, (*optional).data());
280




1
    ASSERT_EQ(origValues, *optional);
281
}
282
283


802
TEST_F(InplaceOptionalHolderTest, reset)
284
{
285

2
    InplaceOptionalHolder<std::vector<int>> optional{std::vector<int>{1, 2, 3}};
286



1
    ASSERT_TRUE(optional.hasValue());
287



1
    ASSERT_EQ(1, (*optional)[0]);
288
289
1
    optional.reset();
290



1
    ASSERT_FALSE(optional.hasValue());
291
292

1
    optional = std::vector<int>{3, 2, 1};
293



1
    ASSERT_TRUE(optional.hasValue());
294



1
    ASSERT_EQ(3, (*optional)[0]);
295
296
1
    optional.reset();
297



1
    ASSERT_FALSE(optional.hasValue());
298
}
299
300


802
TEST_F(InplaceOptionalHolderTest, operatorEquality)
301
{
302
2
    InplaceOptionalHolder<int> optional1;
303
1
    optional1 = 0xDEAD;
304
2
    InplaceOptionalHolder<int> optional2;
305
1
    optional2 = 0xDEAD;
306
2
    InplaceOptionalHolder<int> optional3;
307
1
    optional3 = 0xBEEF;
308
2
    InplaceOptionalHolder<int> optional4;
309
2
    InplaceOptionalHolder<int> optional5;
310
2
    InplaceOptionalHolder<int> optional6;
311
312



1
    ASSERT_TRUE(optional1 == optional1);
313



1
    ASSERT_TRUE(optional1 == optional2);
314



1
    ASSERT_FALSE(optional1 == optional3);
315



1
    ASSERT_FALSE(optional1 == optional4);
316



1
    ASSERT_TRUE(optional5 == optional6);
317




1
    ASSERT_FALSE(optional5 == optional1);
318
}
319
320


802
TEST_F(InplaceOptionalHolderTest, operatorLessThan)
321
{
322
2
    InplaceOptionalHolder<int> optionalEmpty1;
323
2
    InplaceOptionalHolder<int> optionalEmpty2;
324

2
    InplaceOptionalHolder<int> optional1(1);
325

2
    InplaceOptionalHolder<int> optional2(2);
326
327



1
    ASSERT_FALSE(optionalEmpty1 < optionalEmpty2);
328



1
    ASSERT_TRUE(optionalEmpty1 < optional1);
329



1
    ASSERT_FALSE(optional1 < optionalEmpty1);
330



1
    ASSERT_TRUE(optional1 < optional2);
331




1
    ASSERT_FALSE(optional2 < optional1);
332
}
333
334


802
TEST_F(InplaceOptionalHolderTest, setGet)
335
{
336
2
    InplaceOptionalHolder<int> optionalInt;
337









2
    ASSERT_THROW(*optionalInt, CppRuntimeException);
338
1
    const int intValue = 0xDEAD;
339
1
    optionalInt = intValue;
340




1
    ASSERT_EQ(intValue, *optionalInt);
341
342
2
    InplaceOptionalHolder<float> optionalFloat;
343









2
    ASSERT_THROW(*optionalFloat, CppRuntimeException);
344
1
    const float floatValue = 3.14F;
345
1
    optionalFloat = floatValue;
346




1
    ASSERT_EQ(floatValue, optionalFloat.value());
347
348
2
    InplaceOptionalHolder<DummyObject> optionalObject;
349









2
    ASSERT_THROW(*optionalObject, CppRuntimeException);
350
1
    DummyObject objectValue;
351
1
    objectValue.setValue(intValue);
352
1
    optionalObject = objectValue;
353
1
    const DummyObject& readObjectValue = *optionalObject;
354



1
    ASSERT_EQ(intValue, readObjectValue.getValue());
355




1
    ASSERT_EQ(intValue, optionalObject->getValue());
356
}
357
358


802
TEST_F(InplaceOptionalHolderTest, hasValue)
359
{
360
2
    InplaceOptionalHolder<int> optionalInt;
361









2
    ASSERT_THROW(*optionalInt, CppRuntimeException);
362



1
    ASSERT_EQ(false, optionalInt.hasValue());
363
364
1
    optionalInt = 0xDEAD;
365



1
    ASSERT_EQ(true, optionalInt.hasValue());
366
}
367
368


802
TEST_F(InplaceOptionalHolderTest, constGet)
369
{
370
1
    const int intValue = 0xDEAD;
371
2
    InplaceOptionalHolder<int> optional;
372
1
    optional = intValue;
373

2
    const InplaceOptionalHolder<int> constOptional(optional);
374



1
    ASSERT_EQ(intValue, *constOptional);
375



1
    ASSERT_EQ(intValue, constOptional.value());
376
377
1
    DummyObject objectValue;
378
1
    objectValue.setValue(intValue);
379

2
    InplaceOptionalHolder<DummyObject> optionalObject{objectValue};
380




1
    ASSERT_EQ(intValue, optionalObject->getValue());
381
}
382
383

2394
} // namespace zserio