Beispiel #1
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");
  }
}
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 #3
0
TEST(Promise, isFulfilled) {
    Promise<int> p;

    EXPECT_FALSE(p.isFulfilled());
    p.setValue(42);
    EXPECT_TRUE(p.isFulfilled());
}
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 #5
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(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 #7
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);
}
FutureSync<void> TransportSocketCache::disconnect(MessageSocketPtr socket)
{
  Promise<void> promiseSocketRemoved;
  {
    auto syncDisconnectInfos = _disconnectInfos.synchronize();
    // TODO: Remove Promise<void>{} when get rid of VS2013.
    syncDisconnectInfos->push_back(DisconnectInfo{socket, Promise<void>{}});
    promiseSocketRemoved = syncDisconnectInfos->back().promiseSocketRemoved;
  }
  // We wait that the socket has been disconnected _and_ the `disconnected`
  // signal has been received by the cache.
  FutureBarrier<void> barrier;
  barrier.addFuture(promiseSocketRemoved.future());
  barrier.addFuture(socket->disconnect());
  Promise<void> promise;
  return barrier.future().then([=](const std::vector<Future<void>>& v) mutable {
    const auto isInError = [](const Future<void>& f) {
      return f.hasError();
    };
    if (std::any_of(begin(v), end(v), isInError))
    {
      promise.setError("disconnect error");
      return;
    }
    promise.setValue(0);
  });
}
TEST(Future, toUnitWhileInProgress) {
  Promise<int> p;
  Future<Unit> fu = p.getFuture().unit();
  EXPECT_FALSE(fu.isReady());
  p.setValue(42);
  EXPECT_TRUE(fu.isReady());
}
Beispiel #10
0
TEST(SemiFuture, SimpleValue) {
  Promise<int> p;
  auto sf = p.getSemiFuture();
  p.setValue(3);
  auto v = std::move(sf).value();
  ASSERT_EQ(v, 3);
}
TEST(Future, isReady) {
  Promise<int> p;
  auto f = p.getFuture();
  EXPECT_FALSE(f.isReady());
  p.setValue(42);
  EXPECT_TRUE(f.isReady());
  }
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());
}
Beispiel #13
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 #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(SemiFuture, SimpleResult) {
  EventBase e2;
  Promise<int> p;
  auto sf = p.getSemiFuture();
  p.setValue(3);
  auto v = std::move(sf).result();
  ASSERT_EQ(v.value(), 3);
}
Beispiel #16
0
TEST(SemiFuture, SimpleTimedWait) {
  Promise<folly::Unit> p;
  auto sf = p.getSemiFuture();
  sf.wait(std::chrono::milliseconds(100));
  EXPECT_FALSE(sf.isReady());
  p.setValue();
  EXPECT_TRUE(sf.isReady());
}
Beispiel #17
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 #18
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 #19
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 #20
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 #21
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 #22
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 #23
0
TEST(SemiFuture, DeferWithVia) {
  std::atomic<int> innerResult{0};
  EventBase e2;
  Promise<folly::Unit> p;
  auto f = p.getFuture();
  auto sf = std::move(f).semi().defer([&]() { innerResult = 17; });
  // Run "F" here inline in the calling thread
  auto tf = std::move(sf).via(&e2);
  p.setValue();
  tf.getVia(&e2);
  ASSERT_EQ(innerResult, 17);
}
Beispiel #24
0
TEST(Timekeeper, futureGetBeforeTimeout) {
  Promise<int> p;
  auto t = std::thread([&]{ p.setValue(42); });
  // Technically this is a race and if the test server is REALLY overloaded
  // and it takes more than a second to do that thread it could be flaky. But
  // I want a low timeout (in human terms) so if this regresses and someone
  // 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(std::chrono::seconds(2)));
  t.join();
}
Beispiel #25
0
TEST(SharedPromise, splitFutureSuccess) {
  Promise<int> p;
  SharedPromise<int> sp(p.getFuture());
  auto f1 = sp.getFuture();
  EXPECT_FALSE(f1.isReady());
  p.setValue(1);
  EXPECT_TRUE(f1.isReady());
  EXPECT_TRUE(f1.hasValue());
  auto f2 = sp.getFuture();
  EXPECT_TRUE(f2.isReady());
  EXPECT_TRUE(f2.hasValue());
}
Beispiel #26
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();
}
TEST(Future, thenDynamic) {
  // folly::dynamic has a constructor that takes any T, this test makes
  // sure that we call the then lambda with folly::dynamic and not
  // Try<folly::dynamic> because that then fails to compile
  Promise<folly::dynamic> p;
  Future<folly::dynamic> f = p.getFuture().then(
      [](const folly::dynamic& d) {
        return folly::dynamic(d.asInt() + 3);
      }
  );
  p.setValue(2);
  EXPECT_EQ(f.get(), 5);
}
TEST(NonCopyableLambda, FunctionConst) {
  Promise<int> promise;

  Function<int(int) const> callback = [](int x) { return x + 1; };

  auto future = promise.getFuture().thenValue(std::move(callback));
  EXPECT_THROW(callback(0), std::bad_function_call);

  EXPECT_FALSE(future.isReady());
  promise.setValue(100);
  EXPECT_TRUE(future.isReady());
  EXPECT_EQ(std::move(future).get(), 101);
}
Beispiel #29
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 #30
-1
TEST(SemiFuture, MakeSemiFutureFromReadyFuture) {
  Promise<int> p;
  auto f = p.getSemiFuture();
  EXPECT_FALSE(f.isReady());
  p.setValue(42);
  EXPECT_TRUE(f.isReady());
}