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 <boost/thread/barrier.hpp>
21 #include <folly/futures/Future.h>
22 #include <folly/Random.h>
23 #include <folly/small_vector.h>
25 using namespace folly;
27 typedef FutureException eggs_t;
28 static eggs_t eggs("eggs");
30 auto rng = std::mt19937(folly::randomNumberSeed());
32 TEST(Collect, collectAll) {
33 // returns a vector variant
35 std::vector<Promise<int>> promises(10);
36 std::vector<Future<int>> futures;
38 for (auto& p : promises)
39 futures.push_back(p.getFuture());
41 auto allf = collectAll(futures);
43 std::shuffle(promises.begin(), promises.end(), rng);
44 for (auto& p : promises) {
45 EXPECT_FALSE(allf.isReady());
49 EXPECT_TRUE(allf.isReady());
50 auto& results = allf.value();
51 for (auto& t : results) {
52 EXPECT_EQ(42, t.value());
56 // check error semantics
58 std::vector<Promise<int>> promises(4);
59 std::vector<Future<int>> futures;
61 for (auto& p : promises)
62 futures.push_back(p.getFuture());
64 auto allf = collectAll(futures);
67 promises[0].setValue(42);
68 promises[1].setException(eggs);
70 EXPECT_FALSE(allf.isReady());
72 promises[2].setValue(42);
74 EXPECT_FALSE(allf.isReady());
76 promises[3].setException(eggs);
78 EXPECT_TRUE(allf.isReady());
79 EXPECT_FALSE(allf.getTry().hasException());
81 auto& results = allf.value();
82 EXPECT_EQ(42, results[0].value());
83 EXPECT_TRUE(results[1].hasException());
84 EXPECT_EQ(42, results[2].value());
85 EXPECT_TRUE(results[3].hasException());
88 // check that futures are ready in then()
90 std::vector<Promise<Unit>> promises(10);
91 std::vector<Future<Unit>> futures;
93 for (auto& p : promises)
94 futures.push_back(p.getFuture());
96 auto allf = collectAll(futures)
97 .then([](Try<std::vector<Try<Unit>>>&& ts) {
98 for (auto& f : ts.value())
102 std::shuffle(promises.begin(), promises.end(), rng);
103 for (auto& p : promises)
105 EXPECT_TRUE(allf.isReady());
109 TEST(Collect, collect) {
112 std::vector<Promise<int>> promises(10);
113 std::vector<Future<int>> futures;
115 for (auto& p : promises)
116 futures.push_back(p.getFuture());
118 auto allf = collect(futures);
120 std::shuffle(promises.begin(), promises.end(), rng);
121 for (auto& p : promises) {
122 EXPECT_FALSE(allf.isReady());
126 EXPECT_TRUE(allf.isReady());
127 for (auto i : allf.value()) {
134 std::vector<Promise<int>> promises(10);
135 std::vector<Future<int>> futures;
137 for (auto& p : promises)
138 futures.push_back(p.getFuture());
140 auto allf = collect(futures);
142 std::shuffle(promises.begin(), promises.end(), rng);
143 for (int i = 0; i < 10; i++) {
145 // everthing goes well so far...
146 EXPECT_FALSE(allf.isReady());
147 promises[i].setValue(42);
149 // short circuit with an exception
150 EXPECT_FALSE(allf.isReady());
151 promises[i].setException(eggs);
152 EXPECT_TRUE(allf.isReady());
154 // don't blow up on further values
155 EXPECT_TRUE(allf.isReady());
156 promises[i].setValue(42);
158 // don't blow up on further exceptions
159 EXPECT_TRUE(allf.isReady());
160 promises[i].setException(eggs);
164 EXPECT_THROW(allf.value(), eggs_t);
167 // void futures success case
169 std::vector<Promise<Unit>> promises(10);
170 std::vector<Future<Unit>> futures;
172 for (auto& p : promises)
173 futures.push_back(p.getFuture());
175 auto allf = collect(futures);
177 std::shuffle(promises.begin(), promises.end(), rng);
178 for (auto& p : promises) {
179 EXPECT_FALSE(allf.isReady());
183 EXPECT_TRUE(allf.isReady());
186 // void futures failure case
188 std::vector<Promise<Unit>> promises(10);
189 std::vector<Future<Unit>> futures;
191 for (auto& p : promises)
192 futures.push_back(p.getFuture());
194 auto allf = collect(futures);
196 std::shuffle(promises.begin(), promises.end(), rng);
197 for (int i = 0; i < 10; i++) {
199 // everthing goes well so far...
200 EXPECT_FALSE(allf.isReady());
201 promises[i].setValue();
203 // short circuit with an exception
204 EXPECT_FALSE(allf.isReady());
205 promises[i].setException(eggs);
206 EXPECT_TRUE(allf.isReady());
208 // don't blow up on further values
209 EXPECT_TRUE(allf.isReady());
210 promises[i].setValue();
212 // don't blow up on further exceptions
213 EXPECT_TRUE(allf.isReady());
214 promises[i].setException(eggs);
218 EXPECT_THROW(allf.value(), eggs_t);
221 // move only compiles
223 std::vector<Promise<std::unique_ptr<int>>> promises(10);
224 std::vector<Future<std::unique_ptr<int>>> futures;
226 for (auto& p : promises)
227 futures.push_back(p.getFuture());
234 struct NotDefaultConstructible {
235 NotDefaultConstructible() = delete;
236 explicit NotDefaultConstructible(int arg) : i(arg) {}
240 // We have a specialized implementation for non-default-constructible objects
241 // Ensure that it works and preserves order
242 TEST(Collect, collectNotDefaultConstructible) {
243 std::vector<Promise<NotDefaultConstructible>> promises(10);
244 std::vector<Future<NotDefaultConstructible>> futures;
245 std::vector<int> indices(10);
246 std::iota(indices.begin(), indices.end(), 0);
247 std::shuffle(indices.begin(), indices.end(), rng);
249 for (auto& p : promises)
250 futures.push_back(p.getFuture());
252 auto allf = collect(futures);
254 for (auto i : indices) {
255 EXPECT_FALSE(allf.isReady());
256 promises[i].setValue(NotDefaultConstructible(i));
259 EXPECT_TRUE(allf.isReady());
261 for (auto val : allf.value()) {
267 TEST(Collect, collectAny) {
269 std::vector<Promise<int>> promises(10);
270 std::vector<Future<int>> futures;
272 for (auto& p : promises)
273 futures.push_back(p.getFuture());
275 for (auto& f : futures) {
276 EXPECT_FALSE(f.isReady());
279 auto anyf = collectAny(futures);
281 /* futures were moved in, so these are invalid now */
282 EXPECT_FALSE(anyf.isReady());
284 promises[7].setValue(42);
285 EXPECT_TRUE(anyf.isReady());
286 auto& idx_fut = anyf.value();
288 auto i = idx_fut.first;
291 auto& f = idx_fut.second;
292 EXPECT_EQ(42, f.value());
297 std::vector<Promise<Unit>> promises(10);
298 std::vector<Future<Unit>> futures;
300 for (auto& p : promises)
301 futures.push_back(p.getFuture());
303 for (auto& f : futures) {
304 EXPECT_FALSE(f.isReady());
307 auto anyf = collectAny(futures);
309 EXPECT_FALSE(anyf.isReady());
311 promises[3].setException(eggs);
312 EXPECT_TRUE(anyf.isReady());
313 EXPECT_TRUE(anyf.value().second.hasException());
318 std::vector<Promise<int>> promises(10);
319 std::vector<Future<int>> futures;
321 for (auto& p : promises)
322 futures.push_back(p.getFuture());
324 auto anyf = collectAny(futures)
325 .then([](std::pair<size_t, Try<int>> p) {
326 EXPECT_EQ(42, p.second.value());
329 promises[3].setValue(42);
330 EXPECT_TRUE(anyf.isReady());
335 TEST(Collect, alreadyCompleted) {
337 std::vector<Future<Unit>> fs;
338 for (int i = 0; i < 10; i++)
339 fs.push_back(makeFuture());
342 .then([&](std::vector<Try<Unit>> ts) {
343 EXPECT_EQ(fs.size(), ts.size());
347 std::vector<Future<int>> fs;
348 for (int i = 0; i < 10; i++)
349 fs.push_back(makeFuture(i));
352 .then([&](std::pair<size_t, Try<int>> p) {
353 EXPECT_EQ(p.first, p.second.value());
358 TEST(Collect, parallel) {
359 std::vector<Promise<int>> ps(10);
360 std::vector<Future<int>> fs;
361 for (size_t i = 0; i < ps.size(); i++) {
362 fs.emplace_back(ps[i].getFuture());
364 auto f = collect(fs);
366 std::vector<std::thread> ts;
367 boost::barrier barrier(ps.size() + 1);
368 for (size_t i = 0; i < ps.size(); i++) {
369 ts.emplace_back([&ps, &barrier, i]() {
377 for (size_t i = 0; i < ps.size(); i++) {
381 EXPECT_TRUE(f.isReady());
382 for (size_t i = 0; i < ps.size(); i++) {
383 EXPECT_EQ(i, f.value()[i]);
387 TEST(Collect, parallelWithError) {
388 std::vector<Promise<int>> ps(10);
389 std::vector<Future<int>> fs;
390 for (size_t i = 0; i < ps.size(); i++) {
391 fs.emplace_back(ps[i].getFuture());
393 auto f = collect(fs);
395 std::vector<std::thread> ts;
396 boost::barrier barrier(ps.size() + 1);
397 for (size_t i = 0; i < ps.size(); i++) {
398 ts.emplace_back([&ps, &barrier, i]() {
400 if (i == (ps.size()/2)) {
401 ps[i].setException(eggs);
410 for (size_t i = 0; i < ps.size(); i++) {
414 EXPECT_TRUE(f.isReady());
415 EXPECT_THROW(f.value(), eggs_t);
418 TEST(Collect, allParallel) {
419 std::vector<Promise<int>> ps(10);
420 std::vector<Future<int>> fs;
421 for (size_t i = 0; i < ps.size(); i++) {
422 fs.emplace_back(ps[i].getFuture());
424 auto f = collectAll(fs);
426 std::vector<std::thread> ts;
427 boost::barrier barrier(ps.size() + 1);
428 for (size_t i = 0; i < ps.size(); i++) {
429 ts.emplace_back([&ps, &barrier, i]() {
437 for (size_t i = 0; i < ps.size(); i++) {
441 EXPECT_TRUE(f.isReady());
442 for (size_t i = 0; i < ps.size(); i++) {
443 EXPECT_TRUE(f.value()[i].hasValue());
444 EXPECT_EQ(i, f.value()[i].value());
448 TEST(Collect, allParallelWithError) {
449 std::vector<Promise<int>> ps(10);
450 std::vector<Future<int>> fs;
451 for (size_t i = 0; i < ps.size(); i++) {
452 fs.emplace_back(ps[i].getFuture());
454 auto f = collectAll(fs);
456 std::vector<std::thread> ts;
457 boost::barrier barrier(ps.size() + 1);
458 for (size_t i = 0; i < ps.size(); i++) {
459 ts.emplace_back([&ps, &barrier, i]() {
461 if (i == (ps.size()/2)) {
462 ps[i].setException(eggs);
471 for (size_t i = 0; i < ps.size(); i++) {
475 EXPECT_TRUE(f.isReady());
476 for (size_t i = 0; i < ps.size(); i++) {
477 if (i == (ps.size()/2)) {
478 EXPECT_THROW(f.value()[i].value(), eggs_t);
480 EXPECT_TRUE(f.value()[i].hasValue());
481 EXPECT_EQ(i, f.value()[i].value());
486 TEST(Collect, collectN) {
487 std::vector<Promise<Unit>> promises(10);
488 std::vector<Future<Unit>> futures;
490 for (auto& p : promises)
491 futures.push_back(p.getFuture());
496 .then([&](std::vector<std::pair<size_t, Try<Unit>>> v) {
498 EXPECT_EQ(n, v.size());
500 EXPECT_TRUE(tt.second.hasValue());
503 promises[0].setValue();
505 promises[1].setValue();
507 promises[2].setValue();
511 /// Ensure that we can compile collectAll/Any with folly::small_vector
512 TEST(Collect, smallVector) {
513 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<Unit>),
514 "Futures should not be trivially copyable");
515 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<int>),
516 "Futures should not be trivially copyable");
519 folly::small_vector<Future<Unit>> futures;
521 for (int i = 0; i < 10; i++)
522 futures.push_back(makeFuture());
524 auto anyf = collectAny(futures);
527 folly::small_vector<Future<Unit>> futures;
529 for (int i = 0; i < 10; i++)
530 futures.push_back(makeFuture());
532 auto allf = collectAll(futures);
536 TEST(Collect, collectAllVariadic) {
539 Future<bool> fb = pb.getFuture();
540 Future<int> fi = pi.getFuture();
542 collectAll(std::move(fb), std::move(fi))
543 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
545 EXPECT_TRUE(std::get<0>(tup).hasValue());
546 EXPECT_EQ(std::get<0>(tup).value(), true);
547 EXPECT_TRUE(std::get<1>(tup).hasValue());
548 EXPECT_EQ(std::get<1>(tup).value(), 42);
556 TEST(Collect, collectAllVariadicReferences) {
559 Future<bool> fb = pb.getFuture();
560 Future<int> fi = pi.getFuture();
563 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
565 EXPECT_TRUE(std::get<0>(tup).hasValue());
566 EXPECT_EQ(std::get<0>(tup).value(), true);
567 EXPECT_TRUE(std::get<1>(tup).hasValue());
568 EXPECT_EQ(std::get<1>(tup).value(), 42);
576 TEST(Collect, collectAllVariadicWithException) {
579 Future<bool> fb = pb.getFuture();
580 Future<int> fi = pi.getFuture();
582 collectAll(std::move(fb), std::move(fi))
583 .then([&](std::tuple<Try<bool>, Try<int>> tup) {
585 EXPECT_TRUE(std::get<0>(tup).hasValue());
586 EXPECT_EQ(std::get<0>(tup).value(), true);
587 EXPECT_TRUE(std::get<1>(tup).hasException());
588 EXPECT_THROW(std::get<1>(tup).value(), eggs_t);
592 pi.setException(eggs);
596 TEST(Collect, collectVariadic) {
599 Future<bool> fb = pb.getFuture();
600 Future<int> fi = pi.getFuture();
602 collect(std::move(fb), std::move(fi))
603 .then([&](std::tuple<bool, int> tup) {
605 EXPECT_EQ(std::get<0>(tup), true);
606 EXPECT_EQ(std::get<1>(tup), 42);
614 TEST(Collect, collectVariadicWithException) {
617 Future<bool> fb = pb.getFuture();
618 Future<int> fi = pi.getFuture();
619 auto f = collect(std::move(fb), std::move(fi));
621 EXPECT_FALSE(f.isReady());
622 pi.setException(eggs);
623 EXPECT_TRUE(f.isReady());
624 EXPECT_TRUE(f.getTry().hasException());
625 EXPECT_THROW(f.get(), eggs_t);
628 TEST(Collect, collectAllNone) {
629 std::vector<Future<int>> fs;
630 auto f = collectAll(fs);
631 EXPECT_TRUE(f.isReady());
634 TEST(Collect, noDefaultConstructor) {
636 explicit A(size_t /* x */) {}
639 auto f1 = makeFuture(A(1));
640 auto f2 = makeFuture(A(2));
642 auto f = collect(std::move(f1), std::move(f2));