TEST(Future, unwrap) {
  Promise<int> a;
  Promise<int> b;

  auto fa = a.getFuture();
  auto fb = b.getFuture();

  bool flag1 = false;
  bool flag2 = false;

  // do a, then do b, and get the result of a + b.
  Future<int> f = fa.then([&](Try<int>&& ta) {
    auto va = ta.value();
    flag1 = true;
    return fb.then([va, &flag2](Try<int>&& tb) {
      flag2 = true;
      return va + tb.value();
    });
  });

  EXPECT_FALSE(flag1);
  EXPECT_FALSE(flag2);
  EXPECT_FALSE(f.isReady());

  a.setValue(3);
  EXPECT_TRUE(flag1);
  EXPECT_FALSE(flag2);
  EXPECT_FALSE(f.isReady());

  b.setValue(4);
  EXPECT_TRUE(flag1);
  EXPECT_TRUE(flag2);
  EXPECT_EQ(7, f.value());
}
Beispiel #2
0
void test_promise() {
  Promise<bool> p;

  auto f = p.getFuture();
  try {
    p.getFuture();
    ok(false, "should throw");
  } catch (const std::logic_error& exc) {
    ok(!strcmp(exc.what(), "Future already obtained"), "can't getFuture twice");
  }
  ok(!f.isReady(), "not yet ready");

  p.setValue(true);
  try {
    p.setValue(false);
    ok(false, "should throw");
  } catch (const std::logic_error& exc) {
    ok(!strcmp(exc.what(), "Promise already fulfilled"),
       "can't setValue twice");
  }

  ok(f.isReady(), "now ready");
  ok(f.get() == true, "got our true value");

  Promise<std::string> s;
  s.setException(std::make_exception_ptr(std::runtime_error("boo")));
  auto f2 = s.getFuture();
  ok(f2.result().hasError(), "holds an error");
  try {
    f2.get();
  } catch (const std::runtime_error& exc) {
    ok(!strcmp(exc.what(), "boo"), "has boo string");
  }
}
Beispiel #3
0
TEST(Collect, collectVariadicWithException) {
  Promise<bool> pb;
  Promise<int> pi;
  Future<bool> fb = pb.getFuture();
  Future<int> fi = pi.getFuture();
  auto f = collect(std::move(fb), std::move(fi));
  pb.setValue(true);
  EXPECT_FALSE(f.isReady());
  pi.setException(eggs);
  EXPECT_TRUE(f.isReady());
  EXPECT_TRUE(f.getTry().hasException());
  EXPECT_THROW(f.get(), eggs_t);
}
Beispiel #4
0
TEST(Promise, setWith) {
    {
        Promise<int> p;
        auto f = p.getFuture();
        p.setWith([] { return 42; });
        EXPECT_EQ(42, f.value());
    }
    {
        Promise<int> p;
        auto f = p.getFuture();
        p.setWith([]() -> int { throw eggs; });
        EXPECT_THROW(f.value(), eggs_t);
    }
}
TEST(Future, finishBigLambda) {
  auto x = std::make_shared<int>(0);

  // bulk_data, to be captured in the lambda passed to Future::then.
  // This is meant to force that the lambda can't be stored inside
  // the Future object.
  std::array<char, sizeof(detail::Core<int>)> bulk_data = {0};

  // suppress gcc warning about bulk_data not being used
  EXPECT_EQ(bulk_data[0], 0);

  Promise<int> p;
  auto f = p.getFuture().then([x, bulk_data](Try<int>&& t) { *x = t.value(); });

  // The callback hasn't executed
  EXPECT_EQ(0, *x);

  // The callback has a reference to x
  EXPECT_EQ(2, x.use_count());

  p.setValue(42);

  // the callback has executed
  EXPECT_EQ(42, *x);

  // the callback has been destructed
  // and has released its reference to x
  EXPECT_EQ(1, x.use_count());
}
TEST(Future, isReady) {
  Promise<int> p;
  auto f = p.getFuture();
  EXPECT_FALSE(f.isReady());
  p.setValue(42);
  EXPECT_TRUE(f.isReady());
  }
TEST(Future, toUnitWhileInProgress) {
  Promise<int> p;
  Future<Unit> fu = p.getFuture().unit();
  EXPECT_FALSE(fu.isReady());
  p.setValue(42);
  EXPECT_TRUE(fu.isReady());
}
Beispiel #8
0
TEST(Interrupt, interruptThenHandle) {
  Promise<int> p;
  bool flag = false;
  p.getFuture().cancel();
  p.setInterruptHandler([&](const exception_wrapper& /* e */) { flag = true; });
  EXPECT_TRUE(flag);
}
Beispiel #9
0
TEST(Interrupt, cancel) {
  Promise<Unit> p;
  p.setInterruptHandler([&](const exception_wrapper& e) {
    EXPECT_THROW(e.throw_exception(), FutureCancellation);
  });
  p.getFuture().cancel();
}
Beispiel #10
0
TEST(Wait, wait) {
  Promise<int> p;
  Future<int> f = p.getFuture();
  std::atomic<bool> flag{false};
  std::atomic<int> result{1};
  std::atomic<std::thread::id> id;

  std::thread t([&](Future<int>&& tf){
      auto n = tf.then([&](Try<int> && t) {
          id = std::this_thread::get_id();
          return t.value();
        });
      flag = true;
      result.store(n.wait().value());
    },
    std::move(f)
    );
  while(!flag){}
  EXPECT_EQ(result.load(), 1);
  p.setValue(42);
  t.join();
  // validate that the callback ended up executing in this thread, which
  // is more to ensure that this test actually tests what it should
  EXPECT_EQ(id, std::this_thread::get_id());
  EXPECT_EQ(result.load(), 42);
}
TEST(Future, thenTry) {
  bool flag = false;

  makeFuture<int>(42).then([&](Try<int>&& t) {
                              flag = true;
                              EXPECT_EQ(42, t.value());
                            });
  EXPECT_TRUE(flag); flag = false;

  makeFuture<int>(42)
    .then([](Try<int>&& t) { return t.value(); })
    .then([&](Try<int>&& t) { flag = true; EXPECT_EQ(42, t.value()); });
  EXPECT_TRUE(flag); flag = false;

  makeFuture().then([&](Try<Unit>&& t) { flag = true; t.value(); });
  EXPECT_TRUE(flag); flag = false;

  Promise<Unit> p;
  auto f = p.getFuture().then([&](Try<Unit>&& /* t */) { flag = true; });
  EXPECT_FALSE(flag);
  EXPECT_FALSE(f.isReady());
  p.setValue();
  EXPECT_TRUE(flag);
  EXPECT_TRUE(f.isReady());
}
Beispiel #12
0
TEST(Context, basic) {

  // Start a new context
  folly::RequestContextScopeGuard rctx;

  EXPECT_EQ(nullptr, RequestContext::get()->getContextData("test"));

  // Set some test data
  RequestContext::get()->setContextData(
    "test",
    std::unique_ptr<TestData>(new TestData(10)));

  // Start a future
  Promise<Unit> p;
  auto future = p.getFuture().then([&]{
    // Check that the context followed the future
    EXPECT_TRUE(RequestContext::get() != nullptr);
    auto a = dynamic_cast<TestData*>(
      RequestContext::get()->getContextData("test"));
    auto data = a->data_;
    EXPECT_EQ(10, data);
  });

  // Clear the context
  RequestContext::setContext(nullptr);

  EXPECT_EQ(nullptr, RequestContext::get()->getContextData("test"));

  // Fulfill the promise
  p.setValue();
}
TEST(NonCopyableLambda, unique_ptr) {
  Promise<Unit> promise;
  auto int_ptr = std::make_unique<int>(1);

  EXPECT_EQ(*int_ptr, 1);

  auto future = promise.getFuture().thenValue(std::bind(
      [](std::unique_ptr<int>& p, folly::Unit) mutable {
        ++*p;
        return std::move(p);
      },
      std::move(int_ptr),
      std::placeholders::_1));

  // The previous statement can be simplified in C++14:
  //  auto future =
  //      promise.getFuture().thenValue([int_ptr = std::move(int_ptr)](
  //          auto&&) mutable {
  //        ++*int_ptr;
  //        return std::move(int_ptr);
  //      });

  EXPECT_FALSE(future.isReady());
  promise.setValue();
  EXPECT_TRUE(future.isReady());
  EXPECT_EQ(*std::move(future).get(), 2);
}
Beispiel #14
0
TEST(Promise, isFulfilledWithFuture) {
    Promise<int> p;
    auto f = p.getFuture(); // so core_ will become null

    EXPECT_FALSE(p.isFulfilled());
    p.setValue(42); // after here
    EXPECT_TRUE(p.isFulfilled());
}
Beispiel #15
0
TEST(Interrupt, interruptAfterFulfilNoop) {
  Promise<Unit> p;
  bool flag = false;
  p.setInterruptHandler([&](const exception_wrapper& /* e */) { flag = true; });
  p.setValue();
  p.getFuture().cancel();
  EXPECT_FALSE(flag);
}
Beispiel #16
0
TEST(Interrupt, raise) {
  using eggs_t = std::runtime_error;
  Promise<Unit> p;
  p.setInterruptHandler([&](const exception_wrapper& e) {
    EXPECT_THROW(e.throw_exception(), eggs_t);
  });
  p.getFuture().raise(eggs_t("eggs"));
}
Beispiel #17
0
TEST(Timekeeper, futureWithinThrows) {
  Promise<int> p;
  auto f = p.getFuture()
    .within(one_ms)
    .onError([](TimedOut&) { return -1; });

  EXPECT_EQ(-1, f.get());
}
Beispiel #18
0
TEST(Collect, collectVariadic) {
  Promise<bool> pb;
  Promise<int> pi;
  Future<bool> fb = pb.getFuture();
  Future<int> fi = pi.getFuture();
  bool flag = false;
  collect(std::move(fb), std::move(fi))
    .then([&](std::tuple<bool, int> tup) {
      flag = true;
      EXPECT_EQ(std::get<0>(tup), true);
      EXPECT_EQ(std::get<1>(tup), 42);
    });
  pb.setValue(true);
  EXPECT_FALSE(flag);
  pi.setValue(42);
  EXPECT_TRUE(flag);
}
Beispiel #19
0
TEST(SemiFuture, DeferWithGetTimedGet) {
  std::atomic<int> innerResult{0};
  Promise<folly::Unit> p;
  auto f = p.getFuture();
  auto sf = std::move(f).semi().defer([&]() { innerResult = 17; });
  EXPECT_THROW(std::move(sf).get(std::chrono::milliseconds(100)), TimedOut);
  ASSERT_EQ(innerResult, 0);
}
Beispiel #20
0
TEST(Timekeeper, futureWithinFinishesInTime) {
  Promise<int> p;
  auto f = p.getFuture()
    .within(std::chrono::minutes(1))
    .onError([&](TimedOut&){ return -1; });
  p.setValue(42);

  EXPECT_EQ(42, f.get());
}
Beispiel #21
0
TEST(Interrupt, withinTimedOut) {
  Promise<int> p;
  Baton<> done;
  p.setInterruptHandler([&](const exception_wrapper& /* e */) { done.post(); });
  p.getFuture().within(std::chrono::milliseconds(1));
  // Give it 100ms to time out and call the interrupt handler
  auto t = std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
  EXPECT_TRUE(done.timed_wait(t));
}
Beispiel #22
0
TEST(Interrupt, secondInterruptNoop) {
  Promise<Unit> p;
  int count = 0;
  p.setInterruptHandler([&](const exception_wrapper& /* e */) { count++; });
  auto f = p.getFuture();
  f.cancel();
  f.cancel();
  EXPECT_EQ(1, count);
}
Beispiel #23
0
TEST(Promise, setException) {
    {
        Promise<Unit> p;
        auto f = p.getFuture();
        p.setException(eggs);
        EXPECT_THROW(f.value(), eggs_t);
    }
    {
        Promise<Unit> p;
        auto f = p.getFuture();
        try {
            throw eggs;
        } catch (...) {
            p.setException(exception_wrapper(std::current_exception()));
        }
        EXPECT_THROW(f.value(), eggs_t);
    }
}
Beispiel #24
0
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);
}
Beispiel #25
0
TEST(SemiFuture, DeferWithGetTimedWait) {
  Promise<folly::Unit> p;
  auto f = p.getFuture();
  auto sf = std::move(f).semi().defer([&]() { return 17; });
  ASSERT_FALSE(sf.isReady());
  sf.wait(std::chrono::milliseconds(100));
  ASSERT_FALSE(sf.isReady());
  p.setValue();
  ASSERT_EQ(std::move(sf).get(), 17);
}
Beispiel #26
0
TEST(Collect, collectAllVariadicWithException) {
  Promise<bool> pb;
  Promise<int> pi;
  Future<bool> fb = pb.getFuture();
  Future<int> fi = pi.getFuture();
  bool flag = false;
  collectAll(std::move(fb), std::move(fi))
    .then([&](std::tuple<Try<bool>, Try<int>> tup) {
      flag = true;
      EXPECT_TRUE(std::get<0>(tup).hasValue());
      EXPECT_EQ(std::get<0>(tup).value(), true);
      EXPECT_TRUE(std::get<1>(tup).hasException());
      EXPECT_THROW(std::get<1>(tup).value(), eggs_t);
    });
  pb.setValue(true);
  EXPECT_FALSE(flag);
  pi.setException(eggs);
  EXPECT_TRUE(flag);
}
Beispiel #27
0
TEST(Collect, collectAllVariadicReferences) {
  Promise<bool> pb;
  Promise<int> pi;
  Future<bool> fb = pb.getFuture();
  Future<int> fi = pi.getFuture();
  bool flag = false;
  collectAll(fb, fi)
    .then([&](std::tuple<Try<bool>, Try<int>> tup) {
      flag = true;
      EXPECT_TRUE(std::get<0>(tup).hasValue());
      EXPECT_EQ(std::get<0>(tup).value(), true);
      EXPECT_TRUE(std::get<1>(tup).hasValue());
      EXPECT_EQ(std::get<1>(tup).value(), 42);
    });
  pb.setValue(true);
  EXPECT_FALSE(flag);
  pi.setValue(42);
  EXPECT_TRUE(flag);
}
Beispiel #28
0
TEST(SemiFuture, SimpleDeferWithValue) {
  std::atomic<int> innerResult{0};
  Promise<int> p;
  auto f = p.getFuture();
  auto sf = std::move(f).semi().defer([&](int a) { innerResult = a; });
  p.setValue(7);
  // Run "F" here inline in the calling thread
  std::move(sf).get();
  ASSERT_EQ(innerResult, 7);
}
Beispiel #29
0
// Makes sure that the unwrap call also works when the promise was not yet
// fulfilled, and that the returned Future<T> becomes ready once the promise
// is fulfilled.
TEST(Unwrap, futureNotReady) {
  Promise<Future<int>> p;
  Future<Future<int>> future = p.getFuture();
  Future<int> unwrapped = future.unwrap();
  // Sanity - should not be ready before the promise is fulfilled.
  ASSERT_FALSE(unwrapped.isReady());
  // Fulfill the promise and make sure the unwrapped future is now ready.
  p.setValue(makeFuture(5484));
  ASSERT_TRUE(unwrapped.isReady());
  EXPECT_EQ(5484, unwrapped.value());
}
Beispiel #30
0
void test_thread() {
  Promise<std::string> p;

  std::thread thr([&p] {
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
    p.setValue("done");
  });

  auto f = p.getFuture();
  ok(f.get() == "done", "done in thread");
  thr.join();
}