2 * Copyright 2016 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>
21 #include <boost/thread/barrier.hpp>
23 #include <folly/futures/Future.h>
24 #include <folly/Random.h>
25 #include <folly/small_vector.h>
27 using namespace folly;
29 typedef FutureException eggs_t;
30 static eggs_t eggs("eggs");
32 auto rng = std::mt19937(folly::randomNumberSeed());
34 TEST(Collect, collectAll) {
35 // returns a vector variant
37 std::vector<Promise<int>> promises(10);
38 std::vector<Future<int>> futures;
40 for (auto& p : promises)
41 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());
66 auto allf = collectAll(futures);
69 promises[0].setValue(42);
70 promises[1].setException(eggs);
72 EXPECT_FALSE(allf.isReady());
74 promises[2].setValue(42);
76 EXPECT_FALSE(allf.isReady());
78 promises[3].setException(eggs);
80 EXPECT_TRUE(allf.isReady());
81 EXPECT_FALSE(allf.getTry().hasException());
83 auto& results = allf.value();
84 EXPECT_EQ(42, results[0].value());
85 EXPECT_TRUE(results[1].hasException());
86 EXPECT_EQ(42, results[2].value());
87 EXPECT_TRUE(results[3].hasException());
90 // check that futures are ready in then()
92 std::vector<Promise<Unit>> promises(10);
93 std::vector<Future<Unit>> futures;
95 for (auto& p : promises)
96 futures.push_back(p.getFuture());
98 auto allf = collectAll(futures)
99 .then([](Try<std::vector<Try<Unit>>>&& ts) {
100 for (auto& f : ts.value())
104 std::shuffle(promises.begin(), promises.end(), rng);
105 for (auto& p : promises)
107 EXPECT_TRUE(allf.isReady());
111 TEST(Collect, collect) {
114 std::vector<Promise<int>> promises(10);
115 std::vector<Future<int>> futures;
117 for (auto& p : promises)
118 futures.push_back(p.getFuture());
120 auto allf = collect(futures);
122 std::shuffle(promises.begin(), promises.end(), rng);
123 for (auto& p : promises) {
124 EXPECT_FALSE(allf.isReady());
128 EXPECT_TRUE(allf.isReady());
129 for (auto i : allf.value()) {
136 std::vector<Promise<int>> promises(10);
137 std::vector<Future<int>> futures;
139 for (auto& p : promises)
140 futures.push_back(p.getFuture());
142 auto allf = collect(futures);
144 std::shuffle(promises.begin(), promises.end(), rng);
145 for (int i = 0; i < 10; i++) {
147 // everthing goes well so far...
148 EXPECT_FALSE(allf.isReady());
149 promises[i].setValue(42);
151 // short circuit with an exception
152 EXPECT_FALSE(allf.isReady());
153 promises[i].setException(eggs);
154 EXPECT_TRUE(allf.isReady());
156 // don't blow up on further values
157 EXPECT_TRUE(allf.isReady());
158 promises[i].setValue(42);
160 // don't blow up on further exceptions
161 EXPECT_TRUE(allf.isReady());
162 promises[i].setException(eggs);
166 EXPECT_THROW(allf.value(), eggs_t);
169 // void futures success case
171 std::vector<Promise<Unit>> promises(10);
172 std::vector<Future<Unit>> futures;
174 for (auto& p : promises)
175 futures.push_back(p.getFuture());
177 auto allf = collect(futures);
179 std::shuffle(promises.begin(), promises.end(), rng);
180 for (auto& p : promises) {
181 EXPECT_FALSE(allf.isReady());
185 EXPECT_TRUE(allf.isReady());
188 // void futures failure case
190 std::vector<Promise<Unit>> promises(10);
191 std::vector<Future<Unit>> futures;
193 for (auto& p : promises)
194 futures.push_back(p.getFuture());
196 auto allf = collect(futures);
198 std::shuffle(promises.begin(), promises.end(), rng);
199 for (int i = 0; i < 10; i++) {
201 // everthing goes well so far...
202 EXPECT_FALSE(allf.isReady());
203 promises[i].setValue();
205 // short circuit with an exception
206 EXPECT_FALSE(allf.isReady());
207 promises[i].setException(eggs);
208 EXPECT_TRUE(allf.isReady());
210 // don't blow up on further values
211 EXPECT_TRUE(allf.isReady());
212 promises[i].setValue();
214 // don't blow up on further exceptions
215 EXPECT_TRUE(allf.isReady());
216 promises[i].setException(eggs);
220 EXPECT_THROW(allf.value(), eggs_t);
223 // move only compiles
225 std::vector<Promise<std::unique_ptr<int>>> promises(10);
226 std::vector<Future<std::unique_ptr<int>>> futures;
228 for (auto& p : promises)
229 futures.push_back(p.getFuture());
236 struct NotDefaultConstructible {
237 NotDefaultConstructible() = delete;
238 explicit NotDefaultConstructible(int arg) : i(arg) {}
242 // We have a specialized implementation for non-default-constructible objects
243 // Ensure that it works and preserves order
244 TEST(Collect, collectNotDefaultConstructible) {
245 std::vector<Promise<NotDefaultConstructible>> promises(10);
246 std::vector<Future<NotDefaultConstructible>> futures;
247 std::vector<int> indices(10);
248 std::iota(indices.begin(), indices.end(), 0);
249 std::shuffle(indices.begin(), indices.end(), rng);
251 for (auto& p : promises)
252 futures.push_back(p.getFuture());
254 auto allf = collect(futures);
256 for (auto i : indices) {
257 EXPECT_FALSE(allf.isReady());
258 promises[i].setValue(NotDefaultConstructible(i));
261 EXPECT_TRUE(allf.isReady());
263 for (auto val : allf.value()) {
269 TEST(Collect, collectAny) {
271 std::vector<Promise<int>> promises(10);
272 std::vector<Future<int>> futures;
274 for (auto& p : promises)
275 futures.push_back(p.getFuture());
277 for (auto& f : futures) {
278 EXPECT_FALSE(f.isReady());
281 auto anyf = collectAny(futures);
283 /* futures were moved in, so these are invalid now */
284 EXPECT_FALSE(anyf.isReady());
286 promises[7].setValue(42);
287 EXPECT_TRUE(anyf.isReady());
288 auto& idx_fut = anyf.value();
290 auto i = idx_fut.first;
293 auto& f = idx_fut.second;
294 EXPECT_EQ(42, f.value());
299 std::vector<Promise<Unit>> promises(10);
300 std::vector<Future<Unit>> futures;
302 for (auto& p : promises)
303 futures.push_back(p.getFuture());
305 for (auto& f : futures) {
306 EXPECT_FALSE(f.isReady());
309 auto anyf = collectAny(futures);
311 EXPECT_FALSE(anyf.isReady());
313 promises[3].setException(eggs);
314 EXPECT_TRUE(anyf.isReady());
315 EXPECT_TRUE(anyf.value().second.hasException());
320 std::vector<Promise<int>> promises(10);
321 std::vector<Future<int>> futures;
323 for (auto& p : promises)
324 futures.push_back(p.getFuture());
326 auto anyf = collectAny(futures)
327 .then([](std::pair<size_t, Try<int>> p) {
328 EXPECT_EQ(42, p.second.value());
331 promises[3].setValue(42);
332 EXPECT_TRUE(anyf.isReady());
336 TEST(Collect, collectAnyWithoutException) {
338 std::vector<Promise<int>> promises(10);
339 std::vector<Future<int>> futures;
341 for (auto& p : promises) {
342 futures.push_back(p.getFuture());
345 auto onef = collectAnyWithoutException(futures);
347 /* futures were moved in, so these are invalid now */
348 EXPECT_FALSE(onef.isReady());
350 promises[7].setValue(42);
351 EXPECT_TRUE(onef.isReady());
352 auto& idx_fut = onef.value();
353 EXPECT_EQ(7, idx_fut.first);
354 EXPECT_EQ(42, idx_fut.second);
357 // some exception before ready
359 std::vector<Promise<int>> promises(10);
360 std::vector<Future<int>> futures;
362 for (auto& p : promises) {
363 futures.push_back(p.getFuture());
366 auto onef = collectAnyWithoutException(futures);
368 EXPECT_FALSE(onef.isReady());
370 promises[3].setException(eggs);
371 EXPECT_FALSE(onef.isReady());
372 promises[4].setException(eggs);
373 EXPECT_FALSE(onef.isReady());
374 promises[0].setValue(99);
375 EXPECT_TRUE(onef.isReady());
376 auto& idx_fut = onef.value();
377 EXPECT_EQ(0, idx_fut.first);
378 EXPECT_EQ(99, idx_fut.second);
383 std::vector<Promise<int>> promises(10);
384 std::vector<Future<int>> futures;
386 for (auto& p : promises) {
387 futures.push_back(p.getFuture());
390 auto onef = collectAnyWithoutException(futures);
392 EXPECT_FALSE(onef.isReady());
393 for (int i = 0; i < 9; ++i) {
394 promises[i].setException(eggs);
396 EXPECT_FALSE(onef.isReady());
398 promises[9].setException(eggs);
399 EXPECT_TRUE(onef.isReady());
400 EXPECT_TRUE(onef.hasException());
404 TEST(Collect, alreadyCompleted) {
406 std::vector<Future<Unit>> fs;
407 for (int i = 0; i < 10; i++)
408 fs.push_back(makeFuture());
411 .then([&](std::vector<Try<Unit>> ts) {
412 EXPECT_EQ(fs.size(), ts.size());
416 std::vector<Future<int>> fs;
417 for (int i = 0; i < 10; i++)
418 fs.push_back(makeFuture(i));
421 .then([&](std::pair<size_t, Try<int>> p) {
422 EXPECT_EQ(p.first, p.second.value());
427 TEST(Collect, parallel) {
428 std::vector<Promise<int>> ps(10);
429 std::vector<Future<int>> fs;
430 for (size_t i = 0; i < ps.size(); i++) {
431 fs.emplace_back(ps[i].getFuture());
433 auto f = collect(fs);
435 std::vector<std::thread> ts;
436 boost::barrier barrier(ps.size() + 1);
437 for (size_t i = 0; i < ps.size(); i++) {
438 ts.emplace_back([&ps, &barrier, i]() {
446 for (size_t i = 0; i < ps.size(); i++) {
450 EXPECT_TRUE(f.isReady());
451 for (size_t i = 0; i < ps.size(); i++) {
452 EXPECT_EQ(i, f.value()[i]);
456 TEST(Collect, parallelWithError) {
457 std::vector<Promise<int>> ps(10);
458 std::vector<Future<int>> fs;
459 for (size_t i = 0; i < ps.size(); i++) {
460 fs.emplace_back(ps[i].getFuture());
462 auto f = collect(fs);
464 std::vector<std::thread> ts;
465 boost::barrier barrier(ps.size() + 1);
466 for (size_t i = 0; i < ps.size(); i++) {
467 ts.emplace_back([&ps, &barrier, i]() {
469 if (i == (ps.size()/2)) {
470 ps[i].setException(eggs);
479 for (size_t i = 0; i < ps.size(); i++) {
483 EXPECT_TRUE(f.isReady());
484 EXPECT_THROW(f.value(), eggs_t);
487 TEST(Collect, allParallel) {
488 std::vector<Promise<int>> ps(10);
489 std::vector<Future<int>> fs;
490 for (size_t i = 0; i < ps.size(); i++) {
491 fs.emplace_back(ps[i].getFuture());
493 auto f = collectAll(fs);
495 std::vector<std::thread> ts;
496 boost::barrier barrier(ps.size() + 1);
497 for (size_t i = 0; i < ps.size(); i++) {
498 ts.emplace_back([&ps, &barrier, i]() {
506 for (size_t i = 0; i < ps.size(); i++) {
510 EXPECT_TRUE(f.isReady());
511 for (size_t i = 0; i < ps.size(); i++) {
512 EXPECT_TRUE(f.value()[i].hasValue());
513 EXPECT_EQ(i, f.value()[i].value());
517 TEST(Collect, allParallelWithError) {
518 std::vector<Promise<int>> ps(10);
519 std::vector<Future<int>> fs;
520 for (size_t i = 0; i < ps.size(); i++) {
521 fs.emplace_back(ps[i].getFuture());
523 auto f = collectAll(fs);
525 std::vector<std::thread> ts;
526 boost::barrier barrier(ps.size() + 1);
527 for (size_t i = 0; i < ps.size(); i++) {
528 ts.emplace_back([&ps, &barrier, i]() {
530 if (i == (ps.size()/2)) {
531 ps[i].setException(eggs);
540 for (size_t i = 0; i < ps.size(); i++) {
544 EXPECT_TRUE(f.isReady());
545 for (size_t i = 0; i < ps.size(); i++) {
546 if (i == (ps.size()/2)) {
547 EXPECT_THROW(f.value()[i].value(), eggs_t);
549 EXPECT_TRUE(f.value()[i].hasValue());
550 EXPECT_EQ(i, f.value()[i].value());
555 TEST(Collect, collectN) {
556 std::vector<Promise<Unit>> promises(10);
557 std::vector<Future<Unit>> futures;
559 for (auto& p : promises)
560 futures.push_back(p.getFuture());
565 .then([&](std::vector<std::pair<size_t, Try<Unit>>> v) {
567 EXPECT_EQ(n, v.size());
569 EXPECT_TRUE(tt.second.hasValue());
572 promises[0].setValue();
574 promises[1].setValue();
576 promises[2].setValue();
580 /// Ensure that we can compile collectAll/Any with folly::small_vector
581 TEST(Collect, smallVector) {
582 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<Unit>),
583 "Futures should not be trivially copyable");
584 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<int>),
585 "Futures should not be trivially copyable");
588 folly::small_vector<Future<Unit>> futures;
590 for (int i = 0; i < 10; i++)
591 futures.push_back(makeFuture());
593 auto anyf = collectAny(futures);
596 folly::small_vector<Future<Unit>> futures;
598 for (int i = 0; i < 10; i++)
599 futures.push_back(makeFuture());
601 auto allf = collectAll(futures);
605 TEST(Collect, collectAllVariadic) {
608 Future<bool> fb = pb.getFuture();
609 Future<int> fi = pi.getFuture();
611 collectAll(std::move(fb), std::move(fi))
612 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
614 EXPECT_TRUE(std::get<0>(tup).hasValue());
615 EXPECT_EQ(std::get<0>(tup).value(), true);
616 EXPECT_TRUE(std::get<1>(tup).hasValue());
617 EXPECT_EQ(std::get<1>(tup).value(), 42);
625 TEST(Collect, collectAllVariadicReferences) {
628 Future<bool> fb = pb.getFuture();
629 Future<int> fi = pi.getFuture();
632 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
634 EXPECT_TRUE(std::get<0>(tup).hasValue());
635 EXPECT_EQ(std::get<0>(tup).value(), true);
636 EXPECT_TRUE(std::get<1>(tup).hasValue());
637 EXPECT_EQ(std::get<1>(tup).value(), 42);
645 TEST(Collect, collectAllVariadicWithException) {
648 Future<bool> fb = pb.getFuture();
649 Future<int> fi = pi.getFuture();
651 collectAll(std::move(fb), std::move(fi))
652 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
654 EXPECT_TRUE(std::get<0>(tup).hasValue());
655 EXPECT_EQ(std::get<0>(tup).value(), true);
656 EXPECT_TRUE(std::get<1>(tup).hasException());
657 EXPECT_THROW(std::get<1>(tup).value(), eggs_t);
661 pi.setException(eggs);
665 TEST(Collect, collectVariadic) {
668 Future<bool> fb = pb.getFuture();
669 Future<int> fi = pi.getFuture();
671 collect(std::move(fb), std::move(fi))
672 .then([&](std::tuple<bool, int> tup) {
674 EXPECT_EQ(std::get<0>(tup), true);
675 EXPECT_EQ(std::get<1>(tup), 42);
683 TEST(Collect, collectVariadicWithException) {
686 Future<bool> fb = pb.getFuture();
687 Future<int> fi = pi.getFuture();
688 auto f = collect(std::move(fb), std::move(fi));
690 EXPECT_FALSE(f.isReady());
691 pi.setException(eggs);
692 EXPECT_TRUE(f.isReady());
693 EXPECT_TRUE(f.getTry().hasException());
694 EXPECT_THROW(f.get(), eggs_t);
697 TEST(Collect, collectAllNone) {
698 std::vector<Future<int>> fs;
699 auto f = collectAll(fs);
700 EXPECT_TRUE(f.isReady());
703 TEST(Collect, noDefaultConstructor) {
705 explicit A(size_t /* x */) {}
708 auto f1 = makeFuture(A(1));
709 auto f2 = makeFuture(A(2));
711 auto f = collect(std::move(f1), std::move(f2));