+
+TEST(Try, exception) {
+ using ML = exception_wrapper&;
+ using MR = exception_wrapper&&;
+ using CL = exception_wrapper const&;
+ using CR = exception_wrapper const&&;
+
+ {
+ auto obj = Try<int>();
+ using ActualML = decltype(obj.exception());
+ using ActualMR = decltype(std::move(obj).exception());
+ using ActualCL = decltype(as_const(obj).exception());
+ using ActualCR = decltype(std::move(as_const(obj)).exception());
+ EXPECT_TRUE((std::is_same<ML, ActualML>::value));
+ EXPECT_TRUE((std::is_same<MR, ActualMR>::value));
+ EXPECT_TRUE((std::is_same<CL, ActualCL>::value));
+ EXPECT_TRUE((std::is_same<CR, ActualCR>::value));
+ }
+
+ {
+ auto obj = Try<int>(3);
+ EXPECT_THROW(obj.exception(), TryException);
+ EXPECT_THROW(std::move(obj).exception(), TryException);
+ EXPECT_THROW(as_const(obj).exception(), TryException);
+ EXPECT_THROW(std::move(as_const(obj)).exception(), TryException);
+ }
+
+ {
+ auto obj = Try<int>(make_exception_wrapper<int>(-3));
+ EXPECT_EQ(-3, *obj.exception().get_exception<int>());
+ EXPECT_EQ(-3, *std::move(obj).exception().get_exception<int>());
+ EXPECT_EQ(-3, *as_const(obj).exception().get_exception<int>());
+ EXPECT_EQ(-3, *std::move(as_const(obj)).exception().get_exception<int>());
+ }
+
+ {
+ auto obj = Try<void>();
+ using ActualML = decltype(obj.exception());
+ using ActualMR = decltype(std::move(obj).exception());
+ using ActualCL = decltype(as_const(obj).exception());
+ using ActualCR = decltype(std::move(as_const(obj)).exception());
+ EXPECT_TRUE((std::is_same<ML, ActualML>::value));
+ EXPECT_TRUE((std::is_same<MR, ActualMR>::value));
+ EXPECT_TRUE((std::is_same<CL, ActualCL>::value));
+ EXPECT_TRUE((std::is_same<CR, ActualCR>::value));
+ }
+
+ {
+ auto obj = Try<void>();
+ EXPECT_THROW(obj.exception(), TryException);
+ EXPECT_THROW(std::move(obj).exception(), TryException);
+ EXPECT_THROW(as_const(obj).exception(), TryException);
+ EXPECT_THROW(std::move(as_const(obj)).exception(), TryException);
+ }
+
+ {
+ auto obj = Try<void>(make_exception_wrapper<int>(-3));
+ EXPECT_EQ(-3, *obj.exception().get_exception<int>());
+ EXPECT_EQ(-3, *std::move(obj).exception().get_exception<int>());
+ EXPECT_EQ(-3, *as_const(obj).exception().get_exception<int>());
+ EXPECT_EQ(-3, *std::move(as_const(obj)).exception().get_exception<int>());
+ }
+}
+
+template <typename E>
+static E* get_exception(std::exception_ptr eptr) {
+ try {
+ std::rethrow_exception(eptr);
+ } catch (E& e) {
+ return &e;
+ } catch (...) {
+ return nullptr;
+ }
+}
+
+TEST(Try, tryGetExceptionObject) {
+ auto epexn = std::make_exception_ptr(std::range_error("oops"));
+ auto epnum = std::make_exception_ptr(17);
+
+ auto exn = CHECK_NOTNULL(get_exception<std::range_error>(epexn));
+ auto num = CHECK_NOTNULL(get_exception<int>(epnum));
+
+ {
+ auto t = Try<bool>(true);
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+ }
+
+ {
+ auto t = Try<bool>(exception_wrapper(epexn, *exn));
+ EXPECT_EQ(exn, t.tryGetExceptionObject());
+ EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+ }
+
+ {
+ auto t = Try<bool>(exception_wrapper(epnum, *num));
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+ EXPECT_EQ(num, t.tryGetExceptionObject<int>());
+ }
+
+ {
+ auto t = Try<void>();
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+ }
+
+ {
+ auto t = Try<void>(exception_wrapper(epexn, *exn));
+ EXPECT_EQ(exn, t.tryGetExceptionObject());
+ EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+ }
+
+ {
+ auto t = Try<void>(exception_wrapper(epnum, *num));
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+ EXPECT_EQ(num, t.tryGetExceptionObject<int>());
+ }
+
+ {
+ auto const t = Try<bool>(true);
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+ }
+
+ {
+ auto const t = Try<bool>(exception_wrapper(epexn, *exn));
+ EXPECT_EQ(exn, t.tryGetExceptionObject());
+ EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+ }
+
+ {
+ auto const t = Try<bool>(exception_wrapper(epnum, *num));
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+ EXPECT_EQ(num, t.tryGetExceptionObject<int>());
+ }
+
+ {
+ auto const t = Try<void>();
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+ }
+
+ {
+ auto const t = Try<void>(exception_wrapper(epexn, *exn));
+ EXPECT_EQ(exn, t.tryGetExceptionObject());
+ EXPECT_EQ(exn, t.tryGetExceptionObject<std::runtime_error>());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<int>());
+ }
+
+ {
+ auto const t = Try<void>(exception_wrapper(epnum, *num));
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject());
+ EXPECT_EQ(nullptr, t.tryGetExceptionObject<std::runtime_error>());
+ EXPECT_EQ(num, t.tryGetExceptionObject<int>());
+ }
+}
+
+TEST(Try, withException) {
+ auto ew = make_exception_wrapper<std::range_error>("oops");
+
+ {
+ auto t = Try<bool>(true);
+ EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
+ EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+ EXPECT_FALSE(t.withException([](std::runtime_error&) {}));
+ EXPECT_FALSE(t.withException([](std::logic_error&) {}));
+ }
+
+ {
+ auto t = Try<bool>(ew);
+ EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
+ EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+ EXPECT_TRUE(t.withException([](std::runtime_error&) {}));
+ EXPECT_FALSE(t.withException([](std::logic_error&) {}));
+ }
+
+ {
+ auto t = Try<void>();
+ EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
+ EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+ EXPECT_FALSE(t.withException([](std::runtime_error&) {}));
+ EXPECT_FALSE(t.withException([](std::logic_error&) {}));
+ }
+
+ {
+ auto t = Try<void>(ew);
+ EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
+ EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+ EXPECT_TRUE(t.withException([](std::runtime_error&) {}));
+ EXPECT_FALSE(t.withException([](std::logic_error&) {}));
+ }
+
+ {
+ auto const t = Try<bool>(true);
+ EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
+ EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+ EXPECT_FALSE(t.withException([](std::runtime_error const&) {}));
+ EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
+ }
+
+ {
+ auto const t = Try<bool>(ew);
+ EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
+ EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+ EXPECT_TRUE(t.withException([](std::runtime_error const&) {}));
+ EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
+ }
+
+ {
+ auto const t = Try<void>();
+ EXPECT_FALSE(t.withException<std::runtime_error>([](auto&) {}));
+ EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+ EXPECT_FALSE(t.withException([](std::runtime_error const&) {}));
+ EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
+ }
+
+ {
+ auto const t = Try<void>(ew);
+ EXPECT_TRUE(t.withException<std::runtime_error>([](auto&) {}));
+ EXPECT_FALSE(t.withException<std::logic_error>([](auto&) {}));
+ EXPECT_TRUE(t.withException([](std::runtime_error const&) {}));
+ EXPECT_FALSE(t.withException([](std::logic_error const&) {}));
+ }
+}
+
+TEST(Try, TestUnwrapTuple) {
+ auto original = std::make_tuple(Try<int>{1}, Try<int>{2});
+ EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(original));
+ EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(folly::copy(original)));
+ EXPECT_EQ(std::make_tuple(1, 2), unwrapTryTuple(folly::as_const(original)));
+}
+
+TEST(Try, TestUnwrapPair) {
+ auto original = std::make_pair(Try<int>{1}, Try<int>{2});
+ EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(original));
+ EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(folly::copy(original)));
+ EXPECT_EQ(std::make_pair(1, 2), unwrapTryTuple(folly::as_const(original)));
+}
+
+TEST(Try, TestUnwrapForward) {
+ using UPtr_t = std::unique_ptr<int>;
+ auto original = std::make_tuple(Try<UPtr_t>{std::make_unique<int>(1)});
+ auto unwrapped = unwrapTryTuple(std::move(original));
+ EXPECT_EQ(*std::get<0>(unwrapped), 1);
+}