Use the GTest portability headers
[folly.git] / folly / futures / test / ViaTest.cpp
index 499d61d4159ae3b7c14e3d89336f514ef73bdc5c..765fdf6c74010f9b62127ab8bd5505f3b57c0a2e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2016 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 <gtest/gtest.h>
-
 #include <folly/futures/Future.h>
 #include <folly/futures/InlineExecutor.h>
 #include <folly/futures/ManualExecutor.h>
 #include <folly/futures/DrivableExecutor.h>
 #include <folly/Baton.h>
 #include <folly/MPMCQueue.h>
+#include <folly/portability/GTest.h>
 
 #include <thread>
 
@@ -31,7 +30,7 @@ struct ManualWaiter : public DrivableExecutor {
   explicit ManualWaiter(std::shared_ptr<ManualExecutor> ex) : ex(ex) {}
 
   void add(Func f) override {
-    ex->add(f);
+    ex->add(std::move(f));
   }
 
   void drive() override {
@@ -56,7 +55,7 @@ struct ViaFixture : public testing::Test {
       });
   }
 
-  ~ViaFixture() {
+  ~ViaFixture() override {
     done = true;
     eastExecutor->add([=]() { });
     t.join();
@@ -72,7 +71,7 @@ struct ViaFixture : public testing::Test {
   std::shared_ptr<ManualExecutor> eastExecutor;
   std::shared_ptr<ManualWaiter> waiter;
   InlineExecutor inlineExecutor;
-  bool done;
+  std::atomic<bool> done;
   std::thread t;
 };
 
@@ -124,14 +123,16 @@ TEST(Via, thenFunction) {
 
 TEST_F(ViaFixture, threadHops) {
   auto westThreadId = std::this_thread::get_id();
-  auto f = via(eastExecutor.get()).then([=](Try<void>&& t) {
-    EXPECT_NE(std::this_thread::get_id(), westThreadId);
-    return makeFuture<int>(1);
-  }).via(westExecutor.get()
-  ).then([=](Try<int>&& t) {
-    EXPECT_EQ(std::this_thread::get_id(), westThreadId);
-    return t.value();
-  });
+  auto f = via(eastExecutor.get())
+               .then([=](Try<Unit>&& /* t */) {
+                 EXPECT_NE(std::this_thread::get_id(), westThreadId);
+                 return makeFuture<int>(1);
+               })
+               .via(westExecutor.get())
+               .then([=](Try<int>&& t) {
+                 EXPECT_EQ(std::this_thread::get_id(), westThreadId);
+                 return t.value();
+               });
   EXPECT_EQ(f.getVia(waiter.get()), 1);
 }
 
@@ -189,9 +190,9 @@ TEST(Via, chain3) {
 }
 
 struct PriorityExecutor : public Executor {
-  void add(Func f) override {}
+  void add(Func /* f */) override {}
 
-  void addWithPriority(Func, int8_t priority) override {
+  void addWithPriority(Func f, int8_t priority) override {
     int mid = getNumPriorities() / 2;
     int p = priority < 0 ?
             std::max(0, mid + priority) :
@@ -205,6 +206,7 @@ struct PriorityExecutor : public Executor {
     } else if (p == 2) {
       count2++;
     }
+    f();
   }
 
   uint8_t getNumPriorities() const override {
@@ -282,7 +284,7 @@ TEST(Via, then2) {
 }
 
 TEST(Via, then2Variadic) {
-  struct Foo { bool a = false; void foo(Try<void>) { a = true; } };
+  struct Foo { bool a = false; void foo(Try<Unit>) { a = true; } };
   Foo f;
   ManualExecutor x;
   makeFuture().then(&x, &Foo::foo, &f);
@@ -291,6 +293,7 @@ TEST(Via, then2Variadic) {
   EXPECT_TRUE(f.a);
 }
 
+#ifndef __APPLE__ // TODO #7372389
 /// Simple executor that does work in another thread
 class ThreadExecutor : public Executor {
   folly::MPMCQueue<Func> funcs;
@@ -315,7 +318,7 @@ class ThreadExecutor : public Executor {
     worker = std::thread(std::bind(&ThreadExecutor::work, this));
   }
 
-  ~ThreadExecutor() {
+  ~ThreadExecutor() override {
     done = true;
     funcs.write([]{});
     worker.join();
@@ -339,9 +342,37 @@ TEST(Via, viaThenGetWasRacy) {
   EXPECT_EQ(42, *val);
 }
 
+TEST(Via, callbackRace) {
+  ThreadExecutor x;
+
+  auto fn = [&x]{
+    auto promises = std::make_shared<std::vector<Promise<Unit>>>(4);
+    std::vector<Future<Unit>> futures;
+
+    for (auto& p : *promises) {
+      futures.emplace_back(
+        p.getFuture()
+        .via(&x)
+        .then([](Try<Unit>&&){}));
+    }
+
+    x.waitForStartup();
+    x.add([promises]{
+      for (auto& p : *promises) {
+        p.setValue();
+      }
+    });
+
+    return collectAll(futures);
+  };
+
+  fn().wait();
+}
+#endif
+
 class DummyDrivableExecutor : public DrivableExecutor {
  public:
-  void add(Func f) override {}
+  void add(Func /* f */) override {}
   void drive() override { ran = true; }
   bool ran{false};
 };
@@ -394,16 +425,16 @@ TEST(Via, waitVia) {
 
 TEST(Via, viaRaces) {
   ManualExecutor x;
-  Promise<void> p;
+  Promise<Unit> p;
   auto tid = std::this_thread::get_id();
   bool done = false;
 
   std::thread t1([&] {
     p.getFuture()
       .via(&x)
-      .then([&](Try<void>&&) { EXPECT_EQ(tid, std::this_thread::get_id()); })
-      .then([&](Try<void>&&) { EXPECT_EQ(tid, std::this_thread::get_id()); })
-      .then([&](Try<void>&&) { done = true; });
+      .then([&](Try<Unit>&&) { EXPECT_EQ(tid, std::this_thread::get_id()); })
+      .then([&](Try<Unit>&&) { EXPECT_EQ(tid, std::this_thread::get_id()); })
+      .then([&](Try<Unit>&&) { done = true; });
   });
 
   std::thread t2([&] {
@@ -415,37 +446,10 @@ TEST(Via, viaRaces) {
   t2.join();
 }
 
-TEST(Via, callbackRace) {
-  ThreadExecutor x;
-
-  auto fn = [&x]{
-    auto promises = std::make_shared<std::vector<Promise<void>>>(4);
-    std::vector<Future<void>> futures;
-
-    for (auto& p : *promises) {
-      futures.emplace_back(
-        p.getFuture()
-        .via(&x)
-        .then([](Try<void>&&){}));
-    }
-
-    x.waitForStartup();
-    x.add([promises]{
-      for (auto& p : *promises) {
-        p.setValue();
-      }
-    });
-
-    return collectAll(futures);
-  };
-
-  fn().wait();
-}
-
 TEST(ViaFunc, liftsVoid) {
   ManualExecutor x;
   int count = 0;
-  Future<void> f = via(&x, [&]{ count++; });
+  Future<Unit> f = via(&x, [&]{ count++; });
 
   EXPECT_EQ(0, count);
   x.run();
@@ -490,3 +494,10 @@ TEST(ViaFunc, isSticky) {
   x.run();
   EXPECT_EQ(2, count);
 }
+
+TEST(ViaFunc, moveOnly) {
+  ManualExecutor x;
+  auto intp = folly::make_unique<int>(42);
+
+  EXPECT_EQ(42, via(&x, [intp = std::move(intp)] { return *intp; }).getVia(&x));
+}