2 * Copyright 2015-present 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/Random.h>
22 #include <folly/futures/Future.h>
23 #include <folly/portability/GTest.h>
24 #include <folly/small_vector.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());
43 auto allf = collectAll(futures);
45 std::shuffle(promises.begin(), promises.end(), rng);
46 for (auto& p : promises) {
47 EXPECT_FALSE(allf.isReady());
51 EXPECT_TRUE(allf.isReady());
52 auto& results = allf.value();
53 for (auto& t : results) {
54 EXPECT_EQ(42, t.value());
58 // check error semantics
60 std::vector<Promise<int>> promises(4);
61 std::vector<Future<int>> futures;
63 for (auto& p : promises) {
64 futures.push_back(p.getFuture());
67 auto allf = collectAll(futures);
70 promises[0].setValue(42);
71 promises[1].setException(eggs);
73 EXPECT_FALSE(allf.isReady());
75 promises[2].setValue(42);
77 EXPECT_FALSE(allf.isReady());
79 promises[3].setException(eggs);
81 EXPECT_TRUE(allf.isReady());
82 EXPECT_FALSE(allf.getTry().hasException());
84 auto& results = allf.value();
85 EXPECT_EQ(42, results[0].value());
86 EXPECT_TRUE(results[1].hasException());
87 EXPECT_EQ(42, results[2].value());
88 EXPECT_TRUE(results[3].hasException());
91 // check that futures are ready in then()
93 std::vector<Promise<Unit>> promises(10);
94 std::vector<Future<Unit>> futures;
96 for (auto& p : promises) {
97 futures.push_back(p.getFuture());
100 auto allf = collectAll(futures).then([](Try<std::vector<Try<Unit>>>&& ts) {
101 for (auto& f : ts.value()) {
106 std::shuffle(promises.begin(), promises.end(), rng);
107 for (auto& p : promises) {
110 EXPECT_TRUE(allf.isReady());
114 TEST(Collect, collect) {
117 std::vector<Promise<int>> promises(10);
118 std::vector<Future<int>> futures;
120 for (auto& p : promises) {
121 futures.push_back(p.getFuture());
124 auto allf = collect(futures);
126 std::shuffle(promises.begin(), promises.end(), rng);
127 for (auto& p : promises) {
128 EXPECT_FALSE(allf.isReady());
132 EXPECT_TRUE(allf.isReady());
133 for (auto i : allf.value()) {
140 std::vector<Promise<int>> promises(10);
141 std::vector<Future<int>> futures;
143 for (auto& p : promises) {
144 futures.push_back(p.getFuture());
147 auto allf = collect(futures);
149 std::shuffle(promises.begin(), promises.end(), rng);
150 for (int i = 0; i < 10; i++) {
152 // everthing goes well so far...
153 EXPECT_FALSE(allf.isReady());
154 promises[i].setValue(42);
156 // short circuit with an exception
157 EXPECT_FALSE(allf.isReady());
158 promises[i].setException(eggs);
159 EXPECT_TRUE(allf.isReady());
161 // don't blow up on further values
162 EXPECT_TRUE(allf.isReady());
163 promises[i].setValue(42);
165 // don't blow up on further exceptions
166 EXPECT_TRUE(allf.isReady());
167 promises[i].setException(eggs);
171 EXPECT_THROW(allf.value(), eggs_t);
174 // void futures success case
176 std::vector<Promise<Unit>> promises(10);
177 std::vector<Future<Unit>> futures;
179 for (auto& p : promises) {
180 futures.push_back(p.getFuture());
183 auto allf = collect(futures);
185 std::shuffle(promises.begin(), promises.end(), rng);
186 for (auto& p : promises) {
187 EXPECT_FALSE(allf.isReady());
191 EXPECT_TRUE(allf.isReady());
194 // void futures failure case
196 std::vector<Promise<Unit>> promises(10);
197 std::vector<Future<Unit>> futures;
199 for (auto& p : promises) {
200 futures.push_back(p.getFuture());
203 auto allf = collect(futures);
205 std::shuffle(promises.begin(), promises.end(), rng);
206 for (int i = 0; i < 10; i++) {
208 // everthing goes well so far...
209 EXPECT_FALSE(allf.isReady());
210 promises[i].setValue();
212 // short circuit with an exception
213 EXPECT_FALSE(allf.isReady());
214 promises[i].setException(eggs);
215 EXPECT_TRUE(allf.isReady());
217 // don't blow up on further values
218 EXPECT_TRUE(allf.isReady());
219 promises[i].setValue();
221 // don't blow up on further exceptions
222 EXPECT_TRUE(allf.isReady());
223 promises[i].setException(eggs);
227 EXPECT_THROW(allf.value(), eggs_t);
230 // move only compiles
232 std::vector<Promise<std::unique_ptr<int>>> promises(10);
233 std::vector<Future<std::unique_ptr<int>>> futures;
235 for (auto& p : promises) {
236 futures.push_back(p.getFuture());
244 struct NotDefaultConstructible {
245 NotDefaultConstructible() = delete;
246 explicit NotDefaultConstructible(int arg) : i(arg) {}
250 // We have a specialized implementation for non-default-constructible objects
251 // Ensure that it works and preserves order
252 TEST(Collect, collectNotDefaultConstructible) {
253 std::vector<Promise<NotDefaultConstructible>> promises(10);
254 std::vector<Future<NotDefaultConstructible>> futures;
255 std::vector<int> indices(10);
256 std::iota(indices.begin(), indices.end(), 0);
257 std::shuffle(indices.begin(), indices.end(), rng);
259 for (auto& p : promises) {
260 futures.push_back(p.getFuture());
263 auto allf = collect(futures);
265 for (auto i : indices) {
266 EXPECT_FALSE(allf.isReady());
267 promises[i].setValue(NotDefaultConstructible(i));
270 EXPECT_TRUE(allf.isReady());
272 for (auto val : allf.value()) {
278 TEST(Collect, collectAny) {
280 std::vector<Promise<int>> promises(10);
281 std::vector<Future<int>> futures;
283 for (auto& p : promises) {
284 futures.push_back(p.getFuture());
287 for (auto& f : futures) {
288 EXPECT_FALSE(f.isReady());
291 auto anyf = collectAny(futures);
293 /* futures were moved in, so these are invalid now */
294 EXPECT_FALSE(anyf.isReady());
296 promises[7].setValue(42);
297 EXPECT_TRUE(anyf.isReady());
298 auto& idx_fut = anyf.value();
300 auto i = idx_fut.first;
303 auto& f = idx_fut.second;
304 EXPECT_EQ(42, f.value());
309 std::vector<Promise<Unit>> promises(10);
310 std::vector<Future<Unit>> futures;
312 for (auto& p : promises) {
313 futures.push_back(p.getFuture());
316 for (auto& f : futures) {
317 EXPECT_FALSE(f.isReady());
320 auto anyf = collectAny(futures);
322 EXPECT_FALSE(anyf.isReady());
324 promises[3].setException(eggs);
325 EXPECT_TRUE(anyf.isReady());
326 EXPECT_TRUE(anyf.value().second.hasException());
331 std::vector<Promise<int>> promises(10);
332 std::vector<Future<int>> futures;
334 for (auto& p : promises) {
335 futures.push_back(p.getFuture());
338 auto anyf = collectAny(futures)
339 .then([](std::pair<size_t, Try<int>> p) {
340 EXPECT_EQ(42, p.second.value());
343 promises[3].setValue(42);
344 EXPECT_TRUE(anyf.isReady());
348 TEST(Collect, collectAnyWithoutException) {
350 std::vector<Promise<int>> promises(10);
351 std::vector<Future<int>> futures;
353 for (auto& p : promises) {
354 futures.push_back(p.getFuture());
357 auto onef = collectAnyWithoutException(futures);
359 /* futures were moved in, so these are invalid now */
360 EXPECT_FALSE(onef.isReady());
362 promises[7].setValue(42);
363 EXPECT_TRUE(onef.isReady());
364 auto& idx_fut = onef.value();
365 EXPECT_EQ(7, idx_fut.first);
366 EXPECT_EQ(42, idx_fut.second);
369 // some exception before ready
371 std::vector<Promise<int>> promises(10);
372 std::vector<Future<int>> futures;
374 for (auto& p : promises) {
375 futures.push_back(p.getFuture());
378 auto onef = collectAnyWithoutException(futures);
380 EXPECT_FALSE(onef.isReady());
382 promises[3].setException(eggs);
383 EXPECT_FALSE(onef.isReady());
384 promises[4].setException(eggs);
385 EXPECT_FALSE(onef.isReady());
386 promises[0].setValue(99);
387 EXPECT_TRUE(onef.isReady());
388 auto& idx_fut = onef.value();
389 EXPECT_EQ(0, idx_fut.first);
390 EXPECT_EQ(99, idx_fut.second);
395 std::vector<Promise<int>> promises(10);
396 std::vector<Future<int>> futures;
398 for (auto& p : promises) {
399 futures.push_back(p.getFuture());
402 auto onef = collectAnyWithoutException(futures);
404 EXPECT_FALSE(onef.isReady());
405 for (int i = 0; i < 9; ++i) {
406 promises[i].setException(eggs);
408 EXPECT_FALSE(onef.isReady());
410 promises[9].setException(eggs);
411 EXPECT_TRUE(onef.isReady());
412 EXPECT_TRUE(onef.hasException());
416 TEST(Collect, alreadyCompleted) {
418 std::vector<Future<Unit>> fs;
419 for (int i = 0; i < 10; i++) {
420 fs.push_back(makeFuture());
424 .then([&](std::vector<Try<Unit>> ts) {
425 EXPECT_EQ(fs.size(), ts.size());
429 std::vector<Future<int>> fs;
430 for (int i = 0; i < 10; i++) {
431 fs.push_back(makeFuture(i));
435 .then([&](std::pair<size_t, Try<int>> p) {
436 EXPECT_EQ(p.first, p.second.value());
441 TEST(Collect, parallel) {
442 std::vector<Promise<int>> ps(10);
443 std::vector<Future<int>> fs;
444 for (size_t i = 0; i < ps.size(); i++) {
445 fs.emplace_back(ps[i].getFuture());
447 auto f = collect(fs);
449 std::vector<std::thread> ts;
450 boost::barrier barrier(ps.size() + 1);
451 for (size_t i = 0; i < ps.size(); i++) {
452 ts.emplace_back([&ps, &barrier, i]() {
460 for (size_t i = 0; i < ps.size(); i++) {
464 EXPECT_TRUE(f.isReady());
465 for (size_t i = 0; i < ps.size(); i++) {
466 EXPECT_EQ(i, f.value()[i]);
470 TEST(Collect, parallelWithError) {
471 std::vector<Promise<int>> ps(10);
472 std::vector<Future<int>> fs;
473 for (size_t i = 0; i < ps.size(); i++) {
474 fs.emplace_back(ps[i].getFuture());
476 auto f = collect(fs);
478 std::vector<std::thread> ts;
479 boost::barrier barrier(ps.size() + 1);
480 for (size_t i = 0; i < ps.size(); i++) {
481 ts.emplace_back([&ps, &barrier, i]() {
483 if (i == (ps.size()/2)) {
484 ps[i].setException(eggs);
493 for (size_t i = 0; i < ps.size(); i++) {
497 EXPECT_TRUE(f.isReady());
498 EXPECT_THROW(f.value(), eggs_t);
501 TEST(Collect, allParallel) {
502 std::vector<Promise<int>> ps(10);
503 std::vector<Future<int>> fs;
504 for (size_t i = 0; i < ps.size(); i++) {
505 fs.emplace_back(ps[i].getFuture());
507 auto f = collectAll(fs);
509 std::vector<std::thread> ts;
510 boost::barrier barrier(ps.size() + 1);
511 for (size_t i = 0; i < ps.size(); i++) {
512 ts.emplace_back([&ps, &barrier, i]() {
520 for (size_t i = 0; i < ps.size(); i++) {
524 EXPECT_TRUE(f.isReady());
525 for (size_t i = 0; i < ps.size(); i++) {
526 EXPECT_TRUE(f.value()[i].hasValue());
527 EXPECT_EQ(i, f.value()[i].value());
531 TEST(Collect, allParallelWithError) {
532 std::vector<Promise<int>> ps(10);
533 std::vector<Future<int>> fs;
534 for (size_t i = 0; i < ps.size(); i++) {
535 fs.emplace_back(ps[i].getFuture());
537 auto f = collectAll(fs);
539 std::vector<std::thread> ts;
540 boost::barrier barrier(ps.size() + 1);
541 for (size_t i = 0; i < ps.size(); i++) {
542 ts.emplace_back([&ps, &barrier, i]() {
544 if (i == (ps.size()/2)) {
545 ps[i].setException(eggs);
554 for (size_t i = 0; i < ps.size(); i++) {
558 EXPECT_TRUE(f.isReady());
559 for (size_t i = 0; i < ps.size(); i++) {
560 if (i == (ps.size()/2)) {
561 EXPECT_THROW(f.value()[i].value(), eggs_t);
563 EXPECT_TRUE(f.value()[i].hasValue());
564 EXPECT_EQ(i, f.value()[i].value());
569 TEST(Collect, collectN) {
570 std::vector<Promise<Unit>> promises(10);
571 std::vector<Future<Unit>> futures;
573 for (auto& p : promises) {
574 futures.push_back(p.getFuture());
580 .then([&](std::vector<std::pair<size_t, Try<Unit>>> v) {
582 EXPECT_EQ(n, v.size());
584 EXPECT_TRUE(tt.second.hasValue());
588 promises[0].setValue();
590 promises[1].setValue();
592 promises[2].setValue();
596 /// Ensure that we can compile collectAll/Any with folly::small_vector
597 TEST(Collect, smallVector) {
598 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<Unit>),
599 "Futures should not be trivially copyable");
600 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<int>),
601 "Futures should not be trivially copyable");
604 folly::small_vector<Future<Unit>> futures;
606 for (int i = 0; i < 10; i++) {
607 futures.push_back(makeFuture());
610 auto anyf = collectAny(futures);
613 folly::small_vector<Future<Unit>> futures;
615 for (int i = 0; i < 10; i++) {
616 futures.push_back(makeFuture());
619 auto allf = collectAll(futures);
623 TEST(Collect, collectAllVariadic) {
626 Future<bool> fb = pb.getFuture();
627 Future<int> fi = pi.getFuture();
629 collectAll(std::move(fb), std::move(fi))
630 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
632 EXPECT_TRUE(std::get<0>(tup).hasValue());
633 EXPECT_EQ(std::get<0>(tup).value(), true);
634 EXPECT_TRUE(std::get<1>(tup).hasValue());
635 EXPECT_EQ(std::get<1>(tup).value(), 42);
643 TEST(Collect, collectAllVariadicReferences) {
646 Future<bool> fb = pb.getFuture();
647 Future<int> fi = pi.getFuture();
650 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
652 EXPECT_TRUE(std::get<0>(tup).hasValue());
653 EXPECT_EQ(std::get<0>(tup).value(), true);
654 EXPECT_TRUE(std::get<1>(tup).hasValue());
655 EXPECT_EQ(std::get<1>(tup).value(), 42);
663 TEST(Collect, collectAllVariadicWithException) {
666 Future<bool> fb = pb.getFuture();
667 Future<int> fi = pi.getFuture();
669 collectAll(std::move(fb), std::move(fi))
670 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
672 EXPECT_TRUE(std::get<0>(tup).hasValue());
673 EXPECT_EQ(std::get<0>(tup).value(), true);
674 EXPECT_TRUE(std::get<1>(tup).hasException());
675 EXPECT_THROW(std::get<1>(tup).value(), eggs_t);
679 pi.setException(eggs);
683 TEST(Collect, collectVariadic) {
686 Future<bool> fb = pb.getFuture();
687 Future<int> fi = pi.getFuture();
689 collect(std::move(fb), std::move(fi))
690 .then([&](std::tuple<bool, int> tup) {
692 EXPECT_EQ(std::get<0>(tup), true);
693 EXPECT_EQ(std::get<1>(tup), 42);
701 TEST(Collect, collectVariadicWithException) {
704 Future<bool> fb = pb.getFuture();
705 Future<int> fi = pi.getFuture();
706 auto f = collect(std::move(fb), std::move(fi));
708 EXPECT_FALSE(f.isReady());
709 pi.setException(eggs);
710 EXPECT_TRUE(f.isReady());
711 EXPECT_TRUE(f.getTry().hasException());
712 EXPECT_THROW(f.get(), eggs_t);
715 TEST(Collect, collectAllNone) {
716 std::vector<Future<int>> fs;
717 auto f = collectAll(fs);
718 EXPECT_TRUE(f.isReady());
721 TEST(Collect, noDefaultConstructor) {
723 explicit A(size_t /* x */) {}
726 auto f1 = makeFuture(A(1));
727 auto f2 = makeFuture(A(2));
729 auto f = collect(std::move(f1), std::move(f2));