proxygen
TryTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014-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/Try.h>
18 
19 #include <glog/logging.h>
20 
21 #include <folly/Memory.h>
22 #include <folly/Traits.h>
24 
25 using namespace folly;
26 
27 namespace {
28 
29 class A {
30  public:
31  explicit A(int x) : x_(x) {}
32 
33  int x() const {
34  return x_;
35  }
36 
37  private:
38  int x_;
39 };
40 
41 template <bool Nothrow>
42 class HasCtors {
43  public:
44  explicit HasCtors(int) noexcept(Nothrow) {}
45  HasCtors(HasCtors&&) noexcept(Nothrow) {}
46  HasCtors& operator=(HasCtors&&) noexcept(Nothrow) {}
47  HasCtors(HasCtors const&) noexcept(Nothrow) {}
48  HasCtors& operator=(HasCtors const&) noexcept(Nothrow) {}
49 };
50 
51 class MoveConstructOnly {
52  public:
53  MoveConstructOnly() = default;
54  MoveConstructOnly(const MoveConstructOnly&) = delete;
55  MoveConstructOnly(MoveConstructOnly&&) = default;
56 };
57 
58 class MutableContainer {
59  public:
60  mutable MoveConstructOnly val;
61 };
62 } // namespace
63 
65  A a(5);
66  Try<A> t_a(std::move(a));
67 
68  Try<Unit> t_void;
69 
70  EXPECT_EQ(5, t_a.value().x());
71 }
72 
74  Try<A> t_a(in_place, 5);
75 
76  EXPECT_EQ(5, t_a.value().x());
77 }
78 
79 TEST(Try, in_place_nested) {
80  Try<Try<A>> t_t_a(in_place, in_place, 5);
81 
82  EXPECT_EQ(5, t_t_a.value().value().x());
83 }
84 
85 TEST(Try, assignmentWithThrowingCopyConstructor) {
86  struct MyException : std::exception {};
87  struct ThrowingCopyConstructor {
88  int& counter_;
89  explicit ThrowingCopyConstructor(int& counter) : counter_(counter) {
90  ++counter_;
91  }
92 
93  [[noreturn]] ThrowingCopyConstructor(
94  const ThrowingCopyConstructor& other) noexcept(false)
95  : counter_(other.counter_) {
96  throw MyException{};
97  }
98 
99  ThrowingCopyConstructor& operator=(const ThrowingCopyConstructor&) = delete;
100 
101  ~ThrowingCopyConstructor() {
102  --counter_;
103  }
104  };
105 
106  int counter = 0;
107 
108  {
111  EXPECT_EQ(2, counter);
112  EXPECT_THROW(t2 = t1, MyException);
113  EXPECT_EQ(1, counter);
114  EXPECT_FALSE(t2.hasValue());
115  EXPECT_TRUE(t1.hasValue());
116  }
117  EXPECT_EQ(0, counter);
118  {
121  EXPECT_EQ(1, counter);
122  EXPECT_THROW(t2 = t1, MyException);
123  EXPECT_EQ(1, counter);
124  EXPECT_FALSE(t2.hasValue());
125  EXPECT_TRUE(t1.hasValue());
126  }
127  EXPECT_EQ(0, counter);
128 }
129 
130 TEST(Try, assignmentWithThrowingMoveConstructor) {
131  struct MyException : std::exception {};
132  struct ThrowingMoveConstructor {
133  int& counter_;
134  explicit ThrowingMoveConstructor(int& counter) : counter_(counter) {
135  ++counter_;
136  }
137 
138  [[noreturn]] ThrowingMoveConstructor(
139  ThrowingMoveConstructor&& other) noexcept(false)
140  : counter_(other.counter_) {
141  throw MyException{};
142  }
143 
144  ThrowingMoveConstructor& operator=(ThrowingMoveConstructor&&) = delete;
145 
146  ~ThrowingMoveConstructor() {
147  --counter_;
148  }
149  };
150 
151  int counter = 0;
152 
153  {
156  EXPECT_EQ(2, counter);
158  EXPECT_EQ(1, counter);
159  EXPECT_FALSE(t2.hasValue());
160  EXPECT_TRUE(t1.hasValue());
161  }
162  EXPECT_EQ(0, counter);
163  {
166  EXPECT_EQ(1, counter);
168  EXPECT_EQ(1, counter);
169  EXPECT_FALSE(t2.hasValue());
170  EXPECT_TRUE(t1.hasValue());
171  }
172  EXPECT_EQ(0, counter);
173 }
174 
175 TEST(Try, emplace) {
176  Try<A> t;
177  A& t_a = t.emplace(10);
178  EXPECT_TRUE(t.hasValue());
179  EXPECT_EQ(t_a.x(), 10);
180 }
181 
182 TEST(Try, emplaceWithThrowingConstructor) {
183  struct MyException : std::exception {};
184  struct ThrowingConstructor {
185  explicit ThrowingConstructor(bool shouldThrow) {
186  if (shouldThrow) {
187  throw MyException{};
188  }
189  }
190  };
191 
192  {
193  // Try constructing from empty state to new value and constructor throws.
195  EXPECT_FALSE(t.hasValue());
197  EXPECT_THROW(t.emplace(true), MyException);
198 
199  EXPECT_FALSE(t.hasValue());
201  }
202 
203  {
204  // Initialise to value, then re-emplace with throwing constructor.
205  // This should reset the object back to empty.
207  EXPECT_TRUE(t.hasValue());
208  EXPECT_THROW(t.emplace(true), MyException);
209  EXPECT_FALSE(t.hasValue());
210  EXPECT_FALSE(t.hasException());
211  }
212 }
213 
215  Try<A> t;
216  A* a = tryEmplace(t, 10);
217  EXPECT_EQ(&t.value(), a);
218  EXPECT_TRUE(t.hasValue());
219  EXPECT_EQ(10, t.value().x());
220 }
221 
222 TEST(Try, tryEmplaceWithThrowingConstructor) {
223  struct MyException : std::exception {};
224  struct NonInheritingException {};
225  struct ThrowingConstructor {
226  [[noreturn]] ThrowingConstructor() noexcept(false) {
227  throw NonInheritingException{}; // @nolint
228  }
229 
230  explicit ThrowingConstructor(bool shouldThrow) {
231  if (shouldThrow) {
232  throw MyException{};
233  }
234  }
235  };
236 
237  {
239  EXPECT_EQ(nullptr, tryEmplace(t, true));
242  }
243 
244  {
246  EXPECT_EQ(nullptr, tryEmplace(t));
248  EXPECT_NE(t.tryGetExceptionObject<NonInheritingException>(), nullptr);
249  }
250 
251  {
253  EXPECT_NE(nullptr, tryEmplace(t, false));
254  EXPECT_TRUE(t.hasValue());
255  EXPECT_EQ(nullptr, tryEmplace(t, true));
258  }
259 }
260 
261 TEST(Try, emplaceVoidTry) {
262  struct MyException : std::exception {};
263  Try<void> t;
264  t.emplace();
265  EXPECT_TRUE(t.hasValue());
266  t.emplaceException(folly::in_place_type<MyException>);
267  EXPECT_FALSE(t.hasValue());
270  t.emplace();
271  EXPECT_TRUE(t.hasValue());
273 }
274 
275 TEST(Try, tryEmplaceVoidTry) {
276  struct MyException : std::exception {};
277  Try<void> t;
278  tryEmplace(t);
279  EXPECT_TRUE(t.hasValue());
280  t.emplaceException(folly::in_place_type<MyException>);
281  EXPECT_FALSE(t.hasValue());
284  t.emplace();
285  EXPECT_TRUE(t.hasValue());
287 }
288 
291  tryEmplaceWith(t, [] { return "hello"; });
292  EXPECT_EQ("hello", t.value());
293 }
294 
295 TEST(Try, tryEmplaceWithFunctionThrows) {
296  struct MyException : std::exception {};
297  Try<int> t;
298  tryEmplaceWith(t, []() -> int { throw MyException{}; });
301 }
302 
303 TEST(Try, tryEmplaceWithConstructorThrows) {
304  struct MyException : std::exception {};
305  struct ThrowingConstructor {
306  int value_;
307  explicit ThrowingConstructor(bool shouldThrow) noexcept(false) : value_(0) {
308  if (shouldThrow) {
309  throw MyException{};
310  }
311  }
312  };
313 
315  tryEmplaceWith(t, [] { return false; });
316  EXPECT_TRUE(t.hasValue());
317  tryEmplaceWith(t, [] { return true; });
320 }
321 
322 TEST(Try, tryEmplaceWithVoidTry) {
323  Try<void> t;
324  bool hasRun = false;
325  tryEmplaceWith(t, [&] { hasRun = true; });
326  EXPECT_TRUE(t.hasValue());
327  EXPECT_TRUE(hasRun);
328 
329  struct MyException : std::exception {};
330  tryEmplaceWith(t, [&] { throw MyException{}; });
333 }
334 
335 TEST(Try, nothrow) {
336  using F = HasCtors<false>;
337  using T = HasCtors<true>;
338 
339  // default ctor
340  EXPECT_TRUE(std::is_nothrow_default_constructible<Try<F>>::value);
341  EXPECT_TRUE(std::is_nothrow_default_constructible<Try<T>>::value);
342  EXPECT_TRUE(std::is_nothrow_default_constructible<Try<void>>::value);
343 
344  // inner ctor - no void
345  EXPECT_FALSE((std::is_nothrow_constructible<Try<F>, F&&>::value));
346  EXPECT_TRUE((std::is_nothrow_constructible<Try<T>, T&&>::value));
347  EXPECT_FALSE((std::is_nothrow_constructible<Try<F>, F const&>::value));
348  EXPECT_TRUE((std::is_nothrow_constructible<Try<T>, T const&>::value));
349 
350  // emplacing ctor - no void
351  EXPECT_FALSE((std::is_nothrow_constructible<Try<F>, in_place_t, int>::value));
352  EXPECT_TRUE((std::is_nothrow_constructible<Try<T>, in_place_t, int>::value));
353 
354  // copy/move ctor/assign
355  EXPECT_TRUE(std::is_nothrow_constructible<Try<void>>::value);
356  EXPECT_FALSE(std::is_nothrow_move_constructible<Try<F>>::value);
357  EXPECT_TRUE(std::is_nothrow_move_constructible<Try<T>>::value);
358  EXPECT_TRUE(std::is_nothrow_move_constructible<Try<void>>::value);
359  EXPECT_FALSE(std::is_nothrow_move_assignable<Try<F>>::value);
360  EXPECT_TRUE(std::is_nothrow_move_assignable<Try<T>>::value);
361  EXPECT_TRUE(std::is_nothrow_move_assignable<Try<void>>::value);
362  EXPECT_FALSE(std::is_nothrow_copy_constructible<Try<F>>::value);
363  EXPECT_TRUE(std::is_nothrow_copy_constructible<Try<T>>::value);
364  EXPECT_TRUE(std::is_nothrow_copy_constructible<Try<void>>::value);
365  EXPECT_FALSE(std::is_nothrow_copy_assignable<Try<F>>::value);
366  EXPECT_TRUE(std::is_nothrow_copy_assignable<Try<T>>::value);
367  EXPECT_TRUE(std::is_nothrow_copy_assignable<Try<void>>::value);
368 
369  // conversion ctor - void to unit
370  EXPECT_TRUE((std::is_nothrow_constructible<Try<Unit>, Try<void>&&>::value));
371  EXPECT_TRUE(
372  (std::is_nothrow_constructible<Try<Unit>, Try<void> const&>::value));
373 }
374 
375 TEST(Try, MoveDereference) {
376  auto ptr = std::make_unique<int>(1);
378  auto result = *std::move(t);
379  EXPECT_EQ(*result, 1);
380 }
381 
382 TEST(Try, MoveConstRvalue) {
383  // tests to see if Try returns a const Rvalue, this is required in the case
384  // where for example MutableContainer has a mutable memebr that is move only
385  // and you want to fetch the value from the Try and move it into a member
386  {
388  auto val = MoveConstructOnly(std::move(t).value().val);
389  static_cast<void>(val);
390  }
391  {
393  auto val = (*(std::move(t))).val;
394  static_cast<void>(val);
395  }
396 }
397 
398 TEST(Try, ValueOverloads) {
399  using ML = int&;
400  using MR = int&&;
401  using CL = const int&;
402  using CR = const int&&;
403 
404  {
405  auto obj = Try<int>{};
406  using ActualML = decltype(obj.value());
407  using ActualMR = decltype(std::move(obj).value());
408  using ActualCL = decltype(as_const(obj).value());
409  using ActualCR = decltype(std::move(as_const(obj)).value());
414  }
415 
416  {
417  auto obj = Try<int>{3};
418  EXPECT_EQ(obj.value(), 3);
419  EXPECT_EQ(std::move(obj).value(), 3);
420  EXPECT_EQ(as_const(obj).value(), 3);
421  EXPECT_EQ(std::move(as_const(obj)).value(), 3);
422  }
423 
424  {
425  auto obj = Try<int>{make_exception_wrapper<std::range_error>("oops")};
426  EXPECT_THROW(obj.value(), std::range_error);
427  EXPECT_THROW(std::move(obj.value()), std::range_error);
428  EXPECT_THROW(as_const(obj.value()), std::range_error);
429  EXPECT_THROW(std::move(as_const(obj.value())), std::range_error);
430  }
431 }
432 
433 // Make sure we can copy Trys for copyable types
435  Try<int> t;
436  auto t2 = t;
437 }
438 
439 // But don't choke on move-only types
440 TEST(Try, moveOnly) {
442  std::vector<Try<std::unique_ptr<int>>> v;
443  v.reserve(10);
444 }
445 
447  auto func = []() { return std::make_unique<int>(1); };
448 
449  auto result = makeTryWith(func);
450  EXPECT_TRUE(result.hasValue());
451  EXPECT_EQ(*result.value(), 1);
452 }
453 
454 TEST(Try, makeTryWithThrow) {
455  auto func = []() -> std::unique_ptr<int> {
456  throw std::runtime_error("Runtime");
457  };
458 
459  auto result = makeTryWith(func);
460  EXPECT_TRUE(result.hasException<std::runtime_error>());
461 }
462 
463 TEST(Try, makeTryWithVoid) {
464  auto func = []() { return; };
465 
466  auto result = makeTryWith(func);
467  EXPECT_TRUE(result.hasValue());
468 }
469 
470 TEST(Try, makeTryWithVoidThrow) {
471  auto func = []() { throw std::runtime_error("Runtime"); };
472 
473  auto result = makeTryWith(func);
474  EXPECT_TRUE(result.hasException<std::runtime_error>());
475 }
476 
477 TEST(Try, exception) {
478  using ML = exception_wrapper&;
479  using MR = exception_wrapper&&;
480  using CL = exception_wrapper const&;
481  using CR = exception_wrapper const&&;
482 
483  {
484  auto obj = Try<int>();
485  using ActualML = decltype(obj.exception());
486  using ActualMR = decltype(std::move(obj).exception());
487  using ActualCL = decltype(as_const(obj).exception());
488  using ActualCR = decltype(std::move(as_const(obj)).exception());
493  }
494 
495  {
496  auto obj = Try<int>(3);
497  EXPECT_THROW(obj.exception(), TryException);
498  EXPECT_THROW(std::move(obj).exception(), TryException);
499  EXPECT_THROW(as_const(obj).exception(), TryException);
500  EXPECT_THROW(std::move(as_const(obj)).exception(), TryException);
501  }
502 
503  {
504  auto obj = Try<int>(make_exception_wrapper<int>(-3));
505  EXPECT_EQ(-3, *obj.exception().get_exception<int>());
506  EXPECT_EQ(-3, *std::move(obj).exception().get_exception<int>());
507  EXPECT_EQ(-3, *as_const(obj).exception().get_exception<int>());
508  EXPECT_EQ(-3, *std::move(as_const(obj)).exception().get_exception<int>());
509  }
510 
511  {
512  auto obj = Try<void>();
513  using ActualML = decltype(obj.exception());
514  using ActualMR = decltype(std::move(obj).exception());
515  using ActualCL = decltype(as_const(obj).exception());
516  using ActualCR = decltype(std::move(as_const(obj)).exception());
521  }
522 
523  {
524  auto obj = Try<void>();
525  EXPECT_THROW(obj.exception(), TryException);
526  EXPECT_THROW(std::move(obj).exception(), TryException);
527  EXPECT_THROW(as_const(obj).exception(), TryException);
528  EXPECT_THROW(std::move(as_const(obj)).exception(), TryException);
529  }
530 
531  {
532  auto obj = Try<void>(make_exception_wrapper<int>(-3));
533  EXPECT_EQ(-3, *obj.exception().get_exception<int>());
534  EXPECT_EQ(-3, *std::move(obj).exception().get_exception<int>());
535  EXPECT_EQ(-3, *as_const(obj).exception().get_exception<int>());
536  EXPECT_EQ(-3, *std::move(as_const(obj)).exception().get_exception<int>());
537  }
538 }
539 
540 template <typename E>
541 static E* get_exception(std::exception_ptr eptr) {
542  try {
543  std::rethrow_exception(eptr);
544  } catch (E& e) {
545  return &e;
546  } catch (...) {
547  return nullptr;
548  }
549 }
550 
551 TEST(Try, tryGetExceptionObject) {
552  auto epexn = std::make_exception_ptr(std::range_error("oops"));
553  auto epnum = std::make_exception_ptr(17);
554 
555  auto exn = CHECK_NOTNULL(get_exception<std::range_error>(epexn));
556  auto num = CHECK_NOTNULL(get_exception<int>(epnum));
557 
558  {
559  auto t = Try<bool>(true);
560  EXPECT_EQ(nullptr, t.tryGetExceptionObject());
561  EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
562  EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
563  }
564 
565  {
566  auto t = Try<bool>(exception_wrapper(epexn, *exn));
567  EXPECT_EQ(exn, t.tryGetExceptionObject());
568  EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
569  EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
570  }
571 
572  {
573  auto t = Try<bool>(exception_wrapper(epnum, *num));
574  EXPECT_EQ(nullptr, t.tryGetExceptionObject());
575  EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
576  EXPECT_EQ(num, t.tryGetExceptionObject<int>());
577  }
578 
579  {
580  auto t = Try<void>();
581  EXPECT_EQ(nullptr, t.tryGetExceptionObject());
582  EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
583  EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
584  }
585 
586  {
587  auto t = Try<void>(exception_wrapper(epexn, *exn));
588  EXPECT_EQ(exn, t.tryGetExceptionObject());
589  EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
590  EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
591  }
592 
593  {
594  auto t = Try<void>(exception_wrapper(epnum, *num));
595  EXPECT_EQ(nullptr, t.tryGetExceptionObject());
596  EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
597  EXPECT_EQ(num, t.tryGetExceptionObject<int>());
598  }
599 
600  {
601  auto const t = Try<bool>(true);
602  EXPECT_EQ(nullptr, t.tryGetExceptionObject());
603  EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
604  EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
605  }
606 
607  {
608  auto const t = Try<bool>(exception_wrapper(epexn, *exn));
609  EXPECT_EQ(exn, t.tryGetExceptionObject());
610  EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
611  EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
612  }
613 
614  {
615  auto const t = Try<bool>(exception_wrapper(epnum, *num));
616  EXPECT_EQ(nullptr, t.tryGetExceptionObject());
617  EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
618  EXPECT_EQ(num, t.tryGetExceptionObject<int>());
619  }
620 
621  {
622  auto const t = Try<void>();
623  EXPECT_EQ(nullptr, t.tryGetExceptionObject());
624  EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
625  EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
626  }
627 
628  {
629  auto const t = Try<void>(exception_wrapper(epexn, *exn));
630  EXPECT_EQ(exn, t.tryGetExceptionObject());
631  EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
632  EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
633  }
634 
635  {
636  auto const t = Try<void>(exception_wrapper(epnum, *num));
637  EXPECT_EQ(nullptr, t.tryGetExceptionObject());
638  EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
639  EXPECT_EQ(num, t.tryGetExceptionObject<int>());
640  }
641 }
642 
643 TEST(Try, withException) {
644  auto ew = make_exception_wrapper<std::range_error>("oops");
645 
646  {
647  auto t = Try<bool>(true);
648  EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
649  EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
650  EXPECT_FALSE(t.withException([](std::runtime_error&) {}));
651  EXPECT_FALSE(t.withException([](std::logic_error&) {}));
652  }
653 
654  {
655  auto t = Try<bool>(ew);
656  EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
657  EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
658  EXPECT_TRUE(t.withException([](std::runtime_error&) {}));
659  EXPECT_FALSE(t.withException([](std::logic_error&) {}));
660  }
661 
662  {
663  auto t = Try<void>();
664  EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
665  EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
666  EXPECT_FALSE(t.withException([](std::runtime_error&) {}));
667  EXPECT_FALSE(t.withException([](std::logic_error&) {}));
668  }
669 
670  {
671  auto t = Try<void>(ew);
672  EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
673  EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
674  EXPECT_TRUE(t.withException([](std::runtime_error&) {}));
675  EXPECT_FALSE(t.withException([](std::logic_error&) {}));
676  }
677 
678  {
679  auto const t = Try<bool>(true);
680  EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
681  EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
682  EXPECT_FALSE(t.withException([](std::runtime_error const&) {}));
683  EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
684  }
685 
686  {
687  auto const t = Try<bool>(ew);
688  EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
689  EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
690  EXPECT_TRUE(t.withException([](std::runtime_error const&) {}));
691  EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
692  }
693 
694  {
695  auto const t = Try<void>();
696  EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
697  EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
698  EXPECT_FALSE(t.withException([](std::runtime_error const&) {}));
699  EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
700  }
701 
702  {
703  auto const t = Try<void>(ew);
704  EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
705  EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
706  EXPECT_TRUE(t.withException([](std::runtime_error const&) {}));
707  EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
708  }
709 }
710 
711 TEST(Try, TestUnwrapTuple) {
712  auto original = std::make_tuple(Try<int>{1}, Try<int>{2});
713  EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(original));
716 }
717 
718 TEST(Try, TestUnwrapPair) {
719  auto original = std::make_pair(Try<int>{1}, Try<int>{2});
720  EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(original));
721  EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(folly::copy(original)));
722  EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(folly::as_const(original)));
723 }
724 
725 TEST(Try, TestUnwrapForward) {
726  using UPtr_t = std::unique_ptr<int>;
727  auto original = std::make_tuple(Try<UPtr_t>{std::make_unique<int>(1)});
728  auto unwrapped = unwrapTryTuple(std::move(original));
729  EXPECT_EQ(*std::get<0>(unwrapped), 1);
730 }
Definition: InvokeTest.cpp:58
void * ptr
T * tryEmplace(Try< T > &t, Args &&...args) noexcept
Definition: Try-inl.h:249
bool hasException() const
Definition: Try.h:463
#define CR
Definition: http_parser.c:395
auto v
std::unique_ptr< int > A
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
T & emplace(Args &&...args) noexcept(std::is_nothrow_constructible< T, Args &&... >::value)
Definition: Try-inl.h:121
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
const int x
double val
Definition: String.cpp:273
folly::std T
static void basic()
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
in_place_tag in_place(in_place_tag={})
Definition: Utility.h:235
requires E e noexcept(noexcept(s.error(std::move(e))))
in_place_tag(&)(in_place_tag) in_place_t
Definition: Utility.h:229
tuple make_tuple()
Definition: gtest-tuple.h:675
T * tryEmplaceWith(Try< T > &t, Func &&func) noexcept
Definition: Try-inl.h:266
constexpr T const & as_const(T &t) noexcept
Definition: Utility.h:96
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
Definition: Utility.h:72
bool hasException() const
Definition: Try.h:248
void emplace() noexcept
Definition: Try.h:423
exception_wrapper & emplaceException(Args &&...args) noexcept(std::is_nothrow_constructible< exception_wrapper, Args &&... >::value)
Definition: Try-inl.h:203
char a
std::exception * tryGetExceptionObject()
Definition: Try.h:292
static const char *const value
Definition: Conv.cpp:50
Definition: Try.h:51
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
bool hasValue() const
Definition: Try.h:242
std::enable_if< !std::is_same< invoke_result_t< F >, void >::value, Try< invoke_result_t< F > > >::type makeTryWith(F &&f)
Definition: Try-inl.h:223
std::atomic< int > counter
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
T & value()&
Definition: Try-inl.h:140
folly::detail::CompressionCounter * counter_
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
int x_
TEST(SequencedExecutor, CPUThreadPoolExecutor)
auto unwrapTryTuple(Tuple &&instance)
Definition: Try-inl.h:320
bool hasValue() const
Definition: Try.h:459
static E * get_exception(std::exception_ptr eptr)
Definition: TryTest.cpp:541