+ /*
+ EXPECT_FALSE(cew.with_exception([&](std::runtime_error&) {}));
+ EXPECT_FALSE(cew.with_exception([&](int&) {}));
+ */
+}
+
+TEST(ExceptionWrapper, get_or_make_exception_ptr_test) {
+ int expected = 23;
+
+ // This works, and doesn't slice.
+ exception_wrapper ew = try_and_catch<std::exception, std::runtime_error>(
+ [=]() { throw IntException(expected); });
+ std::exception_ptr eptr = ew.to_exception_ptr();
+ EXPECT_THROW(std::rethrow_exception(eptr), IntException);
+
+ // I can try_and_catch a non-copyable base class. This will use
+ // std::exception_ptr internally.
+ exception_wrapper ew2 = try_and_catch<AbstractIntException>(
+ [=]() { throw IntException(expected); });
+ eptr = ew2.to_exception_ptr();
+ EXPECT_THROW(std::rethrow_exception(eptr), IntException);
+
+ // Test with const this.
+ const exception_wrapper& cew = ew;
+ eptr = cew.to_exception_ptr();
+ EXPECT_THROW(std::rethrow_exception(eptr), IntException);
+
+ // Test with empty ew.
+ exception_wrapper empty_ew;
+ eptr = empty_ew.to_exception_ptr();
+ EXPECT_FALSE(eptr);
+}
+
+TEST(ExceptionWrapper, with_exception_ptr_empty) {
+ auto ew = exception_wrapper(std::exception_ptr());
+ EXPECT_EQ(exception_wrapper::none(), ew.type());
+ EXPECT_FALSE(bool(ew));
+ EXPECT_EQ(nullptr, ew.get_exception());
+ EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+ EXPECT_EQ(nullptr, ew.get_object<int>());
+ EXPECT_FALSE(ew.has_exception_ptr());
+ EXPECT_EQ(nullptr, ew.to_exception_ptr());
+ EXPECT_FALSE(ew.has_exception_ptr());
+ EXPECT_EQ("", ew.class_name());
+ EXPECT_EQ("", ew.what());
+ EXPECT_FALSE(ew.is_compatible_with<std::exception>());
+ EXPECT_FALSE(ew.is_compatible_with<int>());
+ EXPECT_DEATH(ew.throw_exception(), "empty folly::exception_wrapper");
+}
+
+TEST(ExceptionWrapper, with_shared_ptr_test) {
+ auto ew = exception_wrapper(std::runtime_error("foo"));
+ EXPECT_TRUE(bool(ew));
+ EXPECT_EQ(typeid(std::runtime_error), ew.type());
+ EXPECT_NE(nullptr, ew.get_exception());
+ EXPECT_NE(nullptr, ew.get_object<std::exception>());
+ EXPECT_EQ(nullptr, ew.get_object<int>());
+ EXPECT_FALSE(ew.has_exception_ptr());
+ EXPECT_NE(nullptr, ew.to_exception_ptr());
+ EXPECT_TRUE(ew.has_exception_ptr());
+ EXPECT_EQ("std::runtime_error", ew.class_name());
+ EXPECT_EQ("std::runtime_error: foo", ew.what());
+ EXPECT_TRUE(ew.is_compatible_with<std::exception>());
+ EXPECT_TRUE(ew.is_compatible_with<std::runtime_error>());
+ EXPECT_FALSE(ew.is_compatible_with<int>());
+ EXPECT_THROW(ew.throw_exception(), std::runtime_error);
+
+ exception_wrapper(std::move(ew));
+ EXPECT_FALSE(bool(ew));
+ EXPECT_EQ(exception_wrapper::none(), ew.type());
+ EXPECT_EQ(nullptr, ew.get_exception());
+ EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+ EXPECT_EQ(nullptr, ew.get_object<int>());
+ EXPECT_EQ(nullptr, ew.to_exception_ptr());
+ EXPECT_EQ("", ew.class_name());
+ EXPECT_EQ("", ew.what());
+ EXPECT_FALSE(ew.is_compatible_with<std::exception>());
+ EXPECT_FALSE(ew.is_compatible_with<std::runtime_error>());
+ EXPECT_FALSE(ew.is_compatible_with<int>());
+}
+
+TEST(ExceptionWrapper, with_exception_ptr_exn_test) {
+ auto ep = std::make_exception_ptr(std::runtime_error("foo"));
+ auto ew = exception_wrapper(ep, from_eptr<std::runtime_error>(ep));
+ EXPECT_TRUE(bool(ew));
+ EXPECT_EQ(typeid(std::runtime_error), ew.type());
+ EXPECT_NE(nullptr, ew.get_exception());
+ EXPECT_NE(nullptr, ew.get_object<std::exception>());
+ EXPECT_EQ(nullptr, ew.get_object<int>());
+ EXPECT_TRUE(ew.has_exception_ptr());
+ EXPECT_EQ(ep, ew.to_exception_ptr());
+ EXPECT_TRUE(ew.has_exception_ptr());
+ EXPECT_EQ("std::runtime_error", ew.class_name());
+ EXPECT_EQ("std::runtime_error: foo", ew.what());
+ EXPECT_TRUE(ew.is_compatible_with<std::exception>());
+ EXPECT_TRUE(ew.is_compatible_with<std::runtime_error>());
+ EXPECT_FALSE(ew.is_compatible_with<int>());
+ EXPECT_THROW(ew.throw_exception(), std::runtime_error);
+
+ exception_wrapper(std::move(ew));
+ EXPECT_FALSE(bool(ew));
+ EXPECT_EQ(exception_wrapper::none(), ew.type());
+ EXPECT_EQ(nullptr, ew.get_exception());
+ EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+ EXPECT_EQ(nullptr, ew.get_object<int>());
+ EXPECT_EQ(nullptr, ew.to_exception_ptr());
+ EXPECT_EQ("", ew.class_name());
+ EXPECT_EQ("", ew.what());
+ EXPECT_FALSE(ew.is_compatible_with<std::exception>());
+ EXPECT_FALSE(ew.is_compatible_with<std::runtime_error>());
+ EXPECT_FALSE(ew.is_compatible_with<int>());
+}
+
+TEST(ExceptionWrapper, with_exception_ptr_any_test) {
+ auto ep = std::make_exception_ptr<int>(12);
+ auto ew = exception_wrapper(ep, from_eptr<int>(ep));
+ EXPECT_TRUE(bool(ew));
+ EXPECT_EQ(nullptr, ew.get_exception());
+ EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+ EXPECT_NE(nullptr, ew.get_object<int>());
+ EXPECT_TRUE(ew.has_exception_ptr());
+ EXPECT_EQ(ep, ew.to_exception_ptr());
+ EXPECT_TRUE(ew.has_exception_ptr());
+ EXPECT_EQ("int", ew.class_name());
+ EXPECT_EQ("int", ew.what());
+ EXPECT_FALSE(ew.is_compatible_with<std::exception>());
+ EXPECT_FALSE(ew.is_compatible_with<std::runtime_error>());
+ EXPECT_TRUE(ew.is_compatible_with<int>());
+ EXPECT_THROW(ew.throw_exception(), int);
+
+ exception_wrapper(std::move(ew));
+ EXPECT_FALSE(bool(ew));
+ EXPECT_EQ(nullptr, ew.get_exception());
+ EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+ EXPECT_EQ(nullptr, ew.get_object<int>());
+ EXPECT_EQ(nullptr, ew.to_exception_ptr());
+ EXPECT_FALSE(ew.has_exception_ptr());
+ EXPECT_EQ("", ew.class_name());
+ EXPECT_EQ("", ew.what());
+ EXPECT_FALSE(ew.is_compatible_with<std::exception>());
+ EXPECT_FALSE(ew.is_compatible_with<std::runtime_error>());
+ EXPECT_FALSE(ew.is_compatible_with<int>());
+}
+
+TEST(ExceptionWrapper, with_non_std_exception_test) {
+ auto ew = exception_wrapper(folly::in_place, 42);
+ EXPECT_TRUE(bool(ew));
+ EXPECT_EQ(nullptr, ew.get_exception());
+ EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+ EXPECT_NE(nullptr, ew.get_object<int>());
+ EXPECT_FALSE(ew.has_exception_ptr());
+ EXPECT_EQ("int", ew.class_name());
+ EXPECT_EQ("int", ew.what());
+ EXPECT_NE(nullptr, ew.to_exception_ptr());
+ EXPECT_TRUE(ew.has_exception_ptr());
+ EXPECT_EQ("int", ew.class_name());
+ EXPECT_EQ("int", ew.what());
+ EXPECT_FALSE(ew.is_compatible_with<std::exception>());
+ EXPECT_FALSE(ew.is_compatible_with<std::runtime_error>());
+ EXPECT_TRUE(ew.is_compatible_with<int>());
+ EXPECT_THROW(ew.throw_exception(), int);
+
+ exception_wrapper(std::move(ew));
+ EXPECT_FALSE(bool(ew));
+ EXPECT_EQ(nullptr, ew.get_exception());
+ EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+ EXPECT_EQ(nullptr, ew.get_object<int>());
+ EXPECT_EQ(nullptr, ew.to_exception_ptr());
+ EXPECT_FALSE(ew.has_exception_ptr());
+ EXPECT_EQ("", ew.class_name());
+ EXPECT_EQ("", ew.what());
+ EXPECT_FALSE(ew.is_compatible_with<std::exception>());
+ EXPECT_FALSE(ew.is_compatible_with<std::runtime_error>());
+ EXPECT_FALSE(ew.is_compatible_with<int>());
+}
+
+TEST(ExceptionWrapper, with_exception_ptr_any_nil_test) {
+ auto ep = std::make_exception_ptr<int>(12);
+ auto ew = exception_wrapper(ep); // concrete type is erased
+ EXPECT_TRUE(bool(ew));
+ EXPECT_EQ(nullptr, ew.get_exception());
+ EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+ EXPECT_NE(nullptr, ew.get_object<int>());
+ EXPECT_EQ(ep, ew.to_exception_ptr());
+ EXPECT_EQ("<unknown exception>", ew.class_name()); // because concrete type is
+ // erased
+ EXPECT_EQ("<unknown exception>", ew.what());
+ EXPECT_FALSE(ew.is_compatible_with<std::exception>());
+ EXPECT_FALSE(ew.is_compatible_with<std::runtime_error>());
+ EXPECT_TRUE(ew.is_compatible_with<int>());
+ EXPECT_THROW(ew.throw_exception(), int);
+
+ exception_wrapper(std::move(ew));
+ EXPECT_FALSE(bool(ew));
+ EXPECT_EQ(nullptr, ew.get_exception());
+ EXPECT_EQ(nullptr, ew.get_object<std::exception>());
+ EXPECT_EQ(nullptr, ew.get_object<int>());
+ EXPECT_EQ(nullptr, ew.to_exception_ptr());
+ EXPECT_EQ("", ew.class_name());
+ EXPECT_EQ("", ew.what());
+ EXPECT_FALSE(ew.is_compatible_with<std::exception>());
+ EXPECT_FALSE(ew.is_compatible_with<std::runtime_error>());
+ EXPECT_FALSE(ew.is_compatible_with<int>());
+}
+
+TEST(ExceptionWrapper, with_exception_deduction) {
+ auto ew = make_exception_wrapper<std::runtime_error>("hi");
+ EXPECT_TRUE(ew.with_exception([](std::runtime_error&) {}));
+ EXPECT_TRUE(ew.with_exception([](std::exception&) {}));
+ EXPECT_FALSE(ew.with_exception([](std::logic_error&) {}));
+}
+
+TEST(ExceptionWrapper, with_exception_deduction_exn_const) {
+ auto ew = make_exception_wrapper<std::runtime_error>("hi");
+ EXPECT_TRUE(ew.with_exception([](const std::runtime_error&) {}));
+ EXPECT_TRUE(ew.with_exception([](const std::exception&) {}));
+ EXPECT_FALSE(ew.with_exception([](const std::logic_error&) {}));
+}
+
+TEST(ExceptionWrapper, with_exception_deduction_wrap_const_exn_const) {
+ const auto cew = make_exception_wrapper<std::runtime_error>("hi");
+ EXPECT_TRUE(cew.with_exception([](const std::runtime_error&) {}));
+ EXPECT_TRUE(cew.with_exception([](const std::exception&) {}));
+ EXPECT_FALSE(cew.with_exception([](const std::logic_error&) {}));
+}
+
+TEST(ExceptionWrapper, with_exception_deduction_returning) {
+ auto ew = make_exception_wrapper<std::runtime_error>("hi");
+ EXPECT_TRUE(ew.with_exception([](std::runtime_error&) { return 3; }));
+ EXPECT_TRUE(ew.with_exception([](std::exception&) { return "hello"; }));
+ EXPECT_FALSE(ew.with_exception([](std::logic_error&) { return nullptr; }));
+}
+
+namespace {
+template <typename T>
+T& r_to_l(T v) { return std::ref(v); }
+}
+
+TEST(ExceptionWrapper, with_exception_deduction_functor_lvalue) {
+ auto ew = make_exception_wrapper<std::runtime_error>("hi");
+ EXPECT_TRUE(ew.with_exception(r_to_l([](std::runtime_error&) {})));
+ EXPECT_TRUE(ew.with_exception(r_to_l([](std::exception&) {})));
+ EXPECT_FALSE(ew.with_exception(r_to_l([](std::logic_error&) {})));