Fix copyright lines
[folly.git] / folly / futures / test / TimekeeperTest.cpp
index f9db640db52f04894194ebe1c7d45188f381678a..3c5464a4a22f6b5db50adb6a8bb4f963d9c4cffe 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2014-present Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <gtest/gtest.h>
 
 #include <folly/futures/Timekeeper.h>
-#include <unistd.h>
+#include <folly/Singleton.h>
+#include <folly/futures/ThreadWheelTimekeeper.h>
+#include <folly/portability/GTest.h>
 
 using namespace folly;
-using namespace std::chrono;
-using folly::Timekeeper;
-using Duration = folly::Duration;
+using std::chrono::milliseconds;
 
+std::chrono::milliseconds const zero_ms(0);
 std::chrono::milliseconds const one_ms(1);
 std::chrono::milliseconds const awhile(10);
 std::chrono::seconds const too_long(10);
@@ -36,12 +36,10 @@ struct TimekeeperFixture : public testing::Test {
     timeLord_(folly::detail::getTimekeeperSingleton())
   {}
 
-  Timekeeper* timeLord_;
+  std::shared_ptr<Timekeeper> timeLord_;
 };
 
 TEST_F(TimekeeperFixture, after) {
-  Duration waited(0);
-
   auto t1 = now();
   auto f = timeLord_->after(awhile);
   EXPECT_FALSE(f.isReady());
@@ -53,8 +51,9 @@ TEST_F(TimekeeperFixture, after) {
 
 TEST(Timekeeper, futureGet) {
   Promise<int> p;
-  std::thread([&]{ p.setValue(42); }).detach();
+  auto t = std::thread([&]{ p.setValue(42); });
   EXPECT_EQ(42, p.getFuture().get());
+  t.join();
 }
 
 TEST(Timekeeper, futureGetBeforeTimeout) {
@@ -66,13 +65,13 @@ TEST(Timekeeper, futureGetBeforeTimeout) {
   // runs it by hand they're not sitting there forever wondering why it's
   // blocked, and get a useful error message instead. If it does get flaky,
   // empirically increase the timeout to the point where it's very improbable.
-  EXPECT_EQ(42, p.getFuture().get(seconds(2)));
+  EXPECT_EQ(42, p.getFuture().get(std::chrono::seconds(2)));
   t.join();
 }
 
 TEST(Timekeeper, futureGetTimeout) {
   Promise<int> p;
-  EXPECT_THROW(p.getFuture().get(Duration(1)), folly::TimedOut);
+  EXPECT_THROW(p.getFuture().get(one_ms), folly::TimedOut);
 }
 
 TEST(Timekeeper, futureSleep) {
@@ -81,6 +80,24 @@ TEST(Timekeeper, futureSleep) {
   EXPECT_GE(now() - t1, one_ms);
 }
 
+TEST(Timekeeper, futureSleepHandlesNullTimekeeperSingleton) {
+  Singleton<ThreadWheelTimekeeper>::make_mock([] { return nullptr; });
+  SCOPE_EXIT {
+    Singleton<ThreadWheelTimekeeper>::make_mock();
+  };
+  EXPECT_THROW(futures::sleep(one_ms).get(), NoTimekeeper);
+}
+
+TEST(Timekeeper, futureWithinHandlesNullTimekeeperSingleton) {
+  Singleton<ThreadWheelTimekeeper>::make_mock([] { return nullptr; });
+  SCOPE_EXIT {
+    Singleton<ThreadWheelTimekeeper>::make_mock();
+  };
+  Promise<int> p;
+  auto f = p.getFuture().within(one_ms);
+  EXPECT_THROW(f.get(), NoTimekeeper);
+}
+
 TEST(Timekeeper, futureDelayed) {
   auto t1 = now();
   auto dur = makeFuture()
@@ -123,34 +140,42 @@ TEST(Timekeeper, futureWithinVoidSpecialization) {
 }
 
 TEST(Timekeeper, futureWithinException) {
-  Promise<void> p;
+  Promise<Unit> p;
   auto f = p.getFuture().within(awhile, std::runtime_error("expected"));
   EXPECT_THROW(f.get(), std::runtime_error);
 }
 
 TEST(Timekeeper, onTimeout) {
   bool flag = false;
-  makeFuture(42).delayed(one_ms)
-    .onTimeout(Duration(0), [&]{ flag = true; return -1; })
+  makeFuture(42).delayed(10 * one_ms)
+    .onTimeout(zero_ms, [&]{ flag = true; return -1; })
     .get();
   EXPECT_TRUE(flag);
 }
 
+TEST(Timekeeper, onTimeoutComplete) {
+  bool flag = false;
+  makeFuture(42)
+    .onTimeout(zero_ms, [&]{ flag = true; return -1; })
+    .get();
+  EXPECT_FALSE(flag);
+}
+
 TEST(Timekeeper, onTimeoutReturnsFuture) {
   bool flag = false;
-  makeFuture(42).delayed(one_ms)
-    .onTimeout(Duration(0), [&]{ flag = true; return makeFuture(-1); })
+  makeFuture(42).delayed(10 * one_ms)
+    .onTimeout(zero_ms, [&]{ flag = true; return makeFuture(-1); })
     .get();
   EXPECT_TRUE(flag);
 }
 
 TEST(Timekeeper, onTimeoutVoid) {
   makeFuture().delayed(one_ms)
-    .onTimeout(Duration(0), [&]{
+    .onTimeout(zero_ms, [&]{
      });
   makeFuture().delayed(one_ms)
-    .onTimeout(Duration(0), [&]{
-       return makeFuture<void>(std::runtime_error("expected"));
+    .onTimeout(zero_ms, [&]{
+       return makeFuture<Unit>(std::runtime_error("expected"));
      });
   // just testing compilation here
 }
@@ -162,7 +187,7 @@ TEST(Timekeeper, interruptDoesntCrash) {
 
 TEST(Timekeeper, chainedInterruptTest) {
   bool test = false;
-  auto f = futures::sleep(Duration(100)).then([&](){
+  auto f = futures::sleep(milliseconds(100)).then([&](){
     test = true;
   });
   f.cancel();
@@ -180,20 +205,36 @@ TEST(Timekeeper, executor) {
     std::atomic<int> count{0};
   };
 
-  auto f = makeFuture();
+  Promise<Unit> p;
   ExecutorTester tester;
-  f.via(&tester).within(std::chrono::milliseconds(1)).then([&](){}).wait();
+  auto f = p.getFuture().via(&tester).within(one_ms).then([&](){});
+  p.setValue();
+  f.wait();
   EXPECT_EQ(2, tester.count);
 }
+
 // TODO(5921764)
 /*
 TEST(Timekeeper, onTimeoutPropagates) {
   bool flag = false;
   EXPECT_THROW(
     makeFuture(42).delayed(one_ms)
-      .onTimeout(Duration(0), [&]{ flag = true; })
+      .onTimeout(zero_ms, [&]{ flag = true; })
       .get(),
     TimedOut);
   EXPECT_TRUE(flag);
 }
 */
+
+TEST_F(TimekeeperFixture, atBeforeNow) {
+  auto f = timeLord_->at(now() - too_long);
+  EXPECT_TRUE(f.isReady());
+  EXPECT_FALSE(f.hasException());
+}
+
+TEST_F(TimekeeperFixture, howToCastDuration) {
+  // I'm not sure whether this rounds up or down but it's irrelevant for the
+  // purpose of this example.
+  auto f = timeLord_->after(std::chrono::duration_cast<Duration>(
+      std::chrono::nanoseconds(1)));
+}