2 * Copyright 2017 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.
19 #include <boost/thread/barrier.hpp>
21 #include <folly/futures/Future.h>
22 #include <folly/Random.h>
23 #include <folly/small_vector.h>
24 #include <folly/portability/GTest.h>
26 using namespace folly;
28 typedef FutureException eggs_t;
29 static eggs_t eggs("eggs");
31 auto rng = std::mt19937(folly::randomNumberSeed());
33 TEST(Collect, collectAll) {
34 // returns a vector variant
36 std::vector<Promise<int>> promises(10);
37 std::vector<Future<int>> futures;
39 for (auto& p : promises)
40 futures.push_back(p.getFuture());
42 auto allf = collectAll(futures);
44 std::shuffle(promises.begin(), promises.end(), rng);
45 for (auto& p : promises) {
46 EXPECT_FALSE(allf.isReady());
50 EXPECT_TRUE(allf.isReady());
51 auto& results = allf.value();
52 for (auto& t : results) {
53 EXPECT_EQ(42, t.value());
57 // check error semantics
59 std::vector<Promise<int>> promises(4);
60 std::vector<Future<int>> futures;
62 for (auto& p : promises)
63 futures.push_back(p.getFuture());
65 auto allf = collectAll(futures);
68 promises[0].setValue(42);
69 promises[1].setException(eggs);
71 EXPECT_FALSE(allf.isReady());
73 promises[2].setValue(42);
75 EXPECT_FALSE(allf.isReady());
77 promises[3].setException(eggs);
79 EXPECT_TRUE(allf.isReady());
80 EXPECT_FALSE(allf.getTry().hasException());
82 auto& results = allf.value();
83 EXPECT_EQ(42, results[0].value());
84 EXPECT_TRUE(results[1].hasException());
85 EXPECT_EQ(42, results[2].value());
86 EXPECT_TRUE(results[3].hasException());
89 // check that futures are ready in then()
91 std::vector<Promise<Unit>> promises(10);
92 std::vector<Future<Unit>> futures;
94 for (auto& p : promises)
95 futures.push_back(p.getFuture());
97 auto allf = collectAll(futures)
98 .then([](Try<std::vector<Try<Unit>>>&& ts) {
99 for (auto& f : ts.value())
103 std::shuffle(promises.begin(), promises.end(), rng);
104 for (auto& p : promises)
106 EXPECT_TRUE(allf.isReady());
110 TEST(Collect, collect) {
113 std::vector<Promise<int>> promises(10);
114 std::vector<Future<int>> futures;
116 for (auto& p : promises)
117 futures.push_back(p.getFuture());
119 auto allf = collect(futures);
121 std::shuffle(promises.begin(), promises.end(), rng);
122 for (auto& p : promises) {
123 EXPECT_FALSE(allf.isReady());
127 EXPECT_TRUE(allf.isReady());
128 for (auto i : allf.value()) {
135 std::vector<Promise<int>> promises(10);
136 std::vector<Future<int>> futures;
138 for (auto& p : promises)
139 futures.push_back(p.getFuture());
141 auto allf = collect(futures);
143 std::shuffle(promises.begin(), promises.end(), rng);
144 for (int i = 0; i < 10; i++) {
146 // everthing goes well so far...
147 EXPECT_FALSE(allf.isReady());
148 promises[i].setValue(42);
150 // short circuit with an exception
151 EXPECT_FALSE(allf.isReady());
152 promises[i].setException(eggs);
153 EXPECT_TRUE(allf.isReady());
155 // don't blow up on further values
156 EXPECT_TRUE(allf.isReady());
157 promises[i].setValue(42);
159 // don't blow up on further exceptions
160 EXPECT_TRUE(allf.isReady());
161 promises[i].setException(eggs);
165 EXPECT_THROW(allf.value(), eggs_t);
168 // void futures success case
170 std::vector<Promise<Unit>> promises(10);
171 std::vector<Future<Unit>> futures;
173 for (auto& p : promises)
174 futures.push_back(p.getFuture());
176 auto allf = collect(futures);
178 std::shuffle(promises.begin(), promises.end(), rng);
179 for (auto& p : promises) {
180 EXPECT_FALSE(allf.isReady());
184 EXPECT_TRUE(allf.isReady());
187 // void futures failure case
189 std::vector<Promise<Unit>> promises(10);
190 std::vector<Future<Unit>> futures;
192 for (auto& p : promises)
193 futures.push_back(p.getFuture());
195 auto allf = collect(futures);
197 std::shuffle(promises.begin(), promises.end(), rng);
198 for (int i = 0; i < 10; i++) {
200 // everthing goes well so far...
201 EXPECT_FALSE(allf.isReady());
202 promises[i].setValue();
204 // short circuit with an exception
205 EXPECT_FALSE(allf.isReady());
206 promises[i].setException(eggs);
207 EXPECT_TRUE(allf.isReady());
209 // don't blow up on further values
210 EXPECT_TRUE(allf.isReady());
211 promises[i].setValue();
213 // don't blow up on further exceptions
214 EXPECT_TRUE(allf.isReady());
215 promises[i].setException(eggs);
219 EXPECT_THROW(allf.value(), eggs_t);
222 // move only compiles
224 std::vector<Promise<std::unique_ptr<int>>> promises(10);
225 std::vector<Future<std::unique_ptr<int>>> futures;
227 for (auto& p : promises)
228 futures.push_back(p.getFuture());
235 struct NotDefaultConstructible {
236 NotDefaultConstructible() = delete;
237 explicit NotDefaultConstructible(int arg) : i(arg) {}
241 // We have a specialized implementation for non-default-constructible objects
242 // Ensure that it works and preserves order
243 TEST(Collect, collectNotDefaultConstructible) {
244 std::vector<Promise<NotDefaultConstructible>> promises(10);
245 std::vector<Future<NotDefaultConstructible>> futures;
246 std::vector<int> indices(10);
247 std::iota(indices.begin(), indices.end(), 0);
248 std::shuffle(indices.begin(), indices.end(), rng);
250 for (auto& p : promises)
251 futures.push_back(p.getFuture());
253 auto allf = collect(futures);
255 for (auto i : indices) {
256 EXPECT_FALSE(allf.isReady());
257 promises[i].setValue(NotDefaultConstructible(i));
260 EXPECT_TRUE(allf.isReady());
262 for (auto val : allf.value()) {
268 TEST(Collect, collectAny) {
270 std::vector<Promise<int>> promises(10);
271 std::vector<Future<int>> futures;
273 for (auto& p : promises)
274 futures.push_back(p.getFuture());
276 for (auto& f : futures) {
277 EXPECT_FALSE(f.isReady());
280 auto anyf = collectAny(futures);
282 /* futures were moved in, so these are invalid now */
283 EXPECT_FALSE(anyf.isReady());
285 promises[7].setValue(42);
286 EXPECT_TRUE(anyf.isReady());
287 auto& idx_fut = anyf.value();
289 auto i = idx_fut.first;
292 auto& f = idx_fut.second;
293 EXPECT_EQ(42, f.value());
298 std::vector<Promise<Unit>> promises(10);
299 std::vector<Future<Unit>> futures;
301 for (auto& p : promises)
302 futures.push_back(p.getFuture());
304 for (auto& f : futures) {
305 EXPECT_FALSE(f.isReady());
308 auto anyf = collectAny(futures);
310 EXPECT_FALSE(anyf.isReady());
312 promises[3].setException(eggs);
313 EXPECT_TRUE(anyf.isReady());
314 EXPECT_TRUE(anyf.value().second.hasException());
319 std::vector<Promise<int>> promises(10);
320 std::vector<Future<int>> futures;
322 for (auto& p : promises)
323 futures.push_back(p.getFuture());
325 auto anyf = collectAny(futures)
326 .then([](std::pair<size_t, Try<int>> p) {
327 EXPECT_EQ(42, p.second.value());
330 promises[3].setValue(42);
331 EXPECT_TRUE(anyf.isReady());
335 TEST(Collect, collectAnyWithoutException) {
337 std::vector<Promise<int>> promises(10);
338 std::vector<Future<int>> futures;
340 for (auto& p : promises) {
341 futures.push_back(p.getFuture());
344 auto onef = collectAnyWithoutException(futures);
346 /* futures were moved in, so these are invalid now */
347 EXPECT_FALSE(onef.isReady());
349 promises[7].setValue(42);
350 EXPECT_TRUE(onef.isReady());
351 auto& idx_fut = onef.value();
352 EXPECT_EQ(7, idx_fut.first);
353 EXPECT_EQ(42, idx_fut.second);
356 // some exception before ready
358 std::vector<Promise<int>> promises(10);
359 std::vector<Future<int>> futures;
361 for (auto& p : promises) {
362 futures.push_back(p.getFuture());
365 auto onef = collectAnyWithoutException(futures);
367 EXPECT_FALSE(onef.isReady());
369 promises[3].setException(eggs);
370 EXPECT_FALSE(onef.isReady());
371 promises[4].setException(eggs);
372 EXPECT_FALSE(onef.isReady());
373 promises[0].setValue(99);
374 EXPECT_TRUE(onef.isReady());
375 auto& idx_fut = onef.value();
376 EXPECT_EQ(0, idx_fut.first);
377 EXPECT_EQ(99, idx_fut.second);
382 std::vector<Promise<int>> promises(10);
383 std::vector<Future<int>> futures;
385 for (auto& p : promises) {
386 futures.push_back(p.getFuture());
389 auto onef = collectAnyWithoutException(futures);
391 EXPECT_FALSE(onef.isReady());
392 for (int i = 0; i < 9; ++i) {
393 promises[i].setException(eggs);
395 EXPECT_FALSE(onef.isReady());
397 promises[9].setException(eggs);
398 EXPECT_TRUE(onef.isReady());
399 EXPECT_TRUE(onef.hasException());
403 TEST(Collect, alreadyCompleted) {
405 std::vector<Future<Unit>> fs;
406 for (int i = 0; i < 10; i++)
407 fs.push_back(makeFuture());
410 .then([&](std::vector<Try<Unit>> ts) {
411 EXPECT_EQ(fs.size(), ts.size());
415 std::vector<Future<int>> fs;
416 for (int i = 0; i < 10; i++)
417 fs.push_back(makeFuture(i));
420 .then([&](std::pair<size_t, Try<int>> p) {
421 EXPECT_EQ(p.first, p.second.value());
426 TEST(Collect, parallel) {
427 std::vector<Promise<int>> ps(10);
428 std::vector<Future<int>> fs;
429 for (size_t i = 0; i < ps.size(); i++) {
430 fs.emplace_back(ps[i].getFuture());
432 auto f = collect(fs);
434 std::vector<std::thread> ts;
435 boost::barrier barrier(ps.size() + 1);
436 for (size_t i = 0; i < ps.size(); i++) {
437 ts.emplace_back([&ps, &barrier, i]() {
445 for (size_t i = 0; i < ps.size(); i++) {
449 EXPECT_TRUE(f.isReady());
450 for (size_t i = 0; i < ps.size(); i++) {
451 EXPECT_EQ(i, f.value()[i]);
455 TEST(Collect, parallelWithError) {
456 std::vector<Promise<int>> ps(10);
457 std::vector<Future<int>> fs;
458 for (size_t i = 0; i < ps.size(); i++) {
459 fs.emplace_back(ps[i].getFuture());
461 auto f = collect(fs);
463 std::vector<std::thread> ts;
464 boost::barrier barrier(ps.size() + 1);
465 for (size_t i = 0; i < ps.size(); i++) {
466 ts.emplace_back([&ps, &barrier, i]() {
468 if (i == (ps.size()/2)) {
469 ps[i].setException(eggs);
478 for (size_t i = 0; i < ps.size(); i++) {
482 EXPECT_TRUE(f.isReady());
483 EXPECT_THROW(f.value(), eggs_t);
486 TEST(Collect, allParallel) {
487 std::vector<Promise<int>> ps(10);
488 std::vector<Future<int>> fs;
489 for (size_t i = 0; i < ps.size(); i++) {
490 fs.emplace_back(ps[i].getFuture());
492 auto f = collectAll(fs);
494 std::vector<std::thread> ts;
495 boost::barrier barrier(ps.size() + 1);
496 for (size_t i = 0; i < ps.size(); i++) {
497 ts.emplace_back([&ps, &barrier, i]() {
505 for (size_t i = 0; i < ps.size(); i++) {
509 EXPECT_TRUE(f.isReady());
510 for (size_t i = 0; i < ps.size(); i++) {
511 EXPECT_TRUE(f.value()[i].hasValue());
512 EXPECT_EQ(i, f.value()[i].value());
516 TEST(Collect, allParallelWithError) {
517 std::vector<Promise<int>> ps(10);
518 std::vector<Future<int>> fs;
519 for (size_t i = 0; i < ps.size(); i++) {
520 fs.emplace_back(ps[i].getFuture());
522 auto f = collectAll(fs);
524 std::vector<std::thread> ts;
525 boost::barrier barrier(ps.size() + 1);
526 for (size_t i = 0; i < ps.size(); i++) {
527 ts.emplace_back([&ps, &barrier, i]() {
529 if (i == (ps.size()/2)) {
530 ps[i].setException(eggs);
539 for (size_t i = 0; i < ps.size(); i++) {
543 EXPECT_TRUE(f.isReady());
544 for (size_t i = 0; i < ps.size(); i++) {
545 if (i == (ps.size()/2)) {
546 EXPECT_THROW(f.value()[i].value(), eggs_t);
548 EXPECT_TRUE(f.value()[i].hasValue());
549 EXPECT_EQ(i, f.value()[i].value());
554 TEST(Collect, collectN) {
555 std::vector<Promise<Unit>> promises(10);
556 std::vector<Future<Unit>> futures;
558 for (auto& p : promises)
559 futures.push_back(p.getFuture());
564 .then([&](std::vector<std::pair<size_t, Try<Unit>>> v) {
566 EXPECT_EQ(n, v.size());
568 EXPECT_TRUE(tt.second.hasValue());
571 promises[0].setValue();
573 promises[1].setValue();
575 promises[2].setValue();
579 /// Ensure that we can compile collectAll/Any with folly::small_vector
580 TEST(Collect, smallVector) {
581 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<Unit>),
582 "Futures should not be trivially copyable");
583 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<int>),
584 "Futures should not be trivially copyable");
587 folly::small_vector<Future<Unit>> futures;
589 for (int i = 0; i < 10; i++)
590 futures.push_back(makeFuture());
592 auto anyf = collectAny(futures);
595 folly::small_vector<Future<Unit>> futures;
597 for (int i = 0; i < 10; i++)
598 futures.push_back(makeFuture());
600 auto allf = collectAll(futures);
604 TEST(Collect, collectAllVariadic) {
607 Future<bool> fb = pb.getFuture();
608 Future<int> fi = pi.getFuture();
610 collectAll(std::move(fb), std::move(fi))
611 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
613 EXPECT_TRUE(std::get<0>(tup).hasValue());
614 EXPECT_EQ(std::get<0>(tup).value(), true);
615 EXPECT_TRUE(std::get<1>(tup).hasValue());
616 EXPECT_EQ(std::get<1>(tup).value(), 42);
624 TEST(Collect, collectAllVariadicReferences) {
627 Future<bool> fb = pb.getFuture();
628 Future<int> fi = pi.getFuture();
631 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
633 EXPECT_TRUE(std::get<0>(tup).hasValue());
634 EXPECT_EQ(std::get<0>(tup).value(), true);
635 EXPECT_TRUE(std::get<1>(tup).hasValue());
636 EXPECT_EQ(std::get<1>(tup).value(), 42);
644 TEST(Collect, collectAllVariadicWithException) {
647 Future<bool> fb = pb.getFuture();
648 Future<int> fi = pi.getFuture();
650 collectAll(std::move(fb), std::move(fi))
651 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
653 EXPECT_TRUE(std::get<0>(tup).hasValue());
654 EXPECT_EQ(std::get<0>(tup).value(), true);
655 EXPECT_TRUE(std::get<1>(tup).hasException());
656 EXPECT_THROW(std::get<1>(tup).value(), eggs_t);
660 pi.setException(eggs);
664 TEST(Collect, collectVariadic) {
667 Future<bool> fb = pb.getFuture();
668 Future<int> fi = pi.getFuture();
670 collect(std::move(fb), std::move(fi))
671 .then([&](std::tuple<bool, int> tup) {
673 EXPECT_EQ(std::get<0>(tup), true);
674 EXPECT_EQ(std::get<1>(tup), 42);
682 TEST(Collect, collectVariadicWithException) {
685 Future<bool> fb = pb.getFuture();
686 Future<int> fi = pi.getFuture();
687 auto f = collect(std::move(fb), std::move(fi));
689 EXPECT_FALSE(f.isReady());
690 pi.setException(eggs);
691 EXPECT_TRUE(f.isReady());
692 EXPECT_TRUE(f.getTry().hasException());
693 EXPECT_THROW(f.get(), eggs_t);
696 TEST(Collect, collectAllNone) {
697 std::vector<Future<int>> fs;
698 auto f = collectAll(fs);
699 EXPECT_TRUE(f.isReady());
702 TEST(Collect, noDefaultConstructor) {
704 explicit A(size_t /* x */) {}
707 auto f1 = makeFuture(A(1));
708 auto f2 = makeFuture(A(2));
710 auto f = collect(std::move(f1), std::move(f2));