1 // Copyright 2018 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/base/optional.h"
16
17 #include <gtest/gtest.h>
18
19 #include <memory>
20 #include <vector>
21
22 namespace astc_codec {
23 namespace base {
24
TEST(Optional,TypeProperties)25 TEST(Optional, TypeProperties) {
26 // Making sure optional has the correct alignment and doesn't waste too much
27 // space
28
29 static_assert(sizeof(Optional<bool>) == 2, "bad Optional<bool> size");
30 static_assert(std::alignment_of<Optional<bool>>::value ==
31 std::alignment_of<bool>::value,
32 "bad Optional<bool> alignment");
33
34 static_assert(sizeof(Optional<char>) == 2, "bad Optional<char> size");
35 static_assert(std::alignment_of<Optional<char>>::value ==
36 std::alignment_of<char>::value,
37 "bad Optional<char> alignment");
38
39 static_assert(sizeof(Optional<int16_t>) == 4, "bad Optional<int16_t> size");
40 static_assert(std::alignment_of<Optional<int16_t>>::value ==
41 std::alignment_of<int16_t>::value,
42 "bad Optional<int16_t> alignment");
43
44 static_assert(sizeof(Optional<int32_t>) == 8, "bad Optional<int32_t> size");
45 static_assert(std::alignment_of<Optional<int32_t>>::value ==
46 std::alignment_of<int32_t>::value,
47 "bad Optional<int32_t> alignment");
48
49 static_assert(sizeof(Optional<int64_t>) == 16, "bad Optional<int64_t> size");
50 static_assert(std::alignment_of<Optional<int64_t>>::value ==
51 std::alignment_of<int64_t>::value,
52 "bad Optional<int64_t> alignment");
53
54 struct S128 {
55 int64_t data[2];
56 };
57
58 static_assert(sizeof(Optional<S128>) == 3 * sizeof(int64_t),
59 "bad Optional<S128> size");
60 static_assert(std::alignment_of<Optional<S128>>::value ==
61 std::alignment_of<S128>::value,
62 "bad Optional<S128> alignment");
63 }
64
TEST(Optional,ConstructFromValue)65 TEST(Optional, ConstructFromValue) {
66 {
67 Optional<int> o;
68 EXPECT_FALSE(o);
69 }
70 {
71 Optional<int> o = {};
72 EXPECT_FALSE(o);
73 }
74 {
75 Optional<int> o = kNullopt;
76 EXPECT_FALSE(o);
77 }
78 {
79 Optional<int> o(1);
80 EXPECT_TRUE(o);
81 EXPECT_EQ(1, *o);
82 }
83 {
84 // check the std::decay<> constructor
85 Optional<int> o = static_cast<const short&>(1);
86 EXPECT_TRUE(o);
87 EXPECT_EQ(1, *o);
88 }
89 {
90 Optional<int> o = 1;
91 EXPECT_TRUE(o);
92 EXPECT_EQ(1, *o);
93 }
94 {
95 Optional<int> o{1};
96 EXPECT_TRUE(o);
97 EXPECT_EQ(1, *o);
98 }
99 {
100 short val = 10;
101 Optional<int> o = val;
102 EXPECT_TRUE(o);
103 EXPECT_EQ(10, *o);
104 }
105 {
106 Optional<std::vector<int>> o(kInplace, 10);
107 EXPECT_TRUE(o);
108 EXPECT_EQ((std::vector<int>(10)), *o);
109 }
110 {
111 Optional<std::vector<int>> o(kInplace, {1, 2, 3, 4});
112 EXPECT_TRUE(o);
113 EXPECT_EQ((std::vector<int>{1, 2, 3, 4}), *o);
114 }
115 }
116
TEST(Optional,ConstructFromOptional)117 TEST(Optional, ConstructFromOptional) {
118 {
119 Optional<int> o = Optional<int>();
120 EXPECT_FALSE(o);
121 }
122 {
123 Optional<short> o2;
124 Optional<int> o(o2);
125 EXPECT_FALSE(o);
126 }
127 {
128 Optional<short> o2 = 42;
129 Optional<int> o(o2);
130 EXPECT_TRUE(o);
131 EXPECT_EQ(42, *o);
132 }
133 {
134 Optional<int> o(Optional<int>(1));
135 EXPECT_TRUE(o);
136 EXPECT_EQ(1, *o);
137 }
138 {
139 Optional<int> o2 = 2;
140 Optional<int> o = o2;
141 EXPECT_TRUE(o);
142 EXPECT_EQ(2, *o);
143 }
144 {
145 Optional<std::vector<int>> o2 = std::vector<int>{20, 30, 40};
146 Optional<std::vector<int>> o = o2;
147 EXPECT_TRUE(o);
148 EXPECT_EQ((std::vector<int>{20, 30, 40}), *o);
149 }
150 }
151
TEST(Optional,Assign)152 TEST(Optional, Assign) {
153 {
154 Optional<int> o;
155 o = 1;
156 EXPECT_TRUE(o);
157 EXPECT_EQ(1, *o);
158
159 o = 2;
160 EXPECT_TRUE(o);
161 EXPECT_EQ(2, *o);
162
163 o = kNullopt;
164 EXPECT_FALSE(o);
165
166 o = Optional<int>(10);
167 EXPECT_TRUE(o);
168 EXPECT_EQ(10, *o);
169
170 Optional<int> o2;
171 o = o2;
172 EXPECT_FALSE(o);
173
174 o = 2u;
175 EXPECT_TRUE(o);
176 EXPECT_EQ(2, *o);
177
178 o = Optional<short>();
179 EXPECT_FALSE(o);
180
181 o = Optional<short>(20);
182 EXPECT_TRUE(o);
183 EXPECT_EQ(20, *o);
184
185 Optional<short> o3(200);
186 o = o3;
187 EXPECT_TRUE(o);
188 EXPECT_EQ(200, *o);
189
190 o = {};
191 EXPECT_FALSE(o);
192
193 // check the std::decay<> assignment
194 o = static_cast<const short&>(1);
195 EXPECT_TRUE(o);
196 EXPECT_EQ(1, *o);
197 }
198 }
199
TEST(Optional,MakeOptional)200 TEST(Optional, MakeOptional) {
201 {
202 auto o = makeOptional(1);
203 static_assert(std::is_same<decltype(o), Optional<int>>::value,
204 "Bad type deduction in makeOptional()");
205 EXPECT_TRUE(o);
206 EXPECT_EQ(1, *o);
207 }
208 {
209 auto o = makeOptional(std::vector<char>{'1', '2'});
210 static_assert(std::is_same<decltype(o), Optional<std::vector<char>>>::value,
211 "Bad type deduction in makeOptional()");
212 EXPECT_TRUE(o);
213 EXPECT_EQ((std::vector<char>{'1', '2'}), *o);
214 }
215 {
216 // check std::decay<> in the factory function
217 auto o = makeOptional("String");
218 static_assert(std::is_same<decltype(o), Optional<const char*>>::value,
219 "Bad type deduction in makeOptional()");
220 EXPECT_TRUE(o);
221 EXPECT_STREQ("String", *o);
222 }
223 {
224 auto o = makeOptional<std::string>("String");
225 static_assert(std::is_same<decltype(o), Optional<std::string>>::value,
226 "Bad type deduction in makeOptional()");
227 EXPECT_TRUE(o);
228 EXPECT_STREQ("String", o->c_str());
229 }
230 {
231 auto o = makeOptional<std::string>(5, 'b');
232 static_assert(std::is_same<decltype(o), Optional<std::string>>::value,
233 "Bad type deduction in makeOptional()");
234 EXPECT_TRUE(o);
235 EXPECT_STREQ("bbbbb", o->c_str());
236 }
237 {
238 auto o = makeOptional<std::string>();
239 static_assert(std::is_same<decltype(o), Optional<std::string>>::value,
240 "Bad type deduction in makeOptional()");
241 EXPECT_TRUE(o);
242 EXPECT_STREQ("", o->c_str());
243 }
244 }
245
TEST(Optional,Move)246 TEST(Optional, Move) {
247 auto o = makeOptional(std::unique_ptr<int>(new int(10)));
248 {
249 decltype(o) o2 = std::move(o);
250 EXPECT_TRUE(o);
251 EXPECT_TRUE(o2);
252 EXPECT_FALSE(bool(*o));
253 EXPECT_TRUE(bool(*o2));
254 EXPECT_EQ(10, **o2);
255
256 decltype(o) o3;
257 o3 = std::move(o2);
258 EXPECT_TRUE(o2);
259 EXPECT_TRUE(o3);
260 EXPECT_FALSE(bool(*o2));
261 EXPECT_TRUE(bool(*o3));
262 EXPECT_EQ(10, **o3);
263
264 o3 = std::move(o2);
265 EXPECT_TRUE(o2);
266 EXPECT_TRUE(o3);
267 EXPECT_FALSE(bool(*o2));
268 EXPECT_FALSE(bool(*o3));
269 }
270
271 {
272 decltype(o) o1;
273 decltype(o) o2 = std::move(o1);
274 EXPECT_FALSE(o1);
275 EXPECT_FALSE(o2);
276
277 o2 = std::move(o1);
278 EXPECT_FALSE(o1);
279 EXPECT_FALSE(o2);
280
281 decltype(o) o3{kInplace, new int(20)};
282 o3 = std::move(o1);
283 EXPECT_FALSE(o1);
284 EXPECT_FALSE(o3);
285 }
286 }
287
TEST(Optional,Value)288 TEST(Optional, Value) {
289 auto o = makeOptional(1);
290 EXPECT_EQ(1, o.value());
291 EXPECT_EQ(1, o.valueOr(2));
292
293 o = kNullopt;
294 EXPECT_EQ(2, o.valueOr(2));
295 }
296
TEST(Optional,Clear)297 TEST(Optional, Clear) {
298 auto o = makeOptional(1);
299 o.clear();
300 EXPECT_FALSE(o);
301
302 o.clear();
303 EXPECT_FALSE(o);
304 }
305
TEST(Optional,Emplace)306 TEST(Optional, Emplace) {
307 auto o = makeOptional(std::vector<int>{1, 2, 3, 4});
308 o.emplace(3, 1);
309 EXPECT_TRUE(o);
310 EXPECT_EQ((std::vector<int>{1, 1, 1}), *o);
311 EXPECT_EQ(3U, o->capacity());
312
313 o.clear();
314 o.emplace({1, 2});
315 EXPECT_TRUE(o);
316 EXPECT_EQ((std::vector<int>{1, 2}), *o);
317 EXPECT_EQ(2U, o->capacity());
318 }
319
TEST(Optional,Reset)320 TEST(Optional, Reset) {
321 auto o = makeOptional(std::vector<int>{1, 2, 3, 4});
322 o.reset(std::vector<int>{4, 3});
323 EXPECT_TRUE(o);
324 EXPECT_EQ((std::vector<int>{4, 3}), *o);
325 EXPECT_EQ(2U, o->capacity());
326
327 o.clear();
328 o.reset(std::vector<int>{1});
329 EXPECT_EQ((std::vector<int>{1}), *o);
330 EXPECT_EQ(1U, o->capacity());
331 }
332
TEST(Optional,CompareEqual)333 TEST(Optional, CompareEqual) {
334 EXPECT_TRUE(makeOptional(1) == makeOptional(1));
335 EXPECT_TRUE(makeOptional(1) == 1);
336 EXPECT_TRUE(1 == makeOptional(1));
337 EXPECT_FALSE(makeOptional(1) == makeOptional(2));
338 EXPECT_FALSE(makeOptional(2) == 1);
339 EXPECT_FALSE(2 == makeOptional(1));
340 EXPECT_TRUE(makeOptional(1) != makeOptional(2));
341 EXPECT_TRUE(makeOptional(1) != 2);
342 EXPECT_TRUE(1 != makeOptional(2));
343
344 EXPECT_FALSE(makeOptional(1) == kNullopt);
345 EXPECT_FALSE(makeOptional(1) == Optional<int>());
346 EXPECT_FALSE(kNullopt == makeOptional(1));
347 EXPECT_FALSE(Optional<int>() == makeOptional(1));
348 EXPECT_TRUE(makeOptional(1) != kNullopt);
349 EXPECT_TRUE(makeOptional(1) != Optional<int>());
350 EXPECT_TRUE(kNullopt != makeOptional(1));
351 EXPECT_TRUE(Optional<int>() != makeOptional(1));
352
353 EXPECT_TRUE(kNullopt == Optional<int>());
354 EXPECT_TRUE(kNullopt == Optional<char*>());
355 EXPECT_FALSE(kNullopt != Optional<int>());
356 EXPECT_FALSE(kNullopt != Optional<char*>());
357 EXPECT_TRUE(Optional<int>() == Optional<int>());
358 EXPECT_FALSE(Optional<int>() != Optional<int>());
359 }
360
TEST(Optional,CompareLess)361 TEST(Optional, CompareLess) {
362 EXPECT_TRUE(makeOptional(1) < makeOptional(2));
363 EXPECT_TRUE(1 < makeOptional(2));
364 EXPECT_TRUE(makeOptional(1) < 2);
365
366 EXPECT_FALSE(makeOptional(1) < makeOptional(1));
367 EXPECT_FALSE(1 < makeOptional(1));
368 EXPECT_FALSE(makeOptional(1) < 1);
369 EXPECT_FALSE(makeOptional(2) < makeOptional(1));
370 EXPECT_FALSE(2 < makeOptional(1));
371 EXPECT_FALSE(makeOptional(2) < 1);
372
373 EXPECT_TRUE(kNullopt < makeOptional(2));
374 EXPECT_TRUE(Optional<int>() < makeOptional(2));
375 EXPECT_TRUE(Optional<int>() < 2);
376 EXPECT_FALSE(makeOptional(2) < kNullopt);
377 EXPECT_FALSE(makeOptional(2) < Optional<int>());
378 EXPECT_FALSE(2 < Optional<int>());
379
380 EXPECT_FALSE(kNullopt < Optional<int>());
381 EXPECT_FALSE(Optional<int>() < kNullopt);
382 }
383
TEST(Optional,Destruction)384 TEST(Optional, Destruction) {
385 // create a reference counting class to check if we delete everything
386 // we've created
387 struct Track {
388 Track(int& val) : mVal(val) { ++mVal.get(); }
389 Track(std::initializer_list<int*> vals) : mVal(**vals.begin()) {
390 ++mVal.get();
391 }
392 Track(const Track& other) : mVal(other.mVal) { ++mVal.get(); }
393 Track(Track&& other) : mVal(other.mVal) { ++mVal.get(); }
394 Track& operator=(const Track& other) {
395 --mVal.get();
396 mVal = other.mVal;
397 ++mVal.get();
398 return *this;
399 }
400 Track& operator=(Track&& other) {
401 --mVal.get();
402 mVal = other.mVal;
403 ++mVal.get();
404 return *this;
405 }
406
407 ~Track() { --mVal.get(); }
408
409 std::reference_wrapper<int> mVal;
410 };
411
412 int counter = 0;
413 {
414 auto o = makeOptional(Track(counter));
415 EXPECT_EQ(1, counter);
416 }
417 EXPECT_EQ(0, counter);
418
419 {
420 auto o = makeOptional(Track(counter));
421 EXPECT_EQ(1, counter);
422 o.clear();
423 EXPECT_EQ(0, counter);
424 }
425 EXPECT_EQ(0, counter);
426
427 {
428 auto o = makeOptional(Track(counter));
429 EXPECT_EQ(1, counter);
430 int counter2 = 0;
431 o.emplace(counter2);
432 EXPECT_EQ(0, counter);
433 EXPECT_EQ(1, counter2);
434 o = Track(counter);
435 EXPECT_EQ(1, counter);
436 EXPECT_EQ(0, counter2);
437
438 auto o2 = o;
439 EXPECT_EQ(2, counter);
440 EXPECT_EQ(0, counter2);
441 }
442 EXPECT_EQ(0, counter);
443
444 {
445 auto o = makeOptional(Track(counter));
446 auto o2 = std::move(o);
447 EXPECT_EQ(2, counter);
448 o = o2;
449 EXPECT_EQ(2, counter);
450 }
451 EXPECT_EQ(0, counter);
452
453 int counter2 = 0;
454 {
455 Optional<Track> o;
456 o.emplace(counter);
457 EXPECT_EQ(1, counter);
458
459 o.emplace(counter2);
460 EXPECT_EQ(0, counter);
461 EXPECT_EQ(1, counter2);
462 }
463 EXPECT_EQ(0, counter);
464 EXPECT_EQ(0, counter2);
465
466 {
467 Optional<Track> o;
468 o.emplace({&counter});
469 EXPECT_EQ(1, counter);
470
471 counter2 = 0;
472 o.emplace({&counter2});
473 EXPECT_EQ(0, counter);
474 EXPECT_EQ(1, counter2);
475 }
476 EXPECT_EQ(0, counter);
477 EXPECT_EQ(0, counter2);
478 }
479
480 } // namespace base
481 } // namespace astc_codec
482