ThreadLocalDetail: fix bug just introduced w/ recent change to constexpr-ctor style...
[folly.git] / folly / test / ExceptionWrapperTest.cpp
index 785ff13db5cdc3fb98fc651df0b3418efa0d59db..71a91599e4c5e0ba5f6eec1f62beed448222e5e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
 #include <stdexcept>
 #include <folly/ExceptionWrapper.h>
 #include <folly/Conv.h>
+#include <folly/Portability.h>
 
 using namespace folly;
 
@@ -139,8 +140,8 @@ public:
   explicit IntException(int i)
     : i_(i) {}
 
-  virtual int getInt() const { return i_; }
-  virtual const char* what() const noexcept override {
+  int getInt() const override { return i_; }
+  const char* what() const noexcept override {
     what_ = folly::to<std::string>("int == ", i_);
     return what_.c_str();
   }
@@ -161,7 +162,7 @@ TEST(ExceptionWrapper, with_exception_test) {
   EXPECT_TRUE(bool(ew));
   EXPECT_EQ(ew.what(), "IntException: int == 23");
   EXPECT_EQ(ew.class_name(), "IntException");
-  ew.with_exception<IntException>([&](const IntException& ie) {
+  ew.with_exception([&](const IntException& ie) {
       EXPECT_EQ(ie.getInt(), expected);
     });
 
@@ -174,27 +175,67 @@ TEST(ExceptionWrapper, with_exception_test) {
   EXPECT_TRUE(bool(ew2));
   EXPECT_EQ(ew2.what(), "IntException: int == 23");
   EXPECT_EQ(ew2.class_name(), "IntException");
-  ew2.with_exception<AbstractIntException>([&](AbstractIntException& ie) {
+  ew2.with_exception([&](AbstractIntException& ie) {
       EXPECT_EQ(ie.getInt(), expected);
-      EXPECT_EQ(typeid(ie), typeid(IntException));
+      EXPECT_TRUE(dynamic_cast<IntException*>(&ie));
     });
 
   // Test with const this.  If this compiles and does not crash due to
   // infinite loop when it runs, it succeeds.
   const exception_wrapper& cew = ew;
-  cew.with_exception<IntException>([&](const IntException& ie) {
+  cew.with_exception([&](const IntException& ie) {
       SUCCEED();
     });
 
   // This won't even compile.  You can't use a function which takes a
   // non-const reference with a const exception_wrapper.
 /*
-  cew.with_exception<IntException>([&](IntException& ie) {
+  cew.with_exception([&](IntException& ie) {
       SUCCEED();
     });
 */
 }
 
+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&) {})));
+}
+
 TEST(ExceptionWrapper, non_std_exception_test) {
   int expected = 17;
 
@@ -210,7 +251,27 @@ TEST(ExceptionWrapper, non_std_exception_test) {
   // access their value is to explicity rethrow and catch it.
   try {
     ew.throwException();
-  } catch (int& i) {
+  } catch /* nolint */ (int& i) {
     EXPECT_EQ(i, expected);
   }
 }
+
+
+TEST(ExceptionWrapper, exceptionStr) {
+  auto ew = make_exception_wrapper<std::runtime_error>("argh");
+  EXPECT_EQ("std::runtime_error: argh", exceptionStr(ew));
+}
+
+namespace {
+class TestException : public std::exception { };
+void testEW(const exception_wrapper& ew) {
+  EXPECT_THROW(ew.throwException(), TestException);
+}
+}  // namespace
+
+TEST(ExceptionWrapper, implicitConstruction) {
+  // Try with both lvalue and rvalue references
+  TestException e;
+  testEW(e);
+  testEW(TestException());
+}