-TEST(Future, whenAll) {
- // returns a vector variant
- {
- vector<Promise<int>> promises(10);
- vector<Future<int>> futures;
-
- for (auto& p : promises)
- futures.push_back(p.getFuture());
-
- auto allf = whenAll(futures.begin(), futures.end());
-
- random_shuffle(promises.begin(), promises.end());
- for (auto& p : promises) {
- EXPECT_FALSE(allf.isReady());
- p.setValue(42);
- }
-
- EXPECT_TRUE(allf.isReady());
- auto& results = allf.value();
- for (auto& t : results) {
- EXPECT_EQ(42, t.value());
- }
- }
-
- // check error semantics
- {
- vector<Promise<int>> promises(4);
- vector<Future<int>> futures;
-
- for (auto& p : promises)
- futures.push_back(p.getFuture());
-
- auto allf = whenAll(futures.begin(), futures.end());
-
-
- promises[0].setValue(42);
- promises[1].setException(eggs);
-
- EXPECT_FALSE(allf.isReady());
-
- promises[2].setValue(42);
-
- EXPECT_FALSE(allf.isReady());
-
- promises[3].setException(eggs);
-
- EXPECT_TRUE(allf.isReady());
- EXPECT_FALSE(allf.getTry().hasException());
-
- auto& results = allf.value();
- EXPECT_EQ(42, results[0].value());
- EXPECT_TRUE(results[1].hasException());
- EXPECT_EQ(42, results[2].value());
- EXPECT_TRUE(results[3].hasException());
- }
-
- // check that futures are ready in then()
- {
- vector<Promise<void>> promises(10);
- vector<Future<void>> futures;
-
- for (auto& p : promises)
- futures.push_back(p.getFuture());
-
- auto allf = whenAll(futures.begin(), futures.end())
- .then([](Try<vector<Try<void>>>&& ts) {
- for (auto& f : ts.value())
- f.value();
- });
-
- random_shuffle(promises.begin(), promises.end());
- for (auto& p : promises)
- p.setValue();
- EXPECT_TRUE(allf.isReady());
- }
-}
-
-
-TEST(Future, whenAny) {
- {
- vector<Promise<int>> promises(10);
- vector<Future<int>> futures;
-
- for (auto& p : promises)
- futures.push_back(p.getFuture());
-
- for (auto& f : futures) {
- EXPECT_FALSE(f.isReady());
- }
-
- auto anyf = whenAny(futures.begin(), futures.end());
-
- /* futures were moved in, so these are invalid now */
- EXPECT_FALSE(anyf.isReady());
-
- promises[7].setValue(42);
- EXPECT_TRUE(anyf.isReady());
- auto& idx_fut = anyf.value();
-
- auto i = idx_fut.first;
- EXPECT_EQ(7, i);
-
- auto& f = idx_fut.second;
- EXPECT_EQ(42, f.value());
- }
-
- // error
- {
- vector<Promise<void>> promises(10);
- vector<Future<void>> futures;
-
- for (auto& p : promises)
- futures.push_back(p.getFuture());
-
- for (auto& f : futures) {
- EXPECT_FALSE(f.isReady());
- }
-
- auto anyf = whenAny(futures.begin(), futures.end());
-
- EXPECT_FALSE(anyf.isReady());
-
- promises[3].setException(eggs);
- EXPECT_TRUE(anyf.isReady());
- EXPECT_TRUE(anyf.value().second.hasException());
- }
-
- // then()
- {
- vector<Promise<int>> promises(10);
- vector<Future<int>> futures;
-
- for (auto& p : promises)
- futures.push_back(p.getFuture());
-
- auto anyf = whenAny(futures.begin(), futures.end())
- .then([](pair<size_t, Try<int>> p) {
- EXPECT_EQ(42, p.second.value());
- });
-
- promises[3].setValue(42);
- EXPECT_TRUE(anyf.isReady());
- }
-}
-
-
-TEST(when, already_completed) {
- {
- vector<Future<void>> fs;
- for (int i = 0; i < 10; i++)
- fs.push_back(makeFuture());
-
- whenAll(fs.begin(), fs.end())
- .then([&](vector<Try<void>> ts) {
- EXPECT_EQ(fs.size(), ts.size());
- });
- }
- {
- vector<Future<int>> fs;
- for (int i = 0; i < 10; i++)
- fs.push_back(makeFuture(i));
-
- whenAny(fs.begin(), fs.end())
- .then([&](pair<size_t, Try<int>> p) {
- EXPECT_EQ(p.first, p.second.value());
- });
- }
-}
-
-TEST(when, whenN) {
- vector<Promise<void>> promises(10);
- vector<Future<void>> futures;
-
- for (auto& p : promises)
- futures.push_back(p.getFuture());
-
- bool flag = false;
- size_t n = 3;
- whenN(futures.begin(), futures.end(), n)
- .then([&](vector<pair<size_t, Try<void>>> v) {
- flag = true;
- EXPECT_EQ(n, v.size());
- for (auto& tt : v)
- EXPECT_TRUE(tt.second.hasValue());
- });
-
- promises[0].setValue();
- EXPECT_FALSE(flag);
- promises[1].setValue();
- EXPECT_FALSE(flag);
- promises[2].setValue();
- EXPECT_TRUE(flag);
-}
-
-/* Ensure that we can compile when_{all,any} with folly::small_vector */
-TEST(when, small_vector) {
-
- static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<void>),
- "Futures should not be trivially copyable");
- static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<int>),
- "Futures should not be trivially copyable");
-
- using folly::small_vector;
- {
- small_vector<Future<void>> futures;
-
- for (int i = 0; i < 10; i++)
- futures.push_back(makeFuture());
-
- auto anyf = whenAny(futures.begin(), futures.end());
- }
-
- {
- small_vector<Future<void>> futures;
-
- for (int i = 0; i < 10; i++)
- futures.push_back(makeFuture());
-
- auto allf = whenAll(futures.begin(), futures.end());
- }
-}
-
-TEST(Future, whenAllVariadic) {
- Promise<bool> pb;
- Promise<int> pi;
- Future<bool> fb = pb.getFuture();
- Future<int> fi = pi.getFuture();
- bool flag = false;
- whenAll(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).hasValue());
- EXPECT_EQ(std::get<1>(tup).value(), 42);
- });
- pb.setValue(true);
- EXPECT_FALSE(flag);
- pi.setValue(42);
- EXPECT_TRUE(flag);
-}
-
-TEST(Future, whenAllVariadicReferences) {
- Promise<bool> pb;
- Promise<int> pi;
- Future<bool> fb = pb.getFuture();
- Future<int> fi = pi.getFuture();
- bool flag = false;
- whenAll(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);
-}
-
-TEST(Future, whenAll_none) {
- vector<Future<int>> fs;
- auto f = whenAll(fs.begin(), fs.end());
- EXPECT_TRUE(f.isReady());
-}
-