Coverage Report

Created: 2024-07-18 11:41

test/zserio/InplaceOptionalHolderTest.cpp
Line
Count
Source
1
#include <vector>
2
3
#include "gtest/gtest.h"
4
#include "zserio/OptionalHolder.h"
5
6
namespace zserio
7
{
8
9
namespace
10
{
11
12
class DummyObject
13
{
14
public:
15
    DummyObject() :
16
            m_value(0),
17
            m_isNoInit(false)
18
2
    {}
19
    explicit DummyObject(int value) :
20
            m_value(value),
21
            m_isNoInit(false)
22
6
    {}
23
    explicit DummyObject(NoInitT, const DummyObject& other) :
24
            m_value(other.m_value),
25
            m_isNoInit(true)
26
5
    {}
27
    int getValue() const
28
8
    {
29
8
        return m_value;
30
8
    }
31
    void setValue(int value)
32
2
    {
33
2
        m_value = value;
34
2
    }
35
36
    bool isNoInit() const
37
9
    {
38
9
        return m_isNoInit;
39
9
    }
40
41
    bool operator==(const DummyObject& other) const
42
3
    {
43
3
        return m_value == other.m_value;
44
3
    }
45
46
private:
47
    int m_value;
48
    bool m_isNoInit;
49
};
50
51
} // namespace
52
53
class InplaceOptionalHolderTest : public ::testing::Test
54
{
55
protected:
56
};
57
58
TEST_F(InplaceOptionalHolderTest, emptyConstructor)
59
1
{
60
1
    InplaceOptionalHolder<int> optional;
61
1
    ASSERT_FALSE(optional.hasValue());
62
1
}
63
64
TEST_F(InplaceOptionalHolderTest, nullOptConstructor)
65
1
{
66
1
    {
67
1
        NullOptType nullOpt{int()};
68
1
        InplaceOptionalHolder<int> optional{nullOpt};
69
1
        ASSERT_FALSE(optional.hasValue());
70
1
    }
71
72
1
    {
73
1
        InplaceOptionalHolder<int> optional{NullOpt};
74
1
        ASSERT_FALSE(optional.hasValue());
75
1
    }
76
1
}
77
78
TEST_F(InplaceOptionalHolderTest, lvalueConstructor)
79
1
{
80
1
    std::vector<int> values{1, 2, 3};
81
1
    void* origAddress = values.data();
82
1
    InplaceOptionalHolder<std::vector<int>> optional{values};
83
1
    ASSERT_NE(origAddress, (*optional).data());
84
1
    ASSERT_EQ(values, *optional);
85
86
    // check initializer list
87
1
    InplaceOptionalHolder<std::vector<int>> optionalFromList{{1, 2, 3}};
88
1
    std::vector<int> listValues{1, 2, 3};
89
1
    ASSERT_EQ(listValues, *optionalFromList);
90
1
}
91
92
TEST_F(InplaceOptionalHolderTest, rvalueConstructor)
93
1
{
94
1
    std::vector<int> values{1, 2, 3};
95
1
    std::vector<int> origValues{values};
96
1
    void* origAddress = values.data();
97
1
    InplaceOptionalHolder<std::vector<int>> optional{std::move(values)};
98
1
    ASSERT_EQ(origAddress, (*optional).data());
99
1
    ASSERT_EQ(origValues, *optional);
100
1
}
101
102
TEST_F(InplaceOptionalHolderTest, copyConstructor)
103
1
{
104
1
    InplaceOptionalHolder<int> optional;
105
1
    ASSERT_THROW(*optional, CppRuntimeException);
106
1
    const int intValue = 0xDEAD;
107
1
    optional = intValue;
108
109
1
    InplaceOptionalHolder<int> optionalCopy(optional);
110
1
    ASSERT_EQ(intValue, *optionalCopy);
111
112
1
    InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}};
113
1
    void* origAddress = (*optionalVector).data();
114
1
    InplaceOptionalHolder<std::vector<int>> optionalVectorCopy{optionalVector};
115
1
    ASSERT_NE(origAddress, (*optionalVectorCopy).data());
116
1
    ASSERT_EQ(*optionalVector, *optionalVectorCopy);
117
118
1
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
119
1
    InplaceOptionalHolder<DummyObject> optionalObjectCopy = optionalObject;
120
1
    ASSERT_EQ(optionalObject, optionalObjectCopy);
121
1
}
122
123
TEST_F(InplaceOptionalHolderTest, copyConstructorNoInit)
124
1
{
125
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObject;
126
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObjectCopy{NoInit, optionalEmptyObject};
127
1
    ASSERT_EQ(optionalEmptyObject, optionalEmptyObjectCopy);
128
129
1
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
130
1
    InplaceOptionalHolder<DummyObject> optionalObjectCopy{NoInit, optionalObject};
131
1
    ASSERT_EQ(optionalObject, optionalObjectCopy);
132
1
    ASSERT_FALSE(optionalObject->isNoInit());
133
1
    ASSERT_TRUE(optionalObjectCopy->isNoInit());
134
1
}
135
136
TEST_F(InplaceOptionalHolderTest, copyAssignmentOperator)
137
1
{
138
1
    InplaceOptionalHolder<int> optional;
139
1
    ASSERT_THROW(*optional, CppRuntimeException);
140
1
    const int intValue = 0xDEAD;
141
1
    optional = intValue;
142
143
1
    InplaceOptionalHolder<int>& optionalRef(optional);
144
1
    optionalRef = optional;
145
1
    ASSERT_EQ(intValue, *optionalRef);
146
147
1
    InplaceOptionalHolder<int> optionalCopy;
148
1
    optionalCopy = optional;
149
1
    ASSERT_EQ(intValue, *optionalCopy);
150
151
1
    InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}};
152
1
    void* origAddress = (*optionalVector).data();
153
1
    InplaceOptionalHolder<std::vector<int>> optionalVectorCopy;
154
1
    optionalVectorCopy = optionalVector;
155
1
    ASSERT_NE(origAddress, ((*optionalVectorCopy).data()));
156
1
    ASSERT_EQ(*optionalVector, *optionalVectorCopy);
157
158
1
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVector;
159
1
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVectorCopy;
160
1
    emptyOptionalVectorCopy = emptyOptionalVector;
161
1
    ASSERT_EQ(false, emptyOptionalVectorCopy.hasValue());
162
1
}
163
164
TEST_F(InplaceOptionalHolderTest, copyAssignmentOperatorNoInit)
165
1
{
166
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObject;
167
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObjectCopy;
168
1
    optionalEmptyObjectCopy.assign(NoInit, optionalEmptyObject);
169
1
    ASSERT_EQ(optionalEmptyObject, optionalEmptyObjectCopy);
170
171
1
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
172
1
    optionalObject.assign(NoInit, optionalObject);
173
174
1
    InplaceOptionalHolder<DummyObject> optionalObjectCopy;
175
1
    optionalObjectCopy.assign(NoInit, optionalObject);
176
1
    ASSERT_EQ(optionalObject, optionalObjectCopy);
177
1
    ASSERT_FALSE(optionalObject->isNoInit());
178
1
    ASSERT_TRUE(optionalObjectCopy->isNoInit());
179
1
}
180
181
TEST_F(InplaceOptionalHolderTest, moveConstructor)
182
1
{
183
1
    InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}};
184
1
    std::vector<int> origValues{*optionalVector};
185
1
    void* origAddress = (*optionalVector).data();
186
1
    InplaceOptionalHolder<std::vector<int>> optionalVectorMoved{std::move(optionalVector)};
187
1
    ASSERT_EQ(origAddress, ((*optionalVectorMoved).data()));
188
1
    ASSERT_EQ(origValues, *optionalVectorMoved);
189
190
1
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVector;
191
1
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVectorMoved{std::move(emptyOptionalVector)};
192
1
    ASSERT_EQ(false, emptyOptionalVectorMoved.hasValue());
193
194
1
    InplaceOptionalHolder<int> optionalInt{1};
195
1
    InplaceOptionalHolder<int> optionalIntMoved{std::move(optionalInt)};
196
1
    ASSERT_EQ(1, *optionalIntMoved);
197
198
1
    InplaceOptionalHolder<int> emptyOptionalInt;
199
1
    InplaceOptionalHolder<int> emptyOptionalIntMoved{std::move(emptyOptionalInt)};
200
1
    ASSERT_EQ(false, emptyOptionalIntMoved.hasValue());
201
1
}
202
203
TEST_F(InplaceOptionalHolderTest, moveConstructorNoInit)
204
1
{
205
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObject;
206
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObjectMoved{NoInit, std::move(optionalEmptyObject)};
207
1
    ASSERT_FALSE(optionalEmptyObjectMoved.hasValue());
208
209
1
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
210
1
    ASSERT_EQ(10, optionalObject->getValue());
211
1
    ASSERT_FALSE(optionalObject->isNoInit());
212
213
1
    InplaceOptionalHolder<DummyObject> optionalObjectMoved{NoInit, std::move(optionalObject)};
214
1
    ASSERT_EQ(10, optionalObjectMoved->getValue());
215
1
    ASSERT_TRUE(optionalObjectMoved->isNoInit());
216
1
}
217
218
TEST_F(InplaceOptionalHolderTest, moveValueConstructorNoInit)
219
1
{
220
1
    InplaceOptionalHolder<DummyObject> optionalObjectMoved{NoInit, DummyObject{10}};
221
1
    ASSERT_EQ(10, optionalObjectMoved->getValue());
222
1
    ASSERT_TRUE(optionalObjectMoved->isNoInit());
223
1
}
224
225
TEST_F(InplaceOptionalHolderTest, forwardingConstructor)
226
1
{
227
1
    {
228
1
        InPlaceT inPlace{};
229
1
        std::vector<int> src = {0, 13, 42};
230
1
        InplaceOptionalHolder<std::vector<int>> optional{inPlace, src.begin(), src.end()};
231
1
        ASSERT_EQ(src, *optional);
232
1
    }
233
234
1
    {
235
1
        std::vector<int> src = {0, 13, 42};
236
1
        InplaceOptionalHolder<std::vector<int>> optional{InPlace, src.begin(), src.end()};
237
1
        ASSERT_EQ(src, *optional);
238
1
    }
239
1
}
240
241
TEST_F(InplaceOptionalHolderTest, moveAssignmentOperator)
242
1
{
243
1
    InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}};
244
1
    std::vector<int> origValues{*optionalVector};
245
1
    void* origAddress = (*optionalVector).data();
246
247
1
    InplaceOptionalHolder<std::vector<int>>& optionalVectorRef(optionalVector);
248
1
    optionalVectorRef = std::move(optionalVector);
249
1
    ASSERT_EQ(origAddress, (*optionalVectorRef).data());
250
1
    ASSERT_EQ(origValues, *optionalVectorRef);
251
252
1
    InplaceOptionalHolder<std::vector<int>> optionalVectorMoved;
253
1
    optionalVectorMoved = std::move(optionalVectorRef);
254
1
    ASSERT_EQ(origAddress, (*optionalVectorMoved).data());
255
1
    ASSERT_EQ(origValues, *optionalVectorMoved);
256
257
1
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVector;
258
1
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVectorMoved;
259
1
    emptyOptionalVectorMoved = std::move(emptyOptionalVector);
260
1
    ASSERT_EQ(false, emptyOptionalVectorMoved.hasValue());
261
1
}
262
263
TEST_F(InplaceOptionalHolderTest, moveAssignmentOperatorNoInit)
264
1
{
265
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObject;
266
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObjectMoved;
267
1
    optionalEmptyObjectMoved.assign(NoInit, std::move(optionalEmptyObject));
268
1
    ASSERT_FALSE(optionalEmptyObjectMoved.hasValue());
269
270
1
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
271
1
    ASSERT_EQ(10, optionalObject->getValue());
272
1
    ASSERT_FALSE(optionalObject->isNoInit());
273
1
    optionalObject.assign(NoInit, std::move(optionalObject));
274
275
1
    InplaceOptionalHolder<DummyObject> optionalObjectMoved;
276
1
    optionalObjectMoved.assign(NoInit, std::move(optionalObject));
277
1
    ASSERT_EQ(10, optionalObjectMoved->getValue());
278
    // memory with object has been moved in optional holder, object move constructor has not been called
279
1
    ASSERT_TRUE(optionalObjectMoved->isNoInit());
280
1
}
281
282
TEST_F(InplaceOptionalHolderTest, lvalueAssignmentOperator)
283
1
{
284
1
    std::vector<int> values{1, 2, 3};
285
1
    void* origAddress = values.data();
286
1
    InplaceOptionalHolder<std::vector<int>> optional;
287
1
    optional = values;
288
1
    ASSERT_NE(origAddress, (*optional).data());
289
1
    ASSERT_EQ(values, *optional);
290
1
}
291
292
TEST_F(InplaceOptionalHolderTest, rvalueAssignmentOperator)
293
1
{
294
1
    std::vector<int> values{1, 2, 3};
295
1
    std::vector<int> origValues{values};
296
1
    void* origAddress = values.data();
297
1
    InplaceOptionalHolder<std::vector<int>> optional;
298
1
    optional = std::move(values);
299
1
    ASSERT_EQ(origAddress, (*optional).data());
300
1
    ASSERT_EQ(origValues, *optional);
301
1
}
302
303
TEST_F(InplaceOptionalHolderTest, reset)
304
1
{
305
1
    InplaceOptionalHolder<std::vector<int>> optional{std::vector<int>{1, 2, 3}};
306
1
    ASSERT_TRUE(optional.hasValue());
307
1
    ASSERT_EQ(1, (*optional)[0]);
308
309
1
    optional.reset();
310
1
    ASSERT_FALSE(optional.hasValue());
311
312
1
    optional = std::vector<int>{3, 2, 1};
313
1
    ASSERT_TRUE(optional.hasValue());
314
1
    ASSERT_EQ(3, (*optional)[0]);
315
316
1
    optional.reset();
317
1
    ASSERT_FALSE(optional.hasValue());
318
1
}
319
320
TEST_F(InplaceOptionalHolderTest, operatorEquality)
321
1
{
322
1
    InplaceOptionalHolder<int> optional1;
323
1
    optional1 = 0xDEAD;
324
1
    InplaceOptionalHolder<int> optional2;
325
1
    optional2 = 0xDEAD;
326
1
    InplaceOptionalHolder<int> optional3;
327
1
    optional3 = 0xBEEF;
328
1
    InplaceOptionalHolder<int> optional4;
329
1
    InplaceOptionalHolder<int> optional5;
330
1
    InplaceOptionalHolder<int> optional6;
331
332
1
    ASSERT_TRUE(optional1 == optional1);
333
1
    ASSERT_TRUE(optional1 == optional2);
334
1
    ASSERT_FALSE(optional1 == optional3);
335
1
    ASSERT_FALSE(optional1 == optional4);
336
1
    ASSERT_TRUE(optional5 == optional6);
337
1
    ASSERT_FALSE(optional5 == optional1);
338
1
}
339
340
TEST_F(InplaceOptionalHolderTest, operatorLessThan)
341
1
{
342
1
    InplaceOptionalHolder<int> optionalEmpty1;
343
1
    InplaceOptionalHolder<int> optionalEmpty2;
344
1
    InplaceOptionalHolder<int> optional1(1);
345
1
    InplaceOptionalHolder<int> optional2(2);
346
347
1
    ASSERT_FALSE(optionalEmpty1 < optionalEmpty2);
348
1
    ASSERT_TRUE(optionalEmpty1 < optional1);
349
1
    ASSERT_FALSE(optional1 < optionalEmpty1);
350
1
    ASSERT_TRUE(optional1 < optional2);
351
1
    ASSERT_FALSE(optional2 < optional1);
352
1
}
353
354
TEST_F(InplaceOptionalHolderTest, setGet)
355
1
{
356
1
    InplaceOptionalHolder<int> optionalInt;
357
1
    ASSERT_THROW(*optionalInt, CppRuntimeException);
358
1
    const int intValue = 0xDEAD;
359
1
    optionalInt = intValue;
360
1
    ASSERT_EQ(intValue, *optionalInt);
361
362
1
    InplaceOptionalHolder<float> optionalFloat;
363
1
    ASSERT_THROW(*optionalFloat, CppRuntimeException);
364
1
    const float floatValue = 3.14F;
365
1
    optionalFloat = floatValue;
366
1
    ASSERT_EQ(floatValue, optionalFloat.value());
367
368
1
    InplaceOptionalHolder<DummyObject> optionalObject;
369
1
    ASSERT_THROW(*optionalObject, CppRuntimeException);
370
1
    DummyObject objectValue;
371
1
    objectValue.setValue(intValue);
372
1
    optionalObject = objectValue;
373
1
    const DummyObject& readObjectValue = *optionalObject;
374
1
    ASSERT_EQ(intValue, readObjectValue.getValue());
375
1
    ASSERT_EQ(intValue, optionalObject->getValue());
376
1
}
377
378
TEST_F(InplaceOptionalHolderTest, hasValue)
379
1
{
380
1
    InplaceOptionalHolder<int> optionalInt;
381
1
    ASSERT_THROW(*optionalInt, CppRuntimeException);
382
1
    ASSERT_EQ(false, optionalInt.hasValue());
383
384
1
    optionalInt = 0xDEAD;
385
1
    ASSERT_EQ(true, optionalInt.hasValue());
386
1
}
387
388
TEST_F(InplaceOptionalHolderTest, constGet)
389
1
{
390
1
    const int intValue = 0xDEAD;
391
1
    InplaceOptionalHolder<int> optional;
392
1
    optional = intValue;
393
1
    const InplaceOptionalHolder<int> constOptional(optional);
394
1
    ASSERT_EQ(intValue, *constOptional);
395
1
    ASSERT_EQ(intValue, constOptional.value());
396
397
1
    DummyObject objectValue;
398
1
    objectValue.setValue(intValue);
399
1
    InplaceOptionalHolder<DummyObject> optionalObject{objectValue};
400
1
    ASSERT_EQ(intValue, optionalObject->getValue());
401
1
}
402
403
} // namespace zserio