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