2 * Copyright 2015 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <gtest/gtest.h>
19 #include <folly/futures/Future.h>
20 #include <folly/Random.h>
21 #include <folly/small_vector.h>
23 using namespace folly;
25 typedef FutureException eggs_t;
26 static eggs_t eggs("eggs");
28 auto rng = std::mt19937(folly::randomNumberSeed());
30 TEST(Collect, collectAll) {
31 // returns a vector variant
33 std::vector<Promise<int>> promises(10);
34 std::vector<Future<int>> futures;
36 for (auto& p : promises)
37 futures.push_back(p.getFuture());
39 auto allf = collectAll(futures);
41 std::shuffle(promises.begin(), promises.end(), rng);
42 for (auto& p : promises) {
43 EXPECT_FALSE(allf.isReady());
47 EXPECT_TRUE(allf.isReady());
48 auto& results = allf.value();
49 for (auto& t : results) {
50 EXPECT_EQ(42, t.value());
54 // check error semantics
56 std::vector<Promise<int>> promises(4);
57 std::vector<Future<int>> futures;
59 for (auto& p : promises)
60 futures.push_back(p.getFuture());
62 auto allf = collectAll(futures);
65 promises[0].setValue(42);
66 promises[1].setException(eggs);
68 EXPECT_FALSE(allf.isReady());
70 promises[2].setValue(42);
72 EXPECT_FALSE(allf.isReady());
74 promises[3].setException(eggs);
76 EXPECT_TRUE(allf.isReady());
77 EXPECT_FALSE(allf.getTry().hasException());
79 auto& results = allf.value();
80 EXPECT_EQ(42, results[0].value());
81 EXPECT_TRUE(results[1].hasException());
82 EXPECT_EQ(42, results[2].value());
83 EXPECT_TRUE(results[3].hasException());
86 // check that futures are ready in then()
88 std::vector<Promise<void>> promises(10);
89 std::vector<Future<void>> futures;
91 for (auto& p : promises)
92 futures.push_back(p.getFuture());
94 auto allf = collectAll(futures)
95 .then([](Try<std::vector<Try<void>>>&& ts) {
96 for (auto& f : ts.value())
100 std::shuffle(promises.begin(), promises.end(), rng);
101 for (auto& p : promises)
103 EXPECT_TRUE(allf.isReady());
107 TEST(Collect, collect) {
110 std::vector<Promise<int>> promises(10);
111 std::vector<Future<int>> futures;
113 for (auto& p : promises)
114 futures.push_back(p.getFuture());
116 auto allf = collect(futures);
118 std::shuffle(promises.begin(), promises.end(), rng);
119 for (auto& p : promises) {
120 EXPECT_FALSE(allf.isReady());
124 EXPECT_TRUE(allf.isReady());
125 for (auto i : allf.value()) {
132 std::vector<Promise<int>> promises(10);
133 std::vector<Future<int>> futures;
135 for (auto& p : promises)
136 futures.push_back(p.getFuture());
138 auto allf = collect(futures);
140 std::shuffle(promises.begin(), promises.end(), rng);
141 for (int i = 0; i < 10; i++) {
143 // everthing goes well so far...
144 EXPECT_FALSE(allf.isReady());
145 promises[i].setValue(42);
147 // short circuit with an exception
148 EXPECT_FALSE(allf.isReady());
149 promises[i].setException(eggs);
150 EXPECT_TRUE(allf.isReady());
152 // don't blow up on further values
153 EXPECT_TRUE(allf.isReady());
154 promises[i].setValue(42);
156 // don't blow up on further exceptions
157 EXPECT_TRUE(allf.isReady());
158 promises[i].setException(eggs);
162 EXPECT_THROW(allf.value(), eggs_t);
165 // void futures success case
167 std::vector<Promise<void>> promises(10);
168 std::vector<Future<void>> futures;
170 for (auto& p : promises)
171 futures.push_back(p.getFuture());
173 auto allf = collect(futures);
175 std::shuffle(promises.begin(), promises.end(), rng);
176 for (auto& p : promises) {
177 EXPECT_FALSE(allf.isReady());
181 EXPECT_TRUE(allf.isReady());
184 // void futures failure case
186 std::vector<Promise<void>> promises(10);
187 std::vector<Future<void>> futures;
189 for (auto& p : promises)
190 futures.push_back(p.getFuture());
192 auto allf = collect(futures);
194 std::shuffle(promises.begin(), promises.end(), rng);
195 for (int i = 0; i < 10; i++) {
197 // everthing goes well so far...
198 EXPECT_FALSE(allf.isReady());
199 promises[i].setValue();
201 // short circuit with an exception
202 EXPECT_FALSE(allf.isReady());
203 promises[i].setException(eggs);
204 EXPECT_TRUE(allf.isReady());
206 // don't blow up on further values
207 EXPECT_TRUE(allf.isReady());
208 promises[i].setValue();
210 // don't blow up on further exceptions
211 EXPECT_TRUE(allf.isReady());
212 promises[i].setException(eggs);
216 EXPECT_THROW(allf.value(), eggs_t);
219 // move only compiles
221 std::vector<Promise<std::unique_ptr<int>>> promises(10);
222 std::vector<Future<std::unique_ptr<int>>> futures;
224 for (auto& p : promises)
225 futures.push_back(p.getFuture());
232 struct NotDefaultConstructible {
233 NotDefaultConstructible() = delete;
234 explicit NotDefaultConstructible(int arg) : i(arg) {}
238 // We have a specialized implementation for non-default-constructible objects
239 // Ensure that it works and preserves order
240 TEST(Collect, collectNotDefaultConstructible) {
241 std::vector<Promise<NotDefaultConstructible>> promises(10);
242 std::vector<Future<NotDefaultConstructible>> futures;
243 std::vector<int> indices(10);
244 std::iota(indices.begin(), indices.end(), 0);
245 std::shuffle(indices.begin(), indices.end(), rng);
247 for (auto& p : promises)
248 futures.push_back(p.getFuture());
250 auto allf = collect(futures);
252 for (auto i : indices) {
253 EXPECT_FALSE(allf.isReady());
254 promises[i].setValue(NotDefaultConstructible(i));
257 EXPECT_TRUE(allf.isReady());
259 for (auto val : allf.value()) {
265 TEST(Collect, collectAny) {
267 std::vector<Promise<int>> promises(10);
268 std::vector<Future<int>> futures;
270 for (auto& p : promises)
271 futures.push_back(p.getFuture());
273 for (auto& f : futures) {
274 EXPECT_FALSE(f.isReady());
277 auto anyf = collectAny(futures);
279 /* futures were moved in, so these are invalid now */
280 EXPECT_FALSE(anyf.isReady());
282 promises[7].setValue(42);
283 EXPECT_TRUE(anyf.isReady());
284 auto& idx_fut = anyf.value();
286 auto i = idx_fut.first;
289 auto& f = idx_fut.second;
290 EXPECT_EQ(42, f.value());
295 std::vector<Promise<void>> promises(10);
296 std::vector<Future<void>> futures;
298 for (auto& p : promises)
299 futures.push_back(p.getFuture());
301 for (auto& f : futures) {
302 EXPECT_FALSE(f.isReady());
305 auto anyf = collectAny(futures);
307 EXPECT_FALSE(anyf.isReady());
309 promises[3].setException(eggs);
310 EXPECT_TRUE(anyf.isReady());
311 EXPECT_TRUE(anyf.value().second.hasException());
316 std::vector<Promise<int>> promises(10);
317 std::vector<Future<int>> futures;
319 for (auto& p : promises)
320 futures.push_back(p.getFuture());
322 auto anyf = collectAny(futures)
323 .then([](std::pair<size_t, Try<int>> p) {
324 EXPECT_EQ(42, p.second.value());
327 promises[3].setValue(42);
328 EXPECT_TRUE(anyf.isReady());
333 TEST(Collect, alreadyCompleted) {
335 std::vector<Future<void>> fs;
336 for (int i = 0; i < 10; i++)
337 fs.push_back(makeFuture());
340 .then([&](std::vector<Try<void>> ts) {
341 EXPECT_EQ(fs.size(), ts.size());
345 std::vector<Future<int>> fs;
346 for (int i = 0; i < 10; i++)
347 fs.push_back(makeFuture(i));
350 .then([&](std::pair<size_t, Try<int>> p) {
351 EXPECT_EQ(p.first, p.second.value());
356 TEST(Collect, collectN) {
357 std::vector<Promise<void>> promises(10);
358 std::vector<Future<void>> futures;
360 for (auto& p : promises)
361 futures.push_back(p.getFuture());
366 .then([&](std::vector<std::pair<size_t, Try<void>>> v) {
368 EXPECT_EQ(n, v.size());
370 EXPECT_TRUE(tt.second.hasValue());
373 promises[0].setValue();
375 promises[1].setValue();
377 promises[2].setValue();
381 /// Ensure that we can compile collectAll/Any with folly::small_vector
382 TEST(Collect, smallVector) {
383 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<void>),
384 "Futures should not be trivially copyable");
385 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<int>),
386 "Futures should not be trivially copyable");
389 folly::small_vector<Future<void>> futures;
391 for (int i = 0; i < 10; i++)
392 futures.push_back(makeFuture());
394 auto anyf = collectAny(futures);
397 folly::small_vector<Future<void>> futures;
399 for (int i = 0; i < 10; i++)
400 futures.push_back(makeFuture());
402 auto allf = collectAll(futures);
406 TEST(Collect, collectAllVariadic) {
409 Future<bool> fb = pb.getFuture();
410 Future<int> fi = pi.getFuture();
412 collectAll(std::move(fb), std::move(fi))
413 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
415 EXPECT_TRUE(std::get<0>(tup).hasValue());
416 EXPECT_EQ(std::get<0>(tup).value(), true);
417 EXPECT_TRUE(std::get<1>(tup).hasValue());
418 EXPECT_EQ(std::get<1>(tup).value(), 42);
426 TEST(Collect, collectAllVariadicReferences) {
429 Future<bool> fb = pb.getFuture();
430 Future<int> fi = pi.getFuture();
433 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
435 EXPECT_TRUE(std::get<0>(tup).hasValue());
436 EXPECT_EQ(std::get<0>(tup).value(), true);
437 EXPECT_TRUE(std::get<1>(tup).hasValue());
438 EXPECT_EQ(std::get<1>(tup).value(), 42);
446 TEST(Collect, collectAllNone) {
447 std::vector<Future<int>> fs;
448 auto f = collectAll(fs);
449 EXPECT_TRUE(f.isReady());