1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "android-base/expected.h"
18
19 #include <cstdio>
20 #include <memory>
21 #include <string>
22
23 #include <gtest/gtest.h>
24
25 using android::base::expected;
26 using android::base::unexpected;
27
28 typedef expected<int, int> exp_int;
29 typedef expected<double, double> exp_double;
30 typedef expected<std::string, std::string> exp_string;
31 typedef expected<std::pair<std::string, int>, int> exp_pair;
32 typedef expected<void, int> exp_void;
33
34 struct T {
35 int a;
36 int b;
37 T() = default;
TT38 T(int a, int b) noexcept : a(a), b(b) {}
39 };
operator ==(const T & x,const T & y)40 bool operator==(const T& x, const T& y) {
41 return x.a == y.a && x.b == y.b;
42 }
operator !=(const T & x,const T & y)43 bool operator!=(const T& x, const T& y) {
44 return x.a != y.a || x.b != y.b;
45 }
46
47 struct E {
48 std::string message;
49 int cause;
EE50 E(const std::string& message, int cause) : message(message), cause(cause) {}
51 };
52
53 typedef expected<T,E> exp_complex;
54
TEST(Expected,testDefaultConstructible)55 TEST(Expected, testDefaultConstructible) {
56 exp_int e;
57 EXPECT_TRUE(e.has_value());
58 EXPECT_EQ(0, e.value());
59
60 exp_complex e2;
61 EXPECT_TRUE(e2.has_value());
62 EXPECT_EQ(T(0,0), e2.value());
63
64 exp_void e3;
65 EXPECT_TRUE(e3.has_value());
66 }
67
TEST(Expected,testCopyConstructible)68 TEST(Expected, testCopyConstructible) {
69 exp_int e;
70 exp_int e2 = e;
71
72 EXPECT_TRUE(e.has_value());
73 EXPECT_TRUE(e2.has_value());
74 EXPECT_EQ(0, e.value());
75 EXPECT_EQ(0, e2.value());
76
77 exp_void e3;
78 exp_void e4 = e3;
79 EXPECT_TRUE(e3.has_value());
80 EXPECT_TRUE(e4.has_value());
81 }
82
TEST(Expected,testMoveConstructible)83 TEST(Expected, testMoveConstructible) {
84 exp_int e;
85 exp_int e2 = std::move(e);
86
87 EXPECT_TRUE(e.has_value());
88 EXPECT_TRUE(e2.has_value());
89 EXPECT_EQ(0, e.value());
90 EXPECT_EQ(0, e2.value());
91
92 exp_string e3(std::string("hello"));
93 exp_string e4 = std::move(e3);
94
95 EXPECT_TRUE(e3.has_value());
96 EXPECT_TRUE(e4.has_value());
97 EXPECT_EQ("", e3.value()); // e3 is moved
98 EXPECT_EQ("hello", e4.value());
99
100 exp_void e5;
101 exp_void e6 = std::move(e5);
102 EXPECT_TRUE(e5.has_value());
103 EXPECT_TRUE(e6.has_value());
104 }
105
TEST(Expected,testCopyConstructibleFromConvertibleType)106 TEST(Expected, testCopyConstructibleFromConvertibleType) {
107 exp_double e = 3.3;
108 exp_int e2 = e;
109
110 EXPECT_TRUE(e.has_value());
111 EXPECT_TRUE(e2.has_value());
112 EXPECT_EQ(3.3, e.value());
113 EXPECT_EQ(3, e2.value());
114 }
115
TEST(Expected,testMoveConstructibleFromConvertibleType)116 TEST(Expected, testMoveConstructibleFromConvertibleType) {
117 exp_double e = 3.3;
118 exp_int e2 = std::move(e);
119
120 EXPECT_TRUE(e.has_value());
121 EXPECT_TRUE(e2.has_value());
122 EXPECT_EQ(3.3, e.value());
123 EXPECT_EQ(3, e2.value());
124 }
125
TEST(Expected,testConstructibleFromValue)126 TEST(Expected, testConstructibleFromValue) {
127 exp_int e = 3;
128 exp_double e2 = 5.5;
129 exp_string e3 = std::string("hello");
130 exp_complex e4 = T(10, 20);
131 exp_void e5 = {};
132
133 EXPECT_TRUE(e.has_value());
134 EXPECT_TRUE(e2.has_value());
135 EXPECT_TRUE(e3.has_value());
136 EXPECT_TRUE(e4.has_value());
137 EXPECT_TRUE(e5.has_value());
138 EXPECT_EQ(3, e.value());
139 EXPECT_EQ(5.5, e2.value());
140 EXPECT_EQ("hello", e3.value());
141 EXPECT_EQ(T(10,20), e4.value());
142 }
143
TEST(Expected,testConstructibleFromMovedValue)144 TEST(Expected, testConstructibleFromMovedValue) {
145 std::string hello = "hello";
146 exp_string e = std::move(hello);
147
148 EXPECT_TRUE(e.has_value());
149 EXPECT_EQ("hello", e.value());
150 EXPECT_EQ("", hello);
151 }
152
TEST(Expected,testConstructibleFromConvertibleValue)153 TEST(Expected, testConstructibleFromConvertibleValue) {
154 exp_int e = 3.3; // double to int
155 exp_string e2 = "hello"; // char* to std::string
156 EXPECT_TRUE(e.has_value());
157 EXPECT_EQ(3, e.value());
158
159 EXPECT_TRUE(e2.has_value());
160 EXPECT_EQ("hello", e2.value());
161 }
162
TEST(Expected,testConstructibleFromUnexpected)163 TEST(Expected, testConstructibleFromUnexpected) {
164 exp_int::unexpected_type unexp = unexpected(10);
165 exp_int e = unexp;
166
167 exp_double::unexpected_type unexp2 = unexpected(10.5);
168 exp_double e2 = unexp2;
169
170 exp_string::unexpected_type unexp3 = unexpected(std::string("error"));
171 exp_string e3 = unexp3;
172
173 exp_void::unexpected_type unexp4 = unexpected(10);
174 exp_void e4 = unexp4;
175
176 EXPECT_FALSE(e.has_value());
177 EXPECT_FALSE(e2.has_value());
178 EXPECT_FALSE(e3.has_value());
179 EXPECT_FALSE(e4.has_value());
180 EXPECT_EQ(10, e.error());
181 EXPECT_EQ(10.5, e2.error());
182 EXPECT_EQ("error", e3.error());
183 EXPECT_EQ(10, e4.error());
184 }
185
TEST(Expected,testMoveConstructibleFromUnexpected)186 TEST(Expected, testMoveConstructibleFromUnexpected) {
187 exp_int e = unexpected(10);
188 exp_double e2 = unexpected(10.5);
189 exp_string e3 = unexpected(std::string("error"));
190 exp_void e4 = unexpected(10);
191
192 EXPECT_FALSE(e.has_value());
193 EXPECT_FALSE(e2.has_value());
194 EXPECT_FALSE(e3.has_value());
195 EXPECT_FALSE(e4.has_value());
196 EXPECT_EQ(10, e.error());
197 EXPECT_EQ(10.5, e2.error());
198 EXPECT_EQ("error", e3.error());
199 EXPECT_EQ(10, e4.error());
200 }
201
TEST(Expected,testConstructibleByForwarding)202 TEST(Expected, testConstructibleByForwarding) {
203 exp_string e(std::in_place, 5, 'a');
204 EXPECT_TRUE(e.has_value());
205 EXPECT_EQ("aaaaa", e.value());
206
207 exp_string e2({'a', 'b', 'c'});
208 EXPECT_TRUE(e2.has_value());
209 EXPECT_EQ("abc", e2.value());
210
211 exp_pair e3({"hello", 30});
212 EXPECT_TRUE(e3.has_value());
213 EXPECT_EQ("hello",e3->first);
214 EXPECT_EQ(30,e3->second);
215
216 exp_void e4({});
217 EXPECT_TRUE(e4.has_value());
218 }
219
TEST(Expected,testDestructible)220 TEST(Expected, testDestructible) {
221 bool destroyed = false;
222 struct T {
223 bool* flag_;
224 T(bool* flag) : flag_(flag) {}
225 ~T() { *flag_ = true; }
226 };
227 {
228 expected<T, int> exp = T(&destroyed);
229 }
230 EXPECT_TRUE(destroyed);
231 }
232
TEST(Expected,testAssignable)233 TEST(Expected, testAssignable) {
234 exp_int e = 10;
235 exp_int e2 = 20;
236 e = e2;
237
238 EXPECT_EQ(20, e.value());
239 EXPECT_EQ(20, e2.value());
240
241 exp_int e3 = 10;
242 exp_int e4 = 20;
243 e3 = std::move(e4);
244
245 EXPECT_EQ(20, e3.value());
246 EXPECT_EQ(20, e4.value());
247
248 exp_void e5 = unexpected(10);
249 ASSERT_FALSE(e5.has_value());
250 exp_void e6;
251 e5 = e6;
252
253 EXPECT_TRUE(e5.has_value());
254 EXPECT_TRUE(e6.has_value());
255 }
256
TEST(Expected,testAssignableFromValue)257 TEST(Expected, testAssignableFromValue) {
258 exp_int e = 10;
259 e = 20;
260 EXPECT_EQ(20, e.value());
261
262 exp_double e2 = 3.5;
263 e2 = 10.5;
264 EXPECT_EQ(10.5, e2.value());
265
266 exp_string e3 = "hello";
267 e3 = "world";
268 EXPECT_EQ("world", e3.value());
269
270 exp_void e4 = unexpected(10);
271 ASSERT_FALSE(e4.has_value());
272 e4 = {};
273 EXPECT_TRUE(e4.has_value());
274 }
275
TEST(Expected,testAssignableFromUnexpected)276 TEST(Expected, testAssignableFromUnexpected) {
277 exp_int e = 10;
278 e = unexpected(30);
279 EXPECT_FALSE(e.has_value());
280 EXPECT_EQ(30, e.error());
281
282 exp_double e2 = 3.5;
283 e2 = unexpected(10.5);
284 EXPECT_FALSE(e2.has_value());
285 EXPECT_EQ(10.5, e2.error());
286
287 exp_string e3 = "hello";
288 e3 = unexpected("world");
289 EXPECT_FALSE(e3.has_value());
290 EXPECT_EQ("world", e3.error());
291
292 exp_void e4 = {};
293 e4 = unexpected(10);
294 EXPECT_FALSE(e4.has_value());
295 EXPECT_EQ(10, e4.error());
296 }
297
TEST(Expected,testAssignableFromMovedValue)298 TEST(Expected, testAssignableFromMovedValue) {
299 std::string world = "world";
300 exp_string e = "hello";
301 e = std::move(world);
302
303 EXPECT_TRUE(e.has_value());
304 EXPECT_EQ("world", e.value());
305 EXPECT_EQ("", world);
306 }
307
TEST(Expected,testAssignableFromMovedUnexpected)308 TEST(Expected, testAssignableFromMovedUnexpected) {
309 std::string world = "world";
310 exp_string e = "hello";
311 e = unexpected(std::move(world));
312
313 EXPECT_FALSE(e.has_value());
314 EXPECT_EQ("world", e.error());
315 EXPECT_EQ("", world);
316 }
317
TEST(Expected,testEmplace)318 TEST(Expected, testEmplace) {
319 struct T {
320 int a;
321 double b;
322 T() {}
323 T(int a, double b) noexcept : a(a), b(b) {}
324 };
325 expected<T, int> exp;
326 T& t = exp.emplace(3, 10.5);
327
328 EXPECT_TRUE(exp.has_value());
329 EXPECT_EQ(3, t.a);
330 EXPECT_EQ(10.5, t.b);
331 EXPECT_EQ(3, exp.value().a);
332 EXPECT_EQ(10.5, exp.value().b);
333
334 exp_void e = unexpected(10);
335 ASSERT_FALSE(e.has_value());
336 e.emplace();
337 EXPECT_TRUE(e.has_value());
338 }
339
340 // For the swap tests, call swap using an unqualified identifier, which should
341 // find the namespace-scope android::base::swap() function using
342 // argument-dependent lookup. The usual idiom for swapping an arbitrary C++ type
343 // is `using std::swap; swap(...);`.
TEST(Expected,testSwapExpectedExpected)344 TEST(Expected, testSwapExpectedExpected) {
345 exp_int e = 10;
346 exp_int e2 = 20;
347 swap(e, e2);
348
349 EXPECT_TRUE(e.has_value());
350 EXPECT_TRUE(e2.has_value());
351 EXPECT_EQ(20, e.value());
352 EXPECT_EQ(10, e2.value());
353
354 exp_void e3;
355 exp_void e4;
356 swap(e3, e4);
357
358 EXPECT_TRUE(e3.has_value());
359 EXPECT_TRUE(e4.has_value());
360 }
361
TEST(Expected,testSwapUnexpectedUnexpected)362 TEST(Expected, testSwapUnexpectedUnexpected) {
363 exp_int e = unexpected(10);
364 exp_int e2 = unexpected(20);
365 swap(e, e2);
366 EXPECT_FALSE(e.has_value());
367 EXPECT_FALSE(e2.has_value());
368 EXPECT_EQ(20, e.error());
369 EXPECT_EQ(10, e2.error());
370
371 exp_void e3 = unexpected(10);
372 exp_void e4 = unexpected(20);
373 swap(e3, e4);
374 EXPECT_FALSE(e3.has_value());
375 EXPECT_FALSE(e4.has_value());
376 EXPECT_EQ(20, e3.error());
377 EXPECT_EQ(10, e4.error());
378 }
379
TEST(Expected,testSwapExpectedUnepected)380 TEST(Expected, testSwapExpectedUnepected) {
381 exp_int e = 10;
382 exp_int e2 = unexpected(30);
383 swap(e, e2);
384 EXPECT_FALSE(e.has_value());
385 EXPECT_TRUE(e2.has_value());
386 EXPECT_EQ(30, e.error());
387 EXPECT_EQ(10, e2.value());
388
389 exp_void e3;
390 exp_void e4 = unexpected(10);
391 swap(e3, e4);
392 EXPECT_FALSE(e3.has_value());
393 EXPECT_TRUE(e4.has_value());
394 EXPECT_EQ(10, e3.error());
395 }
396
TEST(Expected,testNonswappable)397 TEST(Expected, testNonswappable) {
398 struct NoSwap {
399 NoSwap(int val) : val(val) {}
400 NoSwap(const NoSwap& other) : val(other.val) {}
401 NoSwap(NoSwap&& other) : val(other.val) {}
402 int val;
403 };
404
405 // NoSwap has no namespace-scope swap function, and because it lacks a
406 // move assignment operator, std::swap is also not defined for it.
407 static_assert(!std::is_move_assignable_v<NoSwap>);
408 static_assert(!std::is_swappable_v<NoSwap>);
409
410 // A non-swappable type may still be used in the expected class.
411 expected<NoSwap, int> e1(NoSwap(3));
412 EXPECT_EQ(3, e1.value().val);
413 expected<int, NoSwap> e2(unexpected(NoSwap(5)));
414 EXPECT_EQ(5, e2.error().val);
415 expected<void, NoSwap> e3(unexpected(NoSwap(7)));
416 EXPECT_EQ(7, e3.error().val);
417
418 static_assert(!std::is_move_assignable_v<decltype(e1)>);
419 static_assert(!std::is_move_assignable_v<decltype(e2)>);
420 static_assert(!std::is_move_assignable_v<decltype(e3)>);
421 static_assert(!std::is_swappable_v<decltype(e1)>);
422 static_assert(!std::is_swappable_v<decltype(e2)>);
423 static_assert(!std::is_swappable_v<decltype(e3)>);
424 }
425
TEST(Expected,testDereference)426 TEST(Expected, testDereference) {
427 struct T {
428 int a;
429 double b;
430 T() {}
431 T(int a, double b) : a(a), b(b) {}
432 };
433 expected<T, int> exp = T(3, 10.5);
434
435 EXPECT_EQ(3, exp->a);
436 EXPECT_EQ(10.5, exp->b);
437
438 EXPECT_EQ(3, (*exp).a);
439 EXPECT_EQ(10.5, (*exp).b);
440 }
441
TEST(Expected,testTest)442 TEST(Expected, testTest) {
443 exp_int e = 10;
444 EXPECT_TRUE(e.ok());
445 EXPECT_TRUE(e.has_value());
446
447 exp_int e2 = unexpected(10);
448 EXPECT_FALSE(e2.ok());
449 EXPECT_FALSE(e2.has_value());
450 }
451
TEST(Expected,testGetValue)452 TEST(Expected, testGetValue) {
453 exp_int e = 10;
454 EXPECT_EQ(10, e.value());
455 EXPECT_EQ(10, e.value_or(20));
456
457 exp_int e2 = unexpected(10);
458 EXPECT_EQ(10, e2.error());
459 EXPECT_EQ(20, e2.value_or(20));
460 }
461
TEST(Expected,testSameValues)462 TEST(Expected, testSameValues) {
463 exp_int e = 10;
464 exp_int e2 = 10;
465 EXPECT_TRUE(e == e2);
466 EXPECT_TRUE(e2 == e);
467 EXPECT_FALSE(e != e2);
468 EXPECT_FALSE(e2 != e);
469
470 exp_void e3;
471 exp_void e4;
472 EXPECT_TRUE(e3 == e4);
473 EXPECT_TRUE(e4 == e3);
474 EXPECT_FALSE(e3 != e4);
475 EXPECT_FALSE(e4 != e3);
476 }
477
TEST(Expected,testDifferentValues)478 TEST(Expected, testDifferentValues) {
479 exp_int e = 10;
480 exp_int e2 = 20;
481 EXPECT_FALSE(e == e2);
482 EXPECT_FALSE(e2 == e);
483 EXPECT_TRUE(e != e2);
484 EXPECT_TRUE(e2 != e);
485 }
486
TEST(Expected,testValueWithError)487 TEST(Expected, testValueWithError) {
488 exp_int e = 10;
489 exp_int e2 = unexpected(10);
490 EXPECT_FALSE(e == e2);
491 EXPECT_FALSE(e2 == e);
492 EXPECT_TRUE(e != e2);
493 EXPECT_TRUE(e2 != e);
494
495 exp_void e3;
496 exp_void e4 = unexpected(10);
497 EXPECT_FALSE(e3 == e4);
498 EXPECT_FALSE(e4 == e3);
499 EXPECT_TRUE(e3 != e4);
500 EXPECT_TRUE(e4 != e3);
501 }
502
TEST(Expected,testSameErrors)503 TEST(Expected, testSameErrors) {
504 exp_int e = unexpected(10);
505 exp_int e2 = unexpected(10);
506 EXPECT_TRUE(e == e2);
507 EXPECT_TRUE(e2 == e);
508 EXPECT_FALSE(e != e2);
509 EXPECT_FALSE(e2 != e);
510
511 exp_void e3 = unexpected(10);
512 exp_void e4 = unexpected(10);
513 EXPECT_TRUE(e3 == e4);
514 EXPECT_TRUE(e4 == e3);
515 EXPECT_FALSE(e3 != e4);
516 EXPECT_FALSE(e4 != e3);
517 }
518
TEST(Expected,testDifferentErrors)519 TEST(Expected, testDifferentErrors) {
520 exp_int e = unexpected(10);
521 exp_int e2 = unexpected(20);
522 EXPECT_FALSE(e == e2);
523 EXPECT_FALSE(e2 == e);
524 EXPECT_TRUE(e != e2);
525 EXPECT_TRUE(e2 != e);
526
527 exp_void e3 = unexpected(10);
528 exp_void e4 = unexpected(20);
529 EXPECT_FALSE(e3 == e4);
530 EXPECT_FALSE(e4 == e3);
531 EXPECT_TRUE(e3 != e4);
532 EXPECT_TRUE(e4 != e3);
533 }
534
TEST(Expected,testCompareWithSameError)535 TEST(Expected, testCompareWithSameError) {
536 exp_int e = unexpected(10);
537 exp_int::unexpected_type error{10};
538 EXPECT_TRUE(e == error);
539 EXPECT_TRUE(error == e);
540 EXPECT_FALSE(e != error);
541 EXPECT_FALSE(error != e);
542
543 exp_void e2 = unexpected(10);
544 exp_void::unexpected_type error2{10};
545 EXPECT_TRUE(e2 == error2);
546 EXPECT_TRUE(error2 == e2);
547 EXPECT_FALSE(e2 != error2);
548 EXPECT_FALSE(error2 != e2);
549 }
550
TEST(Expected,testCompareWithDifferentError)551 TEST(Expected, testCompareWithDifferentError) {
552 exp_int e = unexpected(10);
553 exp_int::unexpected_type error{20};
554 EXPECT_FALSE(e == error);
555 EXPECT_FALSE(error == e);
556 EXPECT_TRUE(e != error);
557 EXPECT_TRUE(error != e);
558
559 exp_void e2 = unexpected(10);
560 exp_void::unexpected_type error2{20};
561 EXPECT_FALSE(e2 == error2);
562 EXPECT_FALSE(error2 == e2);
563 EXPECT_TRUE(e2 != error2);
564 EXPECT_TRUE(error2 != e2);
565 }
566
TEST(Expected,testCompareDifferentType)567 TEST(Expected, testCompareDifferentType) {
568 expected<int,int> e = 10;
569 expected<int32_t, int> e2 = 10;
570 EXPECT_TRUE(e == e2);
571 e2 = 20;
572 EXPECT_FALSE(e == e2);
573
574 expected<std::string_view,int> e3 = "hello";
575 expected<std::string,int> e4 = "hello";
576 EXPECT_TRUE(e3 == e4);
577 e4 = "world";
578 EXPECT_FALSE(e3 == e4);
579
580 expected<void,int> e5;
581 expected<int,int> e6 = 10;
582 EXPECT_FALSE(e5 == e6);
583 EXPECT_FALSE(e6 == e5);
584 }
585
TEST(Expected,testDivideExample)586 TEST(Expected, testDivideExample) {
587 struct QR {
588 int quotient;
589 int remainder;
590 QR(int q, int r) noexcept : quotient(q), remainder(r) {}
591 bool operator==(const QR& rhs) const {
592 return quotient == rhs.quotient && remainder == rhs.remainder;
593 }
594 bool operator!=(const QR& rhs) const {
595 return quotient != rhs.quotient || remainder == rhs.remainder;
596 }
597 };
598
599 auto divide = [](int x, int y) -> expected<QR,E> {
600 if (y == 0) {
601 return unexpected(E("divide by zero", -1));
602 } else {
603 return QR(x / y, x % y);
604 }
605 };
606
607 EXPECT_FALSE(divide(10, 0).ok());
608 EXPECT_EQ("divide by zero", divide(10, 0).error().message);
609 EXPECT_EQ(-1, divide(10, 0).error().cause);
610
611 EXPECT_TRUE(divide(10, 3).ok());
612 EXPECT_EQ(QR(3, 1), *divide(10, 3));
613 }
614
TEST(Expected,testPair)615 TEST(Expected, testPair) {
616 auto test = [](bool yes) -> exp_pair {
617 if (yes) {
618 return exp_pair({"yes", 42});
619 } else {
620 return unexpected(42);
621 }
622 };
623
624 auto r = test(true);
625 EXPECT_TRUE(r.ok());
626 EXPECT_EQ("yes", r->first);
627 }
628
TEST(Expected,testVoid)629 TEST(Expected, testVoid) {
630 auto test = [](bool ok) -> exp_void {
631 if (ok) {
632 return {};
633 } else {
634 return unexpected(10);
635 }
636 };
637
638 auto r = test(true);
639 EXPECT_TRUE(r.ok());
640 r = test(false);
641 EXPECT_FALSE(r.ok());
642 EXPECT_EQ(10, r.error());
643 }
644
645 // copied from result_test.cpp
646 struct ConstructorTracker {
647 static size_t constructor_called;
648 static size_t copy_constructor_called;
649 static size_t move_constructor_called;
650 static size_t copy_assignment_called;
651 static size_t move_assignment_called;
652
653 template <typename T,
654 typename std::enable_if_t<std::is_convertible_v<T, std::string>>* = nullptr>
ConstructorTrackerConstructorTracker655 ConstructorTracker(T&& string) : string(string) {
656 ++constructor_called;
657 }
ConstructorTrackerConstructorTracker658 ConstructorTracker(const ConstructorTracker& ct) {
659 ++copy_constructor_called;
660 string = ct.string;
661 }
ConstructorTrackerConstructorTracker662 ConstructorTracker(ConstructorTracker&& ct) noexcept {
663 ++move_constructor_called;
664 string = std::move(ct.string);
665 }
operator =ConstructorTracker666 ConstructorTracker& operator=(const ConstructorTracker& ct) {
667 ++copy_assignment_called;
668 string = ct.string;
669 return *this;
670 }
operator =ConstructorTracker671 ConstructorTracker& operator=(ConstructorTracker&& ct) noexcept {
672 ++move_assignment_called;
673 string = std::move(ct.string);
674 return *this;
675 }
ResetConstructorTracker676 static void Reset() {
677 constructor_called = 0;
678 copy_constructor_called = 0;
679 move_constructor_called = 0;
680 copy_assignment_called = 0;
681 move_assignment_called = 0;
682 }
683 std::string string;
684 };
685
686 size_t ConstructorTracker::constructor_called = 0;
687 size_t ConstructorTracker::copy_constructor_called = 0;
688 size_t ConstructorTracker::move_constructor_called = 0;
689 size_t ConstructorTracker::copy_assignment_called = 0;
690 size_t ConstructorTracker::move_assignment_called = 0;
691
692 typedef expected<ConstructorTracker, int> exp_track;
693
TEST(Expected,testNumberOfCopies)694 TEST(Expected, testNumberOfCopies) {
695 // ordinary constructor
696 ConstructorTracker::Reset();
697 exp_track e("hello");
698 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
699 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
700 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
701 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
702 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
703
704 // copy constructor
705 ConstructorTracker::Reset();
706 exp_track e2 = e;
707 EXPECT_EQ(0U, ConstructorTracker::constructor_called);
708 EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
709 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
710 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
711 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
712
713 // move constructor
714 ConstructorTracker::Reset();
715 exp_track e3 = std::move(e);
716 EXPECT_EQ(0U, ConstructorTracker::constructor_called);
717 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
718 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
719 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
720 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
721
722 // construct from lvalue
723 ConstructorTracker::Reset();
724 ConstructorTracker ct = "hello";
725 exp_track e4(ct);
726 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
727 EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
728 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
729 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
730 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
731
732 // construct from rvalue
733 ConstructorTracker::Reset();
734 ConstructorTracker ct2 = "hello";
735 exp_track e5(std::move(ct2));
736 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
737 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
738 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
739 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
740 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
741
742 // copy assignment
743 ConstructorTracker::Reset();
744 exp_track e6 = "hello";
745 exp_track e7 = "world";
746 e7 = e6;
747 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
748 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
749 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
750 EXPECT_EQ(1U, ConstructorTracker::copy_assignment_called);
751 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
752
753 // move assignment
754 ConstructorTracker::Reset();
755 exp_track e8 = "hello";
756 exp_track e9 = "world";
757 e9 = std::move(e8);
758 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
759 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
760 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
761 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
762 EXPECT_EQ(1U, ConstructorTracker::move_assignment_called);
763
764 // swap
765 ConstructorTracker::Reset();
766 exp_track e10 = "hello";
767 exp_track e11 = "world";
768 swap(e10, e11);
769 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
770 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
771 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
772 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
773 EXPECT_EQ(2U, ConstructorTracker::move_assignment_called);
774 }
775
TEST(Expected,testCopiesWithDifferentValueOrErrorTypes)776 TEST(Expected, testCopiesWithDifferentValueOrErrorTypes) {
777 ConstructorTracker::Reset();
778 // copy success value
779 expected<std::string, int> e1 = "hello";
780 expected<ConstructorTracker, int> e2 = e1;
781 // move success value
782 expected<std::string, int> e3 = "hello";
783 expected<ConstructorTracker, int> e4 = std::move(e3);
784 // copy error value
785 expected<int, std::string> e5 = unexpected("hello");
786 expected<int, ConstructorTracker> e6 = e5;
787 // move error value
788 expected<int, std::string> e7 = unexpected("hello");
789 expected<int, ConstructorTracker> e8 = std::move(e7);
790
791 EXPECT_EQ(4U, ConstructorTracker::constructor_called);
792 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
793 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
794 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
795 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
796 }
797
798 // Constructing an expected type from a different expected type where either the
799 // value or the error type is ConstructorTracker in both expected types.
TEST(Expected,testCopyOrMoveTrackerAcrossExpectedConversion)800 TEST(Expected, testCopyOrMoveTrackerAcrossExpectedConversion) {
801 struct IntObj {
802 IntObj(int) {}
803 };
804
805 // same value type, copy
806 ConstructorTracker::Reset();
807 expected<ConstructorTracker, int> e1 = std::string("hello");
808 expected<ConstructorTracker, IntObj> e2 = e1;
809 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
810 EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
811 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
812 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
813 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
814
815 // same value type, move
816 ConstructorTracker::Reset();
817 expected<ConstructorTracker, int> e3 = std::string("hello");
818 expected<ConstructorTracker, IntObj> e4 = std::move(e3);
819 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
820 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
821 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
822 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
823 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
824
825 // same error type, copy
826 ConstructorTracker::Reset();
827 expected<int, ConstructorTracker> e5 = unexpected(std::string("hello"));
828 expected<IntObj, ConstructorTracker> e6 = e5;
829 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
830 EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
831 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
832 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
833 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
834
835 // same error type, move
836 ConstructorTracker::Reset();
837 expected<int, ConstructorTracker> e7 = unexpected(std::string("hello"));
838 expected<IntObj, ConstructorTracker> e8 = std::move(e7);
839 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
840 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
841 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
842 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
843 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
844 }
845
TEST(Expected,testNoCopyOnReturn)846 TEST(Expected, testNoCopyOnReturn) {
847 auto test = [](const std::string& in) -> exp_track {
848 if (in.empty()) {
849 return "literal string";
850 }
851 if (in == "test2") {
852 return ConstructorTracker(in + in + "2");
853 }
854 ConstructorTracker result(in + " " + in);
855 return result;
856 };
857
858 ConstructorTracker::Reset();
859 auto result1 = test("");
860 ASSERT_TRUE(result1.ok());
861 EXPECT_EQ("literal string", result1->string);
862 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
863 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
864 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
865 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
866 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
867
868 ConstructorTracker::Reset();
869 auto result2 = test("test2");
870 ASSERT_TRUE(result2.ok());
871 EXPECT_EQ("test2test22", result2->string);
872 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
873 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
874 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
875 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
876 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
877
878 ConstructorTracker::Reset();
879 auto result3 = test("test3");
880 ASSERT_TRUE(result3.ok());
881 EXPECT_EQ("test3 test3", result3->string);
882 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
883 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
884 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
885 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
886 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
887 }
888
TEST(Expected,testNested)889 TEST(Expected, testNested) {
890 expected<exp_string, std::string> e = "hello";
891
892 EXPECT_TRUE(e.ok());
893 EXPECT_TRUE(e.has_value());
894 EXPECT_TRUE(e.value().has_value());
895 EXPECT_TRUE(e->ok());
896 EXPECT_EQ("hello", e.value().value());
897
898 expected<exp_string, std::string> e2 = unexpected("world");
899 EXPECT_FALSE(e2.has_value());
900 EXPECT_FALSE(e2.ok());
901 EXPECT_EQ("world", e2.error());
902
903 expected<exp_string, std::string> e3 = exp_string(unexpected("world"));
904 EXPECT_TRUE(e3.has_value());
905 EXPECT_FALSE(e3.value().has_value());
906 EXPECT_TRUE(e3.ok());
907 EXPECT_FALSE(e3->ok());
908 EXPECT_EQ("world", e3.value().error());
909 }
910
equals(const char * a,const char * b)911 constexpr bool equals(const char* a, const char* b) {
912 return (a == nullptr && b == nullptr) ||
913 (a != nullptr && b != nullptr && *a == *b &&
914 (*a == '\0' || equals(a + 1, b + 1)));
915 }
916
TEST(Expected,testConstexpr)917 TEST(Expected, testConstexpr) {
918 // Compilation error will occur if these expressions can't be
919 // evaluated at compile time
920 constexpr exp_int e(3);
921 constexpr exp_int::unexpected_type err(3);
922 constexpr int i = 4;
923
924 // default constructor
925 static_assert(exp_int().value() == 0);
926 // copy constructor
927 static_assert(exp_int(e).value() == 3);
928 // move constructor
929 static_assert(exp_int(exp_int(4)).value() == 4);
930 // copy construct from value
931 static_assert(exp_int(i).value() == 4);
932 // copy construct from unexpected
933 static_assert(exp_int(err).error() == 3);
934 // move construct from unexpected
935 static_assert(exp_int(unexpected(3)).error() == 3);
936 // observers
937 static_assert(*exp_int(3) == 3);
938 static_assert(exp_int(3).has_value() == true);
939 static_assert(static_cast<bool>(exp_int(3)));
940 static_assert(!static_cast<bool>(exp_int(err)));
941 static_assert(exp_int(3).value_or(4) == 3);
942
943 typedef expected<const char*, int> exp_s;
944 constexpr exp_s s("hello");
945 constexpr const char* c = "hello";
946 static_assert(equals(exp_s().value(), nullptr));
947 static_assert(equals(exp_s(s).value(), "hello"));
948 static_assert(equals(exp_s(exp_s("hello")).value(), "hello"));
949 static_assert(equals(exp_s("hello").value(), "hello"));
950 static_assert(equals(exp_s(c).value(), "hello"));
951 }
952
TEST(Expected,testWithNonConstructible)953 TEST(Expected, testWithNonConstructible) {
954 struct AssertNotConstructed {
955 AssertNotConstructed() = delete;
956 };
957
958 expected<int, AssertNotConstructed> v(42);
959 EXPECT_TRUE(v.has_value());
960 EXPECT_EQ(42, v.value());
961
962 expected<AssertNotConstructed, int> e(unexpected(42));
963 EXPECT_FALSE(e.has_value());
964 EXPECT_EQ(42, e.error());
965 }
966
TEST(Expected,testWithMoveOnlyType)967 TEST(Expected, testWithMoveOnlyType) {
968 typedef expected<std::unique_ptr<int>,std::unique_ptr<int>> exp_ptr;
969 exp_ptr e(std::make_unique<int>(3));
970 exp_ptr e2(unexpected(std::make_unique<int>(4)));
971
972 EXPECT_TRUE(e.has_value());
973 EXPECT_FALSE(e2.has_value());
974 EXPECT_EQ(3, *(e.value()));
975 EXPECT_EQ(4, *(e2.error()));
976
977 e2 = std::move(e);
978 EXPECT_TRUE(e.has_value());
979 EXPECT_TRUE(e2.has_value());
980 EXPECT_EQ(3, *(e2.value()));
981 }
982
983 // Verify that operator bool doesn't cause surprising behavior when converting
984 // between expected types. See wg21.link/LWG3836.
TEST(Expected,testExpectedConversionWithBoolType)985 TEST(Expected, testExpectedConversionWithBoolType) {
986 expected<bool, int> e1{false};
987 expected<bool, long> e2{e1};
988 EXPECT_TRUE(e1.has_value());
989 EXPECT_TRUE(e2.has_value());
990 EXPECT_FALSE(e1.value());
991 EXPECT_FALSE(e2.value());
992
993 expected<bool, int> e3{unexpected{17}};
994 expected<bool, long> e4{e3};
995 EXPECT_FALSE(e3.has_value());
996 EXPECT_FALSE(e4.has_value());
997 EXPECT_EQ(17, e3.error());
998 EXPECT_EQ(17, e4.error());
999 }
1000
TEST(Expected,testConversionToClassWithExplicitCtor)1001 TEST(Expected, testConversionToClassWithExplicitCtor) {
1002 struct IntObj {
1003 explicit IntObj(int val) : val(val) {}
1004 int val;
1005 };
1006
1007 expected<int, int> e1(3);
1008 expected<IntObj, int> e2(e1);
1009 EXPECT_TRUE(e2.has_value());
1010 EXPECT_EQ(3, e2.value().val);
1011
1012 expected<int, int> e3(unexpected(4));
1013 expected<int, IntObj> e4(e3);
1014 EXPECT_FALSE(e4.has_value());
1015 EXPECT_EQ(4, e4.error().val);
1016 }
1017
TEST(Expected,testNoexcept)1018 TEST(Expected, testNoexcept) {
1019 struct Foo {
1020 Foo(int) noexcept {}
1021 };
1022 struct Bar {
1023 Bar(Foo) noexcept {}
1024 };
1025 expected<Foo, Foo> e1{3};
1026 expected<Foo, Foo> e2{4};
1027 expected<Bar, Bar> e3{e1};
1028 Foo foo{5};
1029 static_assert(noexcept(expected<Foo, Foo>(e1)));
1030 static_assert(noexcept(expected<Foo, Foo>(std::move(e1))));
1031 static_assert(noexcept(expected<Foo, Foo>(foo)));
1032 static_assert(noexcept(expected<Foo, Foo>(std::move(foo))));
1033 static_assert(noexcept(expected<Foo, Foo>(unexpected(Foo(5)))));
1034 static_assert(noexcept(expected<Bar, Bar>(e1)));
1035 static_assert(noexcept(expected<Bar, Bar>(std::move(e1))));
1036 static_assert(noexcept(expected<Bar, Bar>(foo)));
1037 static_assert(noexcept(expected<Bar, Bar>(std::move(foo))));
1038 static_assert(noexcept(expected<Bar, Bar>(unexpected(Bar(foo)))));
1039 static_assert(noexcept(e2 = e1));
1040 static_assert(noexcept(e2 = std::move(e1)));
1041 static_assert(noexcept(e3 = e1));
1042 static_assert(noexcept(e3 = std::move(e1)));
1043 static_assert(noexcept(e1 = Foo(5)));
1044 static_assert(noexcept(e3 = Foo(5)));
1045
1046 // std::string's move constructor is noexcept, but copying a string can throw
1047 // bad_alloc.
1048 expected<Foo, std::string> e11{11};
1049 expected<Foo, std::string> e12{12};
1050 expected<Bar, std::string> e13{e11};
1051 std::string err = "hello";
1052 static_assert(!noexcept(expected<Foo, std::string>(e11)));
1053 static_assert(noexcept(expected<Foo, std::string>(std::move(e11))));
1054 static_assert(noexcept(expected<Foo, std::string>(foo)));
1055 static_assert(noexcept(expected<Foo, std::string>(std::move(foo))));
1056 static_assert(noexcept(expected<Foo, std::string>(unexpected(std::move(err)))));
1057 static_assert(!noexcept(expected<Bar, std::string>(e11)));
1058 static_assert(noexcept(expected<Bar, std::string>(std::move(e11))));
1059 static_assert(noexcept(expected<Bar, std::string>(foo)));
1060 static_assert(noexcept(expected<Bar, std::string>(std::move(foo))));
1061 static_assert(!noexcept(e12 = e11));
1062 static_assert(noexcept(e12 = std::move(e11)));
1063 static_assert(!noexcept(e13 = e11));
1064 static_assert(noexcept(e13 = std::move(e11)));
1065 }
1066