Coverage Report

Created: 2023-12-13 14:58

test/zserio/InplaceOptionalHolderTest.cpp
Line
Count
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
class InplaceOptionalHolderTest : public ::testing::Test
34
{
35
protected:
36
};
37
38
TEST_F(InplaceOptionalHolderTest, emptyConstructor)
39
1
{
40
1
    InplaceOptionalHolder<int> optional;
41
1
    ASSERT_FALSE(optional.hasValue());
42
1
}
43
44
TEST_F(InplaceOptionalHolderTest, nullOptConstructor)
45
1
{
46
1
    {
47
1
        NullOptType nullOpt{int()};
48
1
        InplaceOptionalHolder<int> optional{nullOpt};
49
1
        ASSERT_FALSE(optional.hasValue());
50
1
    }
51
52
1
    {
53
1
        InplaceOptionalHolder<int> optional{NullOpt};
54
1
        ASSERT_FALSE(optional.hasValue());
55
1
    }
56
1
}
57
58
TEST_F(InplaceOptionalHolderTest, lvalueConstructor)
59
1
{
60
1
    std::vector<int> values{1, 2, 3};
61
1
    void* origAddress = values.data();
62
1
    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
1
    InplaceOptionalHolder<std::vector<int>> optionalFromList{{1, 2, 3}};
68
1
    std::vector<int> listValues{1, 2, 3};
69
1
    ASSERT_EQ(listValues, *optionalFromList);
70
1
}
71
72
TEST_F(InplaceOptionalHolderTest, rvalueConstructor)
73
1
{
74
1
    std::vector<int> values{1, 2, 3};
75
1
    std::vector<int> origValues{values};
76
1
    void* origAddress = values.data();
77
1
    InplaceOptionalHolder<std::vector<int>> optional{std::move(values)};
78
1
    ASSERT_EQ(origAddress, (*optional).data());
79
1
    ASSERT_EQ(origValues, *optional);
80
1
}
81
82
TEST_F(InplaceOptionalHolderTest, copyConstructor)
83
1
{
84
1
    InplaceOptionalHolder<int> optional;
85
1
    ASSERT_THROW(*optional, CppRuntimeException);
86
1
    const int intValue = 0xDEAD;
87
1
    optional = intValue;
88
89
1
    InplaceOptionalHolder<int> optionalCopy(optional);
90
1
    ASSERT_EQ(intValue, *optionalCopy);
91
92
1
    InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}};
93
1
    void* origAddress = (*optionalVector).data();
94
1
    InplaceOptionalHolder<std::vector<int>> optionalVectorCopy{optionalVector};
95
1
    ASSERT_NE(origAddress, (*optionalVectorCopy).data());
96
1
    ASSERT_EQ(*optionalVector, *optionalVectorCopy);
97
98
1
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
99
1
    InplaceOptionalHolder<DummyObject> optionalObjectCopy = optionalObject;
100
1
    ASSERT_EQ(optionalObject, optionalObjectCopy);
101
1
}
102
103
TEST_F(InplaceOptionalHolderTest, copyConstructorNoInit)
104
1
{
105
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObject;
106
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObjectCopy{NoInit, optionalEmptyObject};
107
1
    ASSERT_EQ(optionalEmptyObject, optionalEmptyObjectCopy);
108
109
1
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
110
1
    InplaceOptionalHolder<DummyObject> optionalObjectCopy{NoInit, optionalObject};
111
1
    ASSERT_EQ(optionalObject, optionalObjectCopy);
112
1
    ASSERT_FALSE(optionalObject->isNoInit());
113
1
    ASSERT_TRUE(optionalObjectCopy->isNoInit());
114
1
}
115
116
TEST_F(InplaceOptionalHolderTest, copyAssignmentOperator)
117
1
{
118
1
    InplaceOptionalHolder<int> optional;
119
1
    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
1
    InplaceOptionalHolder<int> optionalCopy;
128
1
    optionalCopy = optional;
129
1
    ASSERT_EQ(intValue, *optionalCopy);
130
131
1
    InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}};
132
1
    void* origAddress = (*optionalVector).data();
133
1
    InplaceOptionalHolder<std::vector<int>> optionalVectorCopy;
134
1
    optionalVectorCopy = optionalVector;
135
1
    ASSERT_NE(origAddress, ((*optionalVectorCopy).data()));
136
1
    ASSERT_EQ(*optionalVector, *optionalVectorCopy);
137
138
1
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVector;
139
1
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVectorCopy;
140
1
    emptyOptionalVectorCopy = emptyOptionalVector;
141
1
    ASSERT_EQ(false, emptyOptionalVectorCopy.hasValue());
142
1
}
143
144
TEST_F(InplaceOptionalHolderTest, copyAssignmentOperatorNoInit)
145
1
{
146
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObject;
147
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObjectCopy;
148
1
    optionalEmptyObjectCopy.assign(NoInit, optionalEmptyObject);
149
1
    ASSERT_EQ(optionalEmptyObject, optionalEmptyObjectCopy);
150
151
1
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
152
1
    optionalObject.assign(NoInit, optionalObject);
153
154
1
    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
1
}
160
161
TEST_F(InplaceOptionalHolderTest, moveConstructor)
162
1
{
163
1
    InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}};
164
1
    std::vector<int> origValues{*optionalVector};
165
1
    void* origAddress = (*optionalVector).data();
166
1
    InplaceOptionalHolder<std::vector<int>> optionalVectorMoved{std::move(optionalVector)};
167
1
    ASSERT_EQ(origAddress, ((*optionalVectorMoved).data()));
168
1
    ASSERT_EQ(origValues, *optionalVectorMoved);
169
170
1
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVector;
171
1
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVectorMoved{std::move(emptyOptionalVector)};
172
1
    ASSERT_EQ(false, emptyOptionalVectorMoved.hasValue());
173
174
1
    InplaceOptionalHolder<int> optionalInt{1};
175
1
    InplaceOptionalHolder<int> optionalIntMoved{std::move(optionalInt)};
176
1
    ASSERT_EQ(1, *optionalIntMoved);
177
178
1
    InplaceOptionalHolder<int> emptyOptionalInt;
179
1
    InplaceOptionalHolder<int> emptyOptionalIntMoved{std::move(emptyOptionalInt)};
180
1
    ASSERT_EQ(false, emptyOptionalIntMoved.hasValue());
181
1
}
182
183
TEST_F(InplaceOptionalHolderTest, moveConstructorNoInit)
184
1
{
185
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObject;
186
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObjectMoved{NoInit, std::move(optionalEmptyObject)};
187
1
    ASSERT_FALSE(optionalEmptyObjectMoved.hasValue());
188
189
1
    InplaceOptionalHolder<DummyObject> optionalObject(DummyObject{10});
190
1
    ASSERT_EQ(10, optionalObject->getValue());
191
1
    ASSERT_FALSE(optionalObject->isNoInit());
192
193
1
    InplaceOptionalHolder<DummyObject> optionalObjectMoved{NoInit, std::move(optionalObject)};
194
1
    ASSERT_EQ(10, optionalObjectMoved->getValue());
195
1
    ASSERT_TRUE(optionalObjectMoved->isNoInit());
196
1
}
197
198
TEST_F(InplaceOptionalHolderTest, moveValueConstructorNoInit)
199
1
{
200
1
    InplaceOptionalHolder<DummyObject> optionalObjectMoved{NoInit, DummyObject{10}};
201
1
    ASSERT_EQ(10, optionalObjectMoved->getValue());
202
1
    ASSERT_TRUE(optionalObjectMoved->isNoInit());
203
1
}
204
205
TEST_F(InplaceOptionalHolderTest, forwardingConstructor)
206
1
{
207
1
    {
208
1
        InPlaceT inPlace{};
209
1
        std::vector<int> src = {0, 13, 42};
210
1
        InplaceOptionalHolder<std::vector<int>> optional{inPlace, src.begin(), src.end()};
211
1
        ASSERT_EQ(src, *optional);
212
1
    }
213
214
1
    {
215
1
        std::vector<int> src = {0, 13, 42};
216
1
        InplaceOptionalHolder<std::vector<int>> optional{InPlace, src.begin(), src.end()};
217
1
        ASSERT_EQ(src, *optional);
218
1
    }
219
1
}
220
221
TEST_F(InplaceOptionalHolderTest, moveAssignmentOperator)
222
1
{
223
1
    InplaceOptionalHolder<std::vector<int>> optionalVector{std::vector<int>{1, 2, 3}};
224
1
    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
1
    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
1
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVector;
238
1
    InplaceOptionalHolder<std::vector<int>> emptyOptionalVectorMoved;
239
1
    emptyOptionalVectorMoved = std::move(emptyOptionalVector);
240
1
    ASSERT_EQ(false, emptyOptionalVectorMoved.hasValue());
241
1
}
242
243
TEST_F(InplaceOptionalHolderTest, moveAssignmentOperatorNoInit)
244
1
{
245
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObject;
246
1
    InplaceOptionalHolder<DummyObject> optionalEmptyObjectMoved;
247
1
    optionalEmptyObjectMoved.assign(NoInit, std::move(optionalEmptyObject));
248
1
    ASSERT_FALSE(optionalEmptyObjectMoved.hasValue());
249
250
1
    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
1
    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
1
}
261
262
TEST_F(InplaceOptionalHolderTest, lvalueAssignmentOperator)
263
1
{
264
1
    std::vector<int> values{1, 2, 3};
265
1
    void* origAddress = values.data();
266
1
    InplaceOptionalHolder<std::vector<int>> optional;
267
1
    optional = values;
268
1
    ASSERT_NE(origAddress, (*optional).data());
269
1
    ASSERT_EQ(values, *optional);
270
1
}
271
272
TEST_F(InplaceOptionalHolderTest, rvalueAssignmentOperator)
273
1
{
274
1
    std::vector<int> values{1, 2, 3};
275
1
    std::vector<int> origValues{values};
276
1
    void* origAddress = values.data();
277
1
    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
1
}
282
283
TEST_F(InplaceOptionalHolderTest, reset)
284
1
{
285
1
    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
1
}
299
300
TEST_F(InplaceOptionalHolderTest, operatorEquality)
301
1
{
302
1
    InplaceOptionalHolder<int> optional1;
303
1
    optional1 = 0xDEAD;
304
1
    InplaceOptionalHolder<int> optional2;
305
1
    optional2 = 0xDEAD;
306
1
    InplaceOptionalHolder<int> optional3;
307
1
    optional3 = 0xBEEF;
308
1
    InplaceOptionalHolder<int> optional4;
309
1
    InplaceOptionalHolder<int> optional5;
310
1
    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
1
}
319
320
TEST_F(InplaceOptionalHolderTest, operatorLessThan)
321
1
{
322
1
    InplaceOptionalHolder<int> optionalEmpty1;
323
1
    InplaceOptionalHolder<int> optionalEmpty2;
324
1
    InplaceOptionalHolder<int> optional1(1);
325
1
    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
1
}
333
334
TEST_F(InplaceOptionalHolderTest, setGet)
335
1
{
336
1
    InplaceOptionalHolder<int> optionalInt;
337
1
    ASSERT_THROW(*optionalInt, CppRuntimeException);
338
1
    const int intValue = 0xDEAD;
339
1
    optionalInt = intValue;
340
1
    ASSERT_EQ(intValue, *optionalInt);
341
342
1
    InplaceOptionalHolder<float> optionalFloat;
343
1
    ASSERT_THROW(*optionalFloat, CppRuntimeException);
344
1
    const float floatValue = 3.14F;
345
1
    optionalFloat = floatValue;
346
1
    ASSERT_EQ(floatValue, optionalFloat.value());
347
348
1
    InplaceOptionalHolder<DummyObject> optionalObject;
349
1
    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
1
}
357
358
TEST_F(InplaceOptionalHolderTest, hasValue)
359
1
{
360
1
    InplaceOptionalHolder<int> optionalInt;
361
1
    ASSERT_THROW(*optionalInt, CppRuntimeException);
362
1
    ASSERT_EQ(false, optionalInt.hasValue());
363
364
1
    optionalInt = 0xDEAD;
365
1
    ASSERT_EQ(true, optionalInt.hasValue());
366
1
}
367
368
TEST_F(InplaceOptionalHolderTest, constGet)
369
1
{
370
1
    const int intValue = 0xDEAD;
371
1
    InplaceOptionalHolder<int> optional;
372
1
    optional = intValue;
373
1
    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
1
    InplaceOptionalHolder<DummyObject> optionalObject{objectValue};
380
1
    ASSERT_EQ(intValue, optionalObject->getValue());
381
1
}
382
383
} // namespace zserio