blob: 490ced45647c3d402e9e0ccc59e126715b510af9 [file] [log] [blame]
Jiyong Park7d89fb12019-05-15 19:17:48 +09001/*
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
25using android::base::expected;
26using android::base::unexpected;
27
28typedef expected<int, int> exp_int;
29typedef expected<double, double> exp_double;
30typedef expected<std::string, std::string> exp_string;
31typedef expected<std::pair<std::string, int>, int> exp_pair;
32
33struct T {
34 int a;
35 int b;
36 T() = default;
37 T(int a, int b) noexcept : a(a), b(b) {}
38};
39bool operator==(const T& x, const T& y) {
40 return x.a == y.a && x.b == y.b;
41}
42bool operator!=(const T& x, const T& y) {
43 return x.a != y.a || x.b != y.b;
44}
45
46struct E {
47 std::string message;
48 int cause;
49 E(const std::string& message, int cause) : message(message), cause(cause) {}
50};
51
52typedef expected<T,E> exp_complex;
53
54TEST(Expected, testDefaultConstructible) {
55 exp_int e;
56 EXPECT_TRUE(e.has_value());
57 EXPECT_EQ(0, e.value());
58
59 exp_complex e2;
60 EXPECT_TRUE(e2.has_value());
61 EXPECT_EQ(T(0,0), e2.value());
62}
63
64TEST(Expected, testCopyConstructible) {
65 exp_int e;
66 exp_int e2 = e;
67
68 EXPECT_TRUE(e.has_value());
69 EXPECT_TRUE(e2.has_value());
70 EXPECT_EQ(0, e.value());
71 EXPECT_EQ(0, e2.value());
72}
73
74TEST(Expected, testMoveConstructible) {
75 exp_int e;
76 exp_int e2 = std::move(e);
77
78 EXPECT_TRUE(e.has_value());
79 EXPECT_TRUE(e2.has_value());
80 EXPECT_EQ(0, e.value());
81 EXPECT_EQ(0, e2.value());
82
83 exp_string e3(std::string("hello"));
84 exp_string e4 = std::move(e3);
85
86 EXPECT_TRUE(e3.has_value());
87 EXPECT_TRUE(e4.has_value());
88 EXPECT_EQ("", e3.value()); // e3 is moved
89 EXPECT_EQ("hello", e4.value());
90}
91
92TEST(Expected, testCopyConstructibleFromConvertibleType) {
93 exp_double e = 3.3f;
94 exp_int e2 = e;
95
96 EXPECT_TRUE(e.has_value());
97 EXPECT_TRUE(e2.has_value());
98 EXPECT_EQ(3.3f, e.value());
99 EXPECT_EQ(3, e2.value());
100}
101
102TEST(Expected, testMoveConstructibleFromConvertibleType) {
103 exp_double e = 3.3f;
104 exp_int e2 = std::move(e);
105
106 EXPECT_TRUE(e.has_value());
107 EXPECT_TRUE(e2.has_value());
108 EXPECT_EQ(3.3f, e.value());
109 EXPECT_EQ(3, e2.value());
110}
111
112TEST(Expected, testConstructibleFromValue) {
113 exp_int e = 3;
114 exp_double e2 = 5.5f;
115 exp_string e3 = std::string("hello");
116 exp_complex e4 = T(10, 20);
117
118 EXPECT_TRUE(e.has_value());
119 EXPECT_TRUE(e2.has_value());
120 EXPECT_TRUE(e3.has_value());
121 EXPECT_TRUE(e4.has_value());
122 EXPECT_EQ(3, e.value());
123 EXPECT_EQ(5.5f, e2.value());
124 EXPECT_EQ("hello", e3.value());
125 EXPECT_EQ(T(10,20), e4.value());
126}
127
128TEST(Expected, testConstructibleFromMovedValue) {
129 std::string hello = "hello";
130 exp_string e = std::move(hello);
131
132 EXPECT_TRUE(e.has_value());
133 EXPECT_EQ("hello", e.value());
134 EXPECT_EQ("", hello);
135}
136
137TEST(Expected, testConstructibleFromConvertibleValue) {
138 exp_int e = 3.3f; // double to int
139 exp_string e2 = "hello"; // char* to std::string
140 EXPECT_TRUE(e.has_value());
141 EXPECT_EQ(3, e.value());
142
143 EXPECT_TRUE(e2.has_value());
144 EXPECT_EQ("hello", e2.value());
145}
146
147TEST(Expected, testConstructibleFromUnexpected) {
148 exp_int::unexpected_type unexp = unexpected(10);
149 exp_int e = unexp;
150
151 exp_double::unexpected_type unexp2 = unexpected(10.5f);
152 exp_double e2 = unexp2;
153
154 exp_string::unexpected_type unexp3 = unexpected(std::string("error"));
155 exp_string e3 = unexp3;
156
157 EXPECT_FALSE(e.has_value());
158 EXPECT_FALSE(e2.has_value());
159 EXPECT_FALSE(e3.has_value());
160 EXPECT_EQ(10, e.error());
161 EXPECT_EQ(10.5f, e2.error());
162 EXPECT_EQ("error", e3.error());
163}
164
165TEST(Expected, testMoveConstructibleFromUnexpected) {
166 exp_int e = unexpected(10);
167 exp_double e2 = unexpected(10.5f);
168 exp_string e3 = unexpected(std::string("error"));
169
170 EXPECT_FALSE(e.has_value());
171 EXPECT_FALSE(e2.has_value());
172 EXPECT_FALSE(e3.has_value());
173 EXPECT_EQ(10, e.error());
174 EXPECT_EQ(10.5f, e2.error());
175 EXPECT_EQ("error", e3.error());
176}
177
178TEST(Expected, testConstructibleByForwarding) {
179 exp_string e(std::in_place, 5, 'a');
180 EXPECT_TRUE(e.has_value());
181 EXPECT_EQ("aaaaa", e.value());
182
183 exp_string e2({'a', 'b', 'c'});
184 EXPECT_TRUE(e2.has_value());
185 EXPECT_EQ("abc", e2.value());
186
187 exp_pair e3({"hello", 30});
188 EXPECT_TRUE(e3.has_value());
189 EXPECT_EQ("hello",e3->first);
190 EXPECT_EQ(30,e3->second);
191}
192
193TEST(Expected, testDestructible) {
194 bool destroyed = false;
195 struct T {
196 bool* flag_;
197 T(bool* flag) : flag_(flag) {}
198 ~T() { *flag_ = true; }
199 };
200 {
201 expected<T, int> exp = T(&destroyed);
202 }
203 EXPECT_TRUE(destroyed);
204}
205
206TEST(Expected, testAssignable) {
207 exp_int e = 10;
208 exp_int e2 = 20;
209 e = e2;
210
211 EXPECT_EQ(20, e.value());
212 EXPECT_EQ(20, e2.value());
213
214 exp_int e3 = 10;
215 exp_int e4 = 20;
216 e3 = std::move(e4);
217
218 EXPECT_EQ(20, e3.value());
219 EXPECT_EQ(20, e4.value());
220}
221
222TEST(Expected, testAssignableFromValue) {
223 exp_int e = 10;
224 e = 20;
225 EXPECT_EQ(20, e.value());
226
227 exp_double e2 = 3.5f;
228 e2 = 10.5f;
229 EXPECT_EQ(10.5f, e2.value());
230
231 exp_string e3 = "hello";
232 e3 = "world";
233 EXPECT_EQ("world", e3.value());
234}
235
236TEST(Expected, testAssignableFromUnexpected) {
237 exp_int e = 10;
238 e = unexpected(30);
239 EXPECT_FALSE(e.has_value());
240 EXPECT_EQ(30, e.error());
241
242 exp_double e2 = 3.5f;
243 e2 = unexpected(10.5f);
244 EXPECT_FALSE(e2.has_value());
245 EXPECT_EQ(10.5f, e2.error());
246
247 exp_string e3 = "hello";
248 e3 = unexpected("world");
249 EXPECT_FALSE(e3.has_value());
250 EXPECT_EQ("world", e3.error());
251}
252
253TEST(Expected, testAssignableFromMovedValue) {
254 std::string world = "world";
255 exp_string e = "hello";
256 e = std::move(world);
257
258 EXPECT_TRUE(e.has_value());
259 EXPECT_EQ("world", e.value());
260 EXPECT_EQ("", world);
261}
262
263TEST(Expected, testAssignableFromMovedUnexpected) {
264 std::string world = "world";
265 exp_string e = "hello";
266 e = unexpected(std::move(world));
267
268 EXPECT_FALSE(e.has_value());
269 EXPECT_EQ("world", e.error());
270 EXPECT_EQ("", world);
271}
272
273TEST(Expected, testEmplace) {
274 struct T {
275 int a;
276 double b;
277 T() {}
278 T(int a, double b) noexcept : a(a), b(b) {}
279 };
280 expected<T, int> exp;
281 T& t = exp.emplace(3, 10.5f);
282
283 EXPECT_TRUE(exp.has_value());
284 EXPECT_EQ(3, t.a);
285 EXPECT_EQ(10.5f, t.b);
286 EXPECT_EQ(3, exp.value().a);
287 EXPECT_EQ(10.5, exp.value().b);
288}
289
290TEST(Expected, testSwapExpectedExpected) {
291 exp_int e = 10;
292 exp_int e2 = 20;
293 e.swap(e2);
294
295 EXPECT_TRUE(e.has_value());
296 EXPECT_TRUE(e2.has_value());
297 EXPECT_EQ(20, e.value());
298 EXPECT_EQ(10, e2.value());
299}
300
301TEST(Expected, testSwapUnexpectedUnexpected) {
302 exp_int e = unexpected(10);
303 exp_int e2 = unexpected(20);
304 e.swap(e2);
305 EXPECT_FALSE(e.has_value());
306 EXPECT_FALSE(e2.has_value());
307 EXPECT_EQ(20, e.error());
308 EXPECT_EQ(10, e2.error());
309}
310
311TEST(Expected, testSwapExpectedUnepected) {
312 exp_int e = 10;
313 exp_int e2 = unexpected(30);
314 e.swap(e2);
315 EXPECT_FALSE(e.has_value());
316 EXPECT_TRUE(e2.has_value());
317 EXPECT_EQ(30, e.error());
318 EXPECT_EQ(10, e2.value());
319}
320
321TEST(Expected, testDereference) {
322 struct T {
323 int a;
324 double b;
325 T() {}
326 T(int a, double b) : a(a), b(b) {}
327 };
328 expected<T, int> exp = T(3, 10.5f);
329
330 EXPECT_EQ(3, exp->a);
331 EXPECT_EQ(10.5f, exp->b);
332
333 EXPECT_EQ(3, (*exp).a);
334 EXPECT_EQ(10.5f, (*exp).b);
335}
336
337TEST(Expected, testTest) {
338 exp_int e = 10;
339 EXPECT_TRUE(e);
340 EXPECT_TRUE(e.has_value());
341
342 exp_int e2 = unexpected(10);
343 EXPECT_FALSE(e2);
344 EXPECT_FALSE(e2.has_value());
345}
346
347TEST(Expected, testGetValue) {
348 exp_int e = 10;
349 EXPECT_EQ(10, e.value());
350 EXPECT_EQ(10, e.value_or(20));
351
352 exp_int e2 = unexpected(10);
353 EXPECT_EQ(10, e2.error());
354 EXPECT_EQ(20, e2.value_or(20));
355}
356
357TEST(Expected, testSameValues) {
358 exp_int e = 10;
359 exp_int e2 = 10;
360 EXPECT_TRUE(e == e2);
361 EXPECT_TRUE(e2 == e);
362 EXPECT_FALSE(e != e2);
363 EXPECT_FALSE(e2 != e);
364}
365
366TEST(Expected, testDifferentValues) {
367 exp_int e = 10;
368 exp_int e2 = 20;
369 EXPECT_FALSE(e == e2);
370 EXPECT_FALSE(e2 == e);
371 EXPECT_TRUE(e != e2);
372 EXPECT_TRUE(e2 != e);
373}
374
375TEST(Expected, testValueWithError) {
376 exp_int e = 10;
377 exp_int e2 = unexpected(10);
378 EXPECT_FALSE(e == e2);
379 EXPECT_FALSE(e2 == e);
380 EXPECT_TRUE(e != e2);
381 EXPECT_TRUE(e2 != e);
382}
383
384TEST(Expected, testSameErrors) {
385 exp_int e = unexpected(10);
386 exp_int e2 = unexpected(10);
387 EXPECT_TRUE(e == e2);
388 EXPECT_TRUE(e2 == e);
389 EXPECT_FALSE(e != e2);
390 EXPECT_FALSE(e2 != e);
391}
392
393TEST(Expected, testDifferentErrors) {
394 exp_int e = unexpected(10);
395 exp_int e2 = unexpected(20);
396 EXPECT_FALSE(e == e2);
397 EXPECT_FALSE(e2 == e);
398 EXPECT_TRUE(e != e2);
399 EXPECT_TRUE(e2 != e);
400}
401
402TEST(Expected, testCompareWithSameValue) {
403 exp_int e = 10;
404 int value = 10;
405 EXPECT_TRUE(e == value);
406 EXPECT_TRUE(value == e);
407 EXPECT_FALSE(e != value);
408 EXPECT_FALSE(value != e);
409}
410
411TEST(Expected, testCompareWithDifferentValue) {
412 exp_int e = 10;
413 int value = 20;
414 EXPECT_FALSE(e == value);
415 EXPECT_FALSE(value == e);
416 EXPECT_TRUE(e != value);
417 EXPECT_TRUE(value != e);
418}
419
420TEST(Expected, testCompareWithSameError) {
421 exp_int e = unexpected(10);
422 exp_int::unexpected_type error = 10;
423 EXPECT_TRUE(e == error);
424 EXPECT_TRUE(error == e);
425 EXPECT_FALSE(e != error);
426 EXPECT_FALSE(error != e);
427}
428
429TEST(Expected, testCompareWithDifferentError) {
430 exp_int e = unexpected(10);
431 exp_int::unexpected_type error = 20;
432 EXPECT_FALSE(e == error);
433 EXPECT_FALSE(error == e);
434 EXPECT_TRUE(e != error);
435 EXPECT_TRUE(error != e);
436}
437
438TEST(Expected, testDivideExample) {
439 struct QR {
440 int quotient;
441 int remainder;
442 QR(int q, int r) noexcept : quotient(q), remainder(r) {}
443 bool operator==(const QR& rhs) const {
444 return quotient == rhs.quotient && remainder == rhs.remainder;
445 }
446 bool operator!=(const QR& rhs) const {
447 return quotient != rhs.quotient || remainder == rhs.remainder;
448 }
449 };
450
451 auto divide = [](int x, int y) -> expected<QR,E> {
452 if (y == 0) {
453 return unexpected(E("divide by zero", -1));
454 } else {
455 return QR(x / y, x % y);
456 }
457 };
458
459 EXPECT_FALSE(divide(10, 0));
460 EXPECT_EQ("divide by zero", divide(10, 0).error().message);
461 EXPECT_EQ(-1, divide(10, 0).error().cause);
462
463 EXPECT_TRUE(divide(10, 3));
464 EXPECT_EQ(QR(3, 1), divide(10, 3));
465}
466
467TEST(Expected, testPair) {
468 auto test = [](bool yes) -> exp_pair {
469 if (yes) {
470 return exp_pair({"yes", 42});
471 } else {
472 return unexpected(42);
473 }
474 };
475
476 auto r = test(true);
477 EXPECT_TRUE(r);
478 EXPECT_EQ("yes", r->first);
479}
480
481// copied from result_test.cpp
482struct ConstructorTracker {
483 static size_t constructor_called;
484 static size_t copy_constructor_called;
485 static size_t move_constructor_called;
486 static size_t copy_assignment_called;
487 static size_t move_assignment_called;
488
489 template <typename T,
490 typename std::enable_if_t<std::is_convertible_v<T, std::string>>* = nullptr>
491 ConstructorTracker(T&& string) : string(string) {
492 ++constructor_called;
493 }
494 ConstructorTracker(const ConstructorTracker& ct) {
495 ++copy_constructor_called;
496 string = ct.string;
497 }
498 ConstructorTracker(ConstructorTracker&& ct) noexcept {
499 ++move_constructor_called;
500 string = std::move(ct.string);
501 }
502 ConstructorTracker& operator=(const ConstructorTracker& ct) {
503 ++copy_assignment_called;
504 string = ct.string;
505 return *this;
506 }
507 ConstructorTracker& operator=(ConstructorTracker&& ct) noexcept {
508 ++move_assignment_called;
509 string = std::move(ct.string);
510 return *this;
511 }
512 static void Reset() {
513 constructor_called = 0;
514 copy_constructor_called = 0;
515 move_constructor_called = 0;
516 copy_assignment_called = 0;
517 move_assignment_called = 0;
518 }
519 std::string string;
520};
521
522size_t ConstructorTracker::constructor_called = 0;
523size_t ConstructorTracker::copy_constructor_called = 0;
524size_t ConstructorTracker::move_constructor_called = 0;
525size_t ConstructorTracker::copy_assignment_called = 0;
526size_t ConstructorTracker::move_assignment_called = 0;
527
528typedef expected<ConstructorTracker, int> exp_track;
529
530TEST(Expected, testNumberOfCopies) {
531 // default constructor
532 ConstructorTracker::Reset();
533 exp_track e("hello");
534 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
535 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
536 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
537 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
538 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
539
540 // copy constructor
541 ConstructorTracker::Reset();
542 exp_track e2 = e;
543 EXPECT_EQ(0U, ConstructorTracker::constructor_called);
544 EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
545 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
546 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
547 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
548
549 // move constructor
550 ConstructorTracker::Reset();
551 exp_track e3 = std::move(e);
552 EXPECT_EQ(0U, ConstructorTracker::constructor_called);
553 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
554 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
555 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
556 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
557
558 // construct from lvalue
559 ConstructorTracker::Reset();
560 ConstructorTracker ct = "hello";
561 exp_track e4(ct);
562 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
563 EXPECT_EQ(1U, ConstructorTracker::copy_constructor_called);
564 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
565 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
566 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
567
568 // construct from rvalue
569 ConstructorTracker::Reset();
570 ConstructorTracker ct2 = "hello";
571 exp_track e5(std::move(ct2));
572 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
573 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
574 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
575 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
576 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
577
578 // copy assignment
579 ConstructorTracker::Reset();
580 exp_track e6 = "hello";
581 exp_track e7 = "world";
582 e7 = e6;
583 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
584 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
585 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
586 EXPECT_EQ(1U, ConstructorTracker::copy_assignment_called);
587 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
588
589 // move assignment
590 ConstructorTracker::Reset();
591 exp_track e8 = "hello";
592 exp_track e9 = "world";
593 e9 = std::move(e8);
594 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
595 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
596 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
597 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
598 EXPECT_EQ(1U, ConstructorTracker::move_assignment_called);
599
600 // swap
601 ConstructorTracker::Reset();
602 exp_track e10 = "hello";
603 exp_track e11 = "world";
604 std::swap(e10, e11);
605 EXPECT_EQ(2U, ConstructorTracker::constructor_called);
606 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
607 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
608 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
609 EXPECT_EQ(2U, ConstructorTracker::move_assignment_called);
610}
611
612TEST(Expected, testNoCopyOnReturn) {
613 auto test = [](const std::string& in) -> exp_track {
614 if (in.empty()) {
615 return "literal string";
616 }
617 if (in == "test2") {
618 return ConstructorTracker(in + in + "2");
619 }
620 ConstructorTracker result(in + " " + in);
621 return result;
622 };
623
624 ConstructorTracker::Reset();
625 auto result1 = test("");
626 ASSERT_TRUE(result1);
627 EXPECT_EQ("literal string", result1->string);
628 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
629 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
630 EXPECT_EQ(0U, ConstructorTracker::move_constructor_called);
631 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
632 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
633
634 ConstructorTracker::Reset();
635 auto result2 = test("test2");
636 ASSERT_TRUE(result2);
637 EXPECT_EQ("test2test22", result2->string);
638 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
639 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
640 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
641 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
642 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
643
644 ConstructorTracker::Reset();
645 auto result3 = test("test3");
646 ASSERT_TRUE(result3);
647 EXPECT_EQ("test3 test3", result3->string);
648 EXPECT_EQ(1U, ConstructorTracker::constructor_called);
649 EXPECT_EQ(0U, ConstructorTracker::copy_constructor_called);
650 EXPECT_EQ(1U, ConstructorTracker::move_constructor_called);
651 EXPECT_EQ(0U, ConstructorTracker::copy_assignment_called);
652 EXPECT_EQ(0U, ConstructorTracker::move_assignment_called);
653}
654
655TEST(Expected, testNested) {
656 expected<exp_string, std::string> e = "hello";
657
658 EXPECT_TRUE(e.has_value());
659 EXPECT_TRUE(e.value().has_value());
660 EXPECT_TRUE(e);
661 EXPECT_TRUE(*e);
662 EXPECT_EQ("hello", e.value().value());
663
664 expected<exp_string, std::string> e2 = unexpected("world");
665 EXPECT_FALSE(e2.has_value());
666 EXPECT_FALSE(e2);
667 EXPECT_EQ("world", e2.error());
668
669 expected<exp_string, std::string> e3 = exp_string(unexpected("world"));
670 EXPECT_TRUE(e3.has_value());
671 EXPECT_FALSE(e3.value().has_value());
672 EXPECT_TRUE(e3);
673 EXPECT_FALSE(*e3);
674 EXPECT_EQ("world", e3.value().error());
675}
676
677constexpr bool equals(const char* a, const char* b) {
678 return (a == nullptr && b == nullptr) ||
679 (a != nullptr && b != nullptr && *a == *b &&
680 (*a == '\0' || equals(a + 1, b + 1)));
681}
682
683TEST(Expected, testConstexpr) {
684 // Compliation error will occur if these expressions can't be
685 // evaluated at compile time
686 constexpr exp_int e(3);
687 constexpr exp_int::unexpected_type err(3);
688 constexpr int i = 4;
689
690 // default constructor
691 static_assert(exp_int().value() == 0);
692 // copy constructor
693 static_assert(exp_int(e).value() == 3);
694 // move constructor
695 static_assert(exp_int(exp_int(4)).value() == 4);
696 // copy construct from value
697 static_assert(exp_int(i).value() == 4);
698 // copy construct from unexpected
699 static_assert(exp_int(err).error() == 3);
700 // move costruct from unexpected
701 static_assert(exp_int(unexpected(3)).error() == 3);
702 // observers
703 static_assert(*exp_int(3) == 3);
704 static_assert(exp_int(3).has_value() == true);
705 static_assert(exp_int(3).value_or(4) == 3);
706
707 typedef expected<const char*, int> exp_s;
708 constexpr exp_s s("hello");
709 constexpr const char* c = "hello";
710 static_assert(equals(exp_s().value(), nullptr));
711 static_assert(equals(exp_s(s).value(), "hello"));
712 static_assert(equals(exp_s(exp_s("hello")).value(), "hello"));
713 static_assert(equals(exp_s("hello").value(), "hello"));
714 static_assert(equals(exp_s(c).value(), "hello"));
715}
716
717TEST(Expected, testWithNonConstructible) {
718 struct AssertNotConstructed {
719 AssertNotConstructed() = delete;
720 };
721
722 expected<int, AssertNotConstructed> v(42);
723 EXPECT_TRUE(v.has_value());
724 EXPECT_EQ(42, v.value());
725
726 expected<AssertNotConstructed, int> e(unexpected(42));
727 EXPECT_FALSE(e.has_value());
728 EXPECT_EQ(42, e.error());
729}
730
731TEST(Expected, testWithMoveOnlyType) {
732 typedef expected<std::unique_ptr<int>,std::unique_ptr<int>> exp_ptr;
733 exp_ptr e(std::make_unique<int>(3));
734 exp_ptr e2(unexpected(std::make_unique<int>(4)));
735
736 EXPECT_TRUE(e.has_value());
737 EXPECT_FALSE(e2.has_value());
738 EXPECT_EQ(3, *(e.value()));
739 EXPECT_EQ(4, *(e2.error()));
740
741 e2 = std::move(e);
742 EXPECT_TRUE(e.has_value());
743 EXPECT_TRUE(e2.has_value());
744 EXPECT_EQ(3, *(e2.value()));
745}