Drop support for Clang < 3.9
[folly.git] / folly / test / ExpectedTest.cpp
1 /*
2  * Copyright 2017 Facebook, Inc.
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 <folly/Expected.h>
18 #include <folly/portability/GTest.h>
19
20 #include <algorithm>
21 #include <iomanip>
22 #include <memory>
23 #include <string>
24 #include <type_traits>
25 #include <vector>
26
27 #include <glog/logging.h>
28
29 using std::unique_ptr;
30 using std::shared_ptr;
31
32 namespace folly {
33
34 enum class E { E1, E2 };
35
36 std::ostream& operator<<(std::ostream& os, E e) {
37   switch (e) {
38     case E::E1:
39       return os << "E::E1";
40     case E::E2:
41       return os << "E::E2";
42     default:;
43   }
44   return os;
45 }
46
47 template <class V, class E>
48 std::ostream& operator<<(std::ostream& os, const Expected<V, E>& e) {
49   if (e) {
50     os << "Expected(" << e.value() << ')';
51   } else {
52     os << "Unexpected(" << e.error() << ')';
53   }
54   return os;
55 }
56
57 struct NoDefault {
58   NoDefault(int, int) {}
59   char a, b, c;
60 };
61
62 TEST(Expected, NoDefault) {
63   static_assert(
64       std::is_default_constructible<Expected<NoDefault, int>>::value, "");
65   Expected<NoDefault, int> x{in_place, 42, 42};
66   EXPECT_TRUE(bool(x));
67   x.emplace(4, 5);
68   EXPECT_TRUE(bool(x));
69   x = makeUnexpected(42);
70   EXPECT_FALSE(bool(x));
71   EXPECT_EQ(42, x.error());
72 }
73
74 TEST(Expected, String) {
75   Expected<std::string, int> maybeString;
76   EXPECT_FALSE(bool(maybeString));
77   EXPECT_EQ(0, maybeString.error());
78   maybeString = "hello";
79   EXPECT_TRUE(bool(maybeString));
80   EXPECT_EQ("hello", *maybeString);
81 }
82
83 TEST(Expected, Ambiguous) {
84   // Potentially ambiguous and confusing construction and assignment disallowed:
85   EXPECT_FALSE((std::is_constructible<Expected<int, int>, int>::value));
86   EXPECT_FALSE((std::is_assignable<Expected<int, int>&, int>::value));
87 }
88
89 TEST(Expected, Const) {
90   { // default construct
91     Expected<const int, int> ex;
92     EXPECT_FALSE(bool(ex));
93     EXPECT_EQ(0, ex.error());
94     ex.emplace(4);
95     EXPECT_EQ(4, *ex);
96     ex.emplace(5);
97     EXPECT_EQ(5, *ex);
98     ex = makeUnexpected(42);
99     EXPECT_FALSE(bool(ex));
100     EXPECT_EQ(42, ex.error());
101   }
102   { // copy-constructed
103     const int x = 6;
104     Expected<const int, int> ex{in_place, x};
105     Expected<const int, int> ex2 = ex;
106     EXPECT_EQ(6, *ex2);
107   }
108   { // move-constructed
109     const int x = 7;
110     Expected<const int, int> ex{in_place, std::move(x)};
111     Expected<const int, int> ex2 = std::move(ex);
112     EXPECT_EQ(7, *ex2);
113   }
114   // no assignment allowed
115   EXPECT_FALSE((std::is_copy_assignable<Expected<const int, int>>::value));
116 }
117
118 TEST(Expected, Simple) {
119   Expected<int, int> ex;
120   EXPECT_FALSE(bool(ex));
121   EXPECT_EQ(42, ex.value_or(42));
122   ex.emplace(4);
123   EXPECT_TRUE(bool(ex));
124   EXPECT_EQ(4, *ex);
125   EXPECT_EQ(4, ex.value_or(42));
126   ex = makeUnexpected(-1);
127   EXPECT_FALSE(bool(ex));
128   EXPECT_EQ(-1, ex.error());
129   EXPECT_EQ(42, ex.value_or(42));
130 }
131
132 class MoveTester {
133  public:
134   /* implicit */ MoveTester(const char* s) : s_(s) {}
135   MoveTester(const MoveTester&) = default;
136   MoveTester(MoveTester&& other) noexcept {
137     s_ = std::move(other.s_);
138     other.s_ = "";
139   }
140   MoveTester& operator=(const MoveTester&) = default;
141   MoveTester& operator=(MoveTester&& other) noexcept {
142     s_ = std::move(other.s_);
143     other.s_ = "";
144     return *this;
145   }
146
147  private:
148   friend bool operator==(const MoveTester& o1, const MoveTester& o2);
149   std::string s_;
150 };
151
152 bool operator==(const MoveTester& o1, const MoveTester& o2) {
153   return o1.s_ == o2.s_;
154 }
155
156 TEST(Expected, value_or_rvalue_arg) {
157   Expected<MoveTester, int> ex = makeUnexpected(-1);
158   MoveTester dflt = "hello";
159   EXPECT_EQ("hello", ex.value_or(dflt));
160   EXPECT_EQ("hello", dflt);
161   EXPECT_EQ("hello", ex.value_or(std::move(dflt)));
162   EXPECT_EQ("", dflt);
163   EXPECT_EQ("world", ex.value_or("world"));
164
165   dflt = "hello";
166   // Make sure that the const overload works on const objects
167   const auto& exc = ex;
168   EXPECT_EQ("hello", exc.value_or(dflt));
169   EXPECT_EQ("hello", dflt);
170   EXPECT_EQ("hello", exc.value_or(std::move(dflt)));
171   EXPECT_EQ("", dflt);
172   EXPECT_EQ("world", exc.value_or("world"));
173
174   dflt = "hello";
175   ex = "meow";
176   EXPECT_EQ("meow", ex.value_or(dflt));
177   EXPECT_EQ("hello", dflt);
178   EXPECT_EQ("meow", ex.value_or(std::move(dflt)));
179   EXPECT_EQ("hello", dflt); // only moved if used
180 }
181
182 TEST(Expected, value_or_noncopyable) {
183   Expected<std::unique_ptr<int>, int> ex{unexpected, 42};
184   std::unique_ptr<int> dflt(new int(42));
185   EXPECT_EQ(42, *std::move(ex).value_or(std::move(dflt)));
186 }
187
188 struct ExpectingDeleter {
189   explicit ExpectingDeleter(int expected) : expected(expected) {}
190   int expected;
191   void operator()(const int* ptr) {
192     EXPECT_EQ(*ptr, expected);
193     delete ptr;
194   }
195 };
196
197 TEST(Expected, value_move) {
198   auto ptr = Expected<std::unique_ptr<int, ExpectingDeleter>, int>(
199                  in_place, new int(42), ExpectingDeleter{1337})
200                  .value();
201   *ptr = 1337;
202 }
203
204 TEST(Expected, dereference_move) {
205   auto ptr = *Expected<std::unique_ptr<int, ExpectingDeleter>, int>(
206       in_place, new int(42), ExpectingDeleter{1337});
207   *ptr = 1337;
208 }
209
210 TEST(Expected, EmptyConstruct) {
211   Expected<int, int> ex{unexpected, 42};
212   EXPECT_FALSE(bool(ex));
213   Expected<int, int> test1(ex);
214   EXPECT_FALSE(bool(test1));
215   Expected<int, int> test2(std::move(ex));
216   EXPECT_FALSE(bool(test2));
217   EXPECT_EQ(42, test2.error());
218 }
219
220 TEST(Expected, Unique) {
221   Expected<unique_ptr<int>, int> ex;
222
223   ex = makeUnexpected(-1);
224   EXPECT_FALSE(bool(ex));
225   // empty->emplaced
226   ex.emplace(new int(5));
227   EXPECT_TRUE(bool(ex));
228   EXPECT_EQ(5, **ex);
229
230   ex = makeUnexpected(-1);
231   // empty->moved
232   ex = unique_ptr<int>(new int(6));
233   EXPECT_EQ(6, **ex);
234   // full->moved
235   ex = unique_ptr<int>(new int(7));
236   EXPECT_EQ(7, **ex);
237
238   // move it out by move construct
239   Expected<unique_ptr<int>, int> moved(std::move(ex));
240   EXPECT_TRUE(bool(moved));
241   EXPECT_TRUE(bool(ex));
242   EXPECT_EQ(nullptr, ex->get());
243   EXPECT_EQ(7, **moved);
244
245   EXPECT_TRUE(bool(moved));
246   ex = std::move(moved); // move it back by move assign
247   EXPECT_TRUE(bool(moved));
248   EXPECT_EQ(nullptr, moved->get());
249   EXPECT_TRUE(bool(ex));
250   EXPECT_EQ(7, **ex);
251 }
252
253 TEST(Expected, Shared) {
254   shared_ptr<int> ptr;
255   Expected<shared_ptr<int>, int> ex{unexpected, -1};
256   EXPECT_FALSE(bool(ex));
257   // empty->emplaced
258   ex.emplace(new int(5));
259   EXPECT_TRUE(bool(ex));
260   ptr = ex.value();
261   EXPECT_EQ(ptr.get(), ex->get());
262   EXPECT_EQ(2, ptr.use_count());
263   ex = makeUnexpected(-1);
264   EXPECT_EQ(1, ptr.use_count());
265   // full->copied
266   ex = ptr;
267   EXPECT_EQ(2, ptr.use_count());
268   EXPECT_EQ(ptr.get(), ex->get());
269   ex = makeUnexpected(-1);
270   EXPECT_EQ(1, ptr.use_count());
271   // full->moved
272   ex = std::move(ptr);
273   EXPECT_EQ(1, ex->use_count());
274   EXPECT_EQ(nullptr, ptr.get());
275   {
276     EXPECT_EQ(1, ex->use_count());
277     Expected<shared_ptr<int>, int> copied(ex);
278     EXPECT_EQ(2, ex->use_count());
279     Expected<shared_ptr<int>, int> moved(std::move(ex));
280     EXPECT_EQ(2, moved->use_count());
281     moved.emplace(new int(6));
282     EXPECT_EQ(1, moved->use_count());
283     copied = moved;
284     EXPECT_EQ(2, moved->use_count());
285   }
286 }
287
288 TEST(Expected, Order) {
289   std::vector<Expected<int, E>> vect{
290       {unexpected, E::E1}, {3}, {1}, {unexpected, E::E1}, {2},
291   };
292   std::vector<Expected<int, E>> expected{
293       {unexpected, E::E1}, {unexpected, E::E1}, {1}, {2}, {3},
294   };
295   std::sort(vect.begin(), vect.end());
296   EXPECT_EQ(vect, expected);
297 }
298
299 TEST(Expected, Swap) {
300   Expected<std::string, E> a;
301   Expected<std::string, E> b;
302
303   swap(a, b);
304   EXPECT_FALSE(a.hasValue());
305   EXPECT_FALSE(b.hasValue());
306
307   a = "hello";
308   EXPECT_TRUE(a.hasValue());
309   EXPECT_FALSE(b.hasValue());
310   EXPECT_EQ("hello", a.value());
311
312   swap(a, b);
313   EXPECT_FALSE(a.hasValue());
314   EXPECT_TRUE(b.hasValue());
315   EXPECT_EQ("hello", b.value());
316
317   a = "bye";
318   EXPECT_TRUE(a.hasValue());
319   EXPECT_EQ("bye", a.value());
320
321   swap(a, b);
322 }
323
324 TEST(Expected, Comparisons) {
325   Expected<int, E> o_;
326   Expected<int, E> o1(1);
327   Expected<int, E> o2(2);
328
329   EXPECT_TRUE(o_ <= (o_));
330   EXPECT_TRUE(o_ == (o_));
331   EXPECT_TRUE(o_ >= (o_));
332
333   EXPECT_TRUE(o1 < o2);
334   EXPECT_TRUE(o1 <= o2);
335   EXPECT_TRUE(o1 <= (o1));
336   EXPECT_TRUE(o1 == (o1));
337   EXPECT_TRUE(o1 != o2);
338   EXPECT_TRUE(o1 >= (o1));
339   EXPECT_TRUE(o2 >= o1);
340   EXPECT_TRUE(o2 > o1);
341
342   EXPECT_FALSE(o2 < o1);
343   EXPECT_FALSE(o2 <= o1);
344   EXPECT_FALSE(o2 <= o1);
345   EXPECT_FALSE(o2 == o1);
346   EXPECT_FALSE(o1 != (o1));
347   EXPECT_FALSE(o1 >= o2);
348   EXPECT_FALSE(o1 >= o2);
349   EXPECT_FALSE(o1 > o2);
350
351   /* folly::Expected explicitly doesn't support comparisons with contained value
352   EXPECT_TRUE(1 < o2);
353   EXPECT_TRUE(1 <= o2);
354   EXPECT_TRUE(1 <= o1);
355   EXPECT_TRUE(1 == o1);
356   EXPECT_TRUE(2 != o1);
357   EXPECT_TRUE(1 >= o1);
358   EXPECT_TRUE(2 >= o1);
359   EXPECT_TRUE(2 > o1);
360
361   EXPECT_FALSE(o2 < 1);
362   EXPECT_FALSE(o2 <= 1);
363   EXPECT_FALSE(o2 <= 1);
364   EXPECT_FALSE(o2 == 1);
365   EXPECT_FALSE(o2 != 2);
366   EXPECT_FALSE(o1 >= 2);
367   EXPECT_FALSE(o1 >= 2);
368   EXPECT_FALSE(o1 > 2);
369   */
370 }
371
372 TEST(Expected, Conversions) {
373   Expected<bool, E> mbool;
374   Expected<short, E> mshort;
375   Expected<char*, E> mstr;
376   Expected<int, E> mint;
377
378   EXPECT_FALSE((std::is_convertible<Expected<bool, E>&, bool>::value));
379   EXPECT_FALSE((std::is_convertible<Expected<short, E>&, short>::value));
380   EXPECT_FALSE((std::is_convertible<Expected<char*, E>&, char*>::value));
381   EXPECT_FALSE((std::is_convertible<Expected<int, E>&, int>::value));
382
383   // intended explicit operator bool, for if (ex).
384   bool b(mbool);
385   EXPECT_FALSE(b);
386
387   // Truthy tests work and are not ambiguous
388   if (mbool && mshort && mstr && mint) { // only checks not-empty
389     if (*mbool && *mshort && *mstr && *mint) { // only checks value
390       ;
391     }
392   }
393
394   mbool = false;
395   EXPECT_TRUE(bool(mbool));
396   EXPECT_FALSE(*mbool);
397
398   mbool = true;
399   EXPECT_TRUE(bool(mbool));
400   EXPECT_TRUE(*mbool);
401
402   mbool = {unexpected, E::E1};
403   EXPECT_FALSE(bool(mbool));
404
405   // No conversion allowed; does not compile
406   // mbool == false;
407 }
408
409 TEST(Expected, Pointee) {
410   Expected<int, E> x;
411   EXPECT_FALSE(get_pointer(x));
412   x = 1;
413   EXPECT_TRUE(get_pointer(x));
414   *get_pointer(x) = 2;
415   EXPECT_TRUE(*x == 2);
416   x = {unexpected, E::E1};
417   EXPECT_FALSE(get_pointer(x));
418 }
419
420 TEST(Expected, MakeOptional) {
421   // const L-value version
422   const std::string s("abc");
423   auto exStr = makeExpected<E>(s);
424   ASSERT_TRUE(exStr.hasValue());
425   EXPECT_EQ(*exStr, "abc");
426   *exStr = "cde";
427   EXPECT_EQ(s, "abc");
428   EXPECT_EQ(*exStr, "cde");
429
430   // L-value version
431   std::string s2("abc");
432   auto exStr2 = makeExpected<E>(s2);
433   ASSERT_TRUE(exStr2.hasValue());
434   EXPECT_EQ(*exStr2, "abc");
435   *exStr2 = "cde";
436   // it's vital to check that s2 wasn't clobbered
437   EXPECT_EQ(s2, "abc");
438
439   // L-value reference version
440   std::string& s3(s2);
441   auto exStr3 = makeExpected<E>(s3);
442   ASSERT_TRUE(exStr3.hasValue());
443   EXPECT_EQ(*exStr3, "abc");
444   *exStr3 = "cde";
445   EXPECT_EQ(s3, "abc");
446
447   // R-value ref version
448   unique_ptr<int> pInt(new int(3));
449   auto exIntPtr = makeExpected<E>(std::move(pInt));
450   EXPECT_TRUE(pInt.get() == nullptr);
451   ASSERT_TRUE(exIntPtr.hasValue());
452   EXPECT_EQ(**exIntPtr, 3);
453 }
454
455 #if __clang__
456 #pragma clang diagnostic push
457 #pragma clang diagnostic ignored "-Wself-move"
458 #endif
459
460 TEST(Expected, SelfAssignment) {
461   Expected<std::string, E> a = "42";
462   a = a;
463   ASSERT_TRUE(a.hasValue() && a.value() == "42");
464
465   Expected<std::string, E> b = "23333333";
466   b = std::move(b);
467   ASSERT_TRUE(b.hasValue() && b.value() == "23333333");
468 }
469
470 #if __clang__
471 #pragma clang diagnostic pop
472 #endif
473
474 class ContainsExpected {
475  public:
476   ContainsExpected() {}
477   explicit ContainsExpected(int x) : ex_(x) {}
478   bool hasValue() const {
479     return ex_.hasValue();
480   }
481   int value() const {
482     return ex_.value();
483   }
484
485   ContainsExpected(const ContainsExpected& other) = default;
486   ContainsExpected& operator=(const ContainsExpected& other) = default;
487   ContainsExpected(ContainsExpected&& other) = default;
488   ContainsExpected& operator=(ContainsExpected&& other) = default;
489
490  private:
491   Expected<int, E> ex_;
492 };
493
494 /**
495  * Test that a class containing an Expected can be copy and move assigned.
496  * This was broken under gcc 4.7 until assignment operators were explicitly
497  * defined.
498  */
499 TEST(Expected, AssignmentContained) {
500   {
501     ContainsExpected source(5), target;
502     target = source;
503     EXPECT_TRUE(target.hasValue());
504     EXPECT_EQ(5, target.value());
505   }
506
507   {
508     ContainsExpected source(5), target;
509     target = std::move(source);
510     EXPECT_TRUE(target.hasValue());
511     EXPECT_EQ(5, target.value());
512     EXPECT_TRUE(source.hasValue());
513   }
514
515   {
516     ContainsExpected ex_uninit, target(10);
517     target = ex_uninit;
518     EXPECT_FALSE(target.hasValue());
519   }
520 }
521
522 TEST(Expected, Exceptions) {
523   Expected<int, E> empty;
524   EXPECT_THROW(empty.value(), Unexpected<E>::BadExpectedAccess);
525 }
526
527 struct ThrowingBadness {
528   ThrowingBadness() noexcept(false);
529   ThrowingBadness(const ThrowingBadness&) noexcept(false);
530   ThrowingBadness(ThrowingBadness&&) noexcept(false);
531   ThrowingBadness& operator=(const ThrowingBadness&) noexcept(false);
532   ThrowingBadness& operator=(ThrowingBadness&&) noexcept(false);
533 };
534
535 TEST(Expected, NoThrowDefaultConstructible) {
536   EXPECT_TRUE(
537       (std::is_nothrow_default_constructible<Expected<bool, E>>::value));
538   EXPECT_TRUE(
539       (std::is_nothrow_default_constructible<Expected<std::string, E>>::value));
540   EXPECT_TRUE((std::is_nothrow_default_constructible<
541                Expected<ThrowingBadness, E>>::value));
542   EXPECT_FALSE((std::is_nothrow_default_constructible<
543                 Expected<int, ThrowingBadness>>::value));
544 }
545
546 TEST(Expected, NoThrowMoveConstructible) {
547   EXPECT_TRUE((std::is_nothrow_move_constructible<Expected<bool, E>>::value));
548   EXPECT_TRUE((std::is_nothrow_move_constructible<
549                Expected<std::unique_ptr<int>, E>>::value));
550   EXPECT_FALSE((
551       std::is_nothrow_move_constructible<Expected<ThrowingBadness, E>>::value));
552 }
553
554 TEST(Expected, NoThrowMoveAssignable) {
555   EXPECT_TRUE((std::is_nothrow_move_assignable<Expected<bool, E>>::value));
556   EXPECT_TRUE((std::is_nothrow_move_assignable<
557                Expected<std::unique_ptr<int>, E>>::value));
558   EXPECT_FALSE(
559       (std::is_nothrow_move_assignable<Expected<ThrowingBadness, E>>::value));
560 }
561
562 struct NoSelfAssign {
563   NoSelfAssign() = default;
564   NoSelfAssign(NoSelfAssign&&) = default;
565   NoSelfAssign(const NoSelfAssign&) = default;
566   NoSelfAssign& operator=(NoSelfAssign&& that) {
567     EXPECT_NE(this, &that);
568     return *this;
569   }
570   NoSelfAssign& operator=(const NoSelfAssign& that) {
571     EXPECT_NE(this, &that);
572     return *this;
573   }
574 };
575
576 #ifdef __GNUC__
577 #pragma GCC diagnostic push
578 #pragma GCC diagnostic ignored "-Wpragmas"
579 #pragma GCC diagnostic ignored "-Wself-move"
580 #endif
581
582 TEST(Expected, NoSelfAssign) {
583   folly::Expected<NoSelfAssign, int> e {NoSelfAssign{}};
584   e = e; // @nolint
585   e = std::move(e); // @nolint
586 }
587
588 #ifdef __GNUC__
589 #pragma GCC diagnostic pop
590 #endif
591
592 struct NoDestructor {};
593
594 struct WithDestructor {
595   ~WithDestructor();
596 };
597
598 TEST(Expected, TriviallyDestructible) {
599   // These could all be static_asserts but EXPECT_* give much nicer output on
600   // failure.
601   EXPECT_TRUE(
602       (std::is_trivially_destructible<Expected<NoDestructor, E>>::value));
603   EXPECT_TRUE((std::is_trivially_destructible<Expected<int, E>>::value));
604   EXPECT_FALSE(
605       (std::is_trivially_destructible<Expected<WithDestructor, E>>::value));
606 }
607
608 struct NoConstructor {};
609
610 struct WithConstructor {
611   WithConstructor();
612 };
613
614 TEST(Expected, TriviallyCopyable) {
615   // These could all be static_asserts but EXPECT_* give much nicer output on
616   // failure.
617   EXPECT_TRUE((IsTriviallyCopyable<Expected<int, E>>::value));
618   EXPECT_TRUE((IsTriviallyCopyable<Expected<char*, E>>::value));
619   EXPECT_TRUE(
620       (IsTriviallyCopyable<Expected<NoDestructor, E>>::value));
621   EXPECT_FALSE(
622       (IsTriviallyCopyable<Expected<WithDestructor, E>>::value));
623   EXPECT_TRUE(
624       (IsTriviallyCopyable<Expected<NoConstructor, E>>::value));
625   EXPECT_FALSE(
626       (IsTriviallyCopyable<Expected<std::string, E>>::value));
627   EXPECT_FALSE(
628       (IsTriviallyCopyable<Expected<int, std::string>>::value));
629 // libstdc++ with GCC 4.x doesn't have std::is_trivially_copyable
630 #if (defined(__clang__) && !defined(_LIBCPP_VERSION)) || \
631     !(defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 5)
632   EXPECT_TRUE(
633       (IsTriviallyCopyable<Expected<WithConstructor, E>>::value));
634 #endif
635   EXPECT_TRUE(
636       (IsTriviallyCopyable<Expected<Expected<int, E>, E>>::value));
637 }
638
639 TEST(Expected, Then) {
640   // Lifting
641   {
642     Expected<int, E> ex = Expected<std::unique_ptr<int>, E>{
643         in_place, new int(42)}.then([](std::unique_ptr<int> p) { return *p; });
644     EXPECT_TRUE(bool(ex));
645     EXPECT_EQ(42, *ex);
646   }
647
648   // Flattening
649   {
650     Expected<int, E> ex =
651         Expected<std::unique_ptr<int>, E>{in_place, new int(42)}.then(
652             [](std::unique_ptr<int> p) { return makeExpected<E>(*p); });
653     EXPECT_TRUE(bool(ex));
654     EXPECT_EQ(42, *ex);
655   }
656
657   // Void
658   {
659     Expected<Unit, E> ex = Expected<std::unique_ptr<int>, E>{
660         in_place, new int(42)}.then([](std::unique_ptr<int>) {});
661     EXPECT_TRUE(bool(ex));
662   }
663
664   // Non-flattening (different error codes)
665   {
666     Expected<Expected<int, int>, E> ex =
667         Expected<std::unique_ptr<int>, E>{in_place, new int(42)}.then(
668             [](std::unique_ptr<int> p) { return makeExpected<int>(*p); });
669     EXPECT_TRUE(bool(ex));
670     EXPECT_TRUE(bool(*ex));
671     EXPECT_EQ(42, **ex);
672   }
673
674   {
675     // Error case:
676     Expected<int, E> ex = Expected<std::unique_ptr<int>, E>{
677         unexpected, E::E1}.then([](std::unique_ptr<int> p) -> int {
678       EXPECT_TRUE(false);
679       return *p;
680     });
681     EXPECT_FALSE(bool(ex));
682     EXPECT_EQ(E::E1, ex.error());
683   }
684
685   // Chaining
686   {
687     Expected<std::string, E> ex =
688         Expected<std::unique_ptr<int>, E>{in_place, new int(42)}.then(
689             [](std::unique_ptr<int> p) { return makeExpected<E>(*p); },
690             [](int i) { return i == 42 ? "yes" : "no"; });
691     EXPECT_TRUE(bool(ex));
692     EXPECT_EQ("yes", *ex);
693   }
694
695   // Chaining with errors
696   {
697     Expected<std::string, E> ex =
698         Expected<std::unique_ptr<int>, E>{in_place, new int(42)}.then(
699             [](std::unique_ptr<int>) {
700               return Expected<int, E>(unexpected, E::E1);
701             },
702             [](int i) { return i == 42 ? "yes" : "no"; });
703     EXPECT_FALSE(bool(ex));
704     EXPECT_EQ(E::E1, ex.error());
705   }
706 }
707
708 TEST(Expected, ThenOrThrow) {
709   {
710     int e =
711         Expected<std::unique_ptr<int>, E>{in_place, new int(42)}.thenOrThrow(
712             [](std::unique_ptr<int> p) { return *p; });
713     EXPECT_EQ(42, e);
714   }
715
716   {
717     EXPECT_THROW(
718         (Expected<std::unique_ptr<int>, E>{unexpected, E::E1}.thenOrThrow(
719             [](std::unique_ptr<int> p) { return *p; })),
720         Unexpected<E>::BadExpectedAccess);
721   }
722
723   {
724     EXPECT_THROW(
725         (Expected<std::unique_ptr<int>, E>{unexpected, E::E1}.thenOrThrow(
726             [](std::unique_ptr<int> p) { return *p; },
727             [](E) { return std::runtime_error(""); })),
728         std::runtime_error);
729   }
730
731   {
732     EXPECT_THROW(
733         (Expected<std::unique_ptr<int>, E>{unexpected, E::E1}.thenOrThrow(
734             [](std::unique_ptr<int> p) { return *p; },
735             [](E) { throw std::runtime_error(""); })),
736         std::runtime_error);
737   }
738
739   {
740     EXPECT_THROW(
741         (Expected<std::unique_ptr<int>, E>{unexpected, E::E1}.thenOrThrow(
742             [](std::unique_ptr<int> p) { return *p; }, [](E) {})),
743         Unexpected<E>::BadExpectedAccess);
744   }
745 }
746 }