Detect identity conversion in toDynamic
[folly.git] / folly / test / FunctionTest.cpp
index 7c5159c9ae0873f28ac1b8e5dd209fefbbb435a6..e9ac94302326993c3fdc5ab4b4f32c5ae649a590 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  */
 
+#include <array>
 #include <cstdarg>
 
 #include <folly/Function.h>
 
 #include <folly/Memory.h>
-#include <gtest/gtest.h>
+#include <folly/portability/GTest.h>
 
 using folly::Function;
 
@@ -49,6 +50,10 @@ struct Functor {
     return oldvalue;
   }
 };
+
+template <typename Ret, typename... Args>
+void deduceArgs(Function<Ret(Args...)>) {}
+
 } // namespace
 
 // TEST =====================================================================
@@ -96,13 +101,15 @@ TEST(Function, Emptiness_T) {
   Function<int(int)> g([](int x) { return x + 1; });
   EXPECT_NE(g, nullptr);
   EXPECT_NE(nullptr, g);
-  EXPECT_TRUE(g);
+  // Explicitly convert to bool to work around
+  // https://github.com/google/googletest/issues/429
+  EXPECT_TRUE(bool(g));
   EXPECT_EQ(100, g(99));
 
   Function<int(int)> h(&func_int_int_add_25);
   EXPECT_NE(h, nullptr);
   EXPECT_NE(nullptr, h);
-  EXPECT_TRUE(h);
+  EXPECT_TRUE(bool(h));
   EXPECT_EQ(125, h(100));
 
   h = {};
@@ -190,8 +197,10 @@ TEST(Function, NonCopyableLambda) {
   auto unique_ptr_int = folly::make_unique<int>(900);
   EXPECT_EQ(900, *unique_ptr_int);
 
-  char fooData[64] = {0};
-  EXPECT_EQ(0, fooData[0]); // suppress gcc warning about fooData not being used
+  struct {
+    char data[64];
+  } fooData = {{0}};
+  (void)fooData; // suppress gcc warning about fooData not being used
 
   auto functor = std::bind(
       [fooData](std::unique_ptr<int>& up) mutable { return ++*up; },
@@ -813,6 +822,80 @@ TEST(Function, asStdFunction_args_const) {
   EXPECT_EQ(1, i);
 }
 
+// TEST =====================================================================
+// asSharedProxy_*
+
+TEST(Function, asSharedProxy_void) {
+  int i = 0;
+  folly::Function<void()> f = [&i] { ++i; };
+  auto sp = std::move(f).asSharedProxy();
+  auto spcopy = sp;
+  sp();
+  EXPECT_EQ(1, i);
+  spcopy();
+  EXPECT_EQ(2, i);
+}
+
+TEST(Function, asSharedProxy_void_const) {
+  int i = 0;
+  folly::Function<void() const> f = [&i] { ++i; };
+  auto sp = std::move(f).asSharedProxy();
+  auto spcopy = sp;
+  sp();
+  EXPECT_EQ(1, i);
+  spcopy();
+  EXPECT_EQ(2, i);
+}
+
+TEST(Function, asSharedProxy_return) {
+  folly::Function<int()> f = [i = 0]() mutable {
+    ++i;
+    return i;
+  };
+  auto sp = std::move(f).asSharedProxy();
+  auto spcopy = sp;
+  EXPECT_EQ(1, sp());
+  EXPECT_EQ(2, spcopy());
+}
+
+TEST(Function, asSharedProxy_return_const) {
+  int i = 0;
+  folly::Function<int() const> f = [&i] {
+    ++i;
+    return i;
+  };
+  auto sp = std::move(f).asSharedProxy();
+  auto spcopy = sp;
+  EXPECT_EQ(1, sp());
+  EXPECT_EQ(2, spcopy());
+}
+
+TEST(Function, asSharedProxy_args) {
+  int i = 0;
+  folly::Function<int(int, int)> f = [&](int x, int y) mutable {
+    ++i;
+    return x + y * 2;
+  };
+  auto sp = std::move(f).asSharedProxy();
+  auto spcopy = sp;
+  EXPECT_EQ(120, sp(100, 10));
+  EXPECT_EQ(1, i);
+  EXPECT_EQ(120, spcopy(100, 10));
+  EXPECT_EQ(2, i);
+}
+
+TEST(Function, asSharedProxy_args_const) {
+  int i = 0;
+  folly::Function<int(int, int) const> f = [&i](int x, int y) {
+    ++i;
+    return x * 100 + y * 10 + i;
+  };
+  auto sp = std::move(f).asSharedProxy();
+  auto spcopy = sp;
+  EXPECT_EQ(561, sp(5, 6));
+  EXPECT_EQ(562, spcopy(5, 6));
+}
+
 TEST(Function, NoAllocatedMemoryAfterMove) {
   Functor<int, 100> foo;
 
@@ -847,5 +930,11 @@ TEST(Function, SelfMoveAssign) {
   Function<int()> f = [] { return 0; };
   Function<int()>& g = f;
   f = std::move(g);
-  EXPECT_TRUE(f);
+  EXPECT_TRUE(bool(f));
+}
+
+TEST(Function, DeducableArguments) {
+  deduceArgs(Function<void()>{[] {}});
+  deduceArgs(Function<void(int, float)>{[](int, float) {}});
+  deduceArgs(Function<int(int, float)>{[](int i, float) { return i; }});
 }