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