2 * Copyright 2014 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.
18 #include <folly/small_vector.h>
19 #include <gtest/gtest.h>
22 #include <type_traits>
24 #include "folly/wangle/Executor.h"
25 #include "folly/wangle/Future.h"
27 using namespace folly::wangle;
30 using std::unique_ptr;
33 #define EXPECT_TYPE(x, T) \
34 EXPECT_TRUE((std::is_same<decltype(x), T>::value))
36 typedef WangleException eggs_t;
37 static eggs_t eggs("eggs");
54 Try<A> t_a(std::move(a));
58 EXPECT_EQ(5, t_a.value().x());
61 TEST(Future, special) {
62 EXPECT_FALSE(std::is_copy_constructible<Future<int>>::value);
63 EXPECT_FALSE(std::is_copy_assignable<Future<int>>::value);
64 EXPECT_TRUE(std::is_move_constructible<Future<int>>::value);
65 EXPECT_TRUE(std::is_move_assignable<Future<int>>::value);
71 makeFuture<int>(42).then([&](Try<int>&& t) {
73 EXPECT_EQ(42, t.value());
75 EXPECT_TRUE(flag); flag = false;
78 .then([](Try<int>&& t) { return t.value(); })
79 .then([&](Try<int>&& t) { flag = true; EXPECT_EQ(42, t.value()); });
80 EXPECT_TRUE(flag); flag = false;
82 makeFuture().then([&](Try<void>&& t) { flag = true; t.value(); });
83 EXPECT_TRUE(flag); flag = false;
86 auto f = p.getFuture().then([&](Try<void>&& t) { flag = true; });
88 EXPECT_FALSE(f.isReady());
91 EXPECT_TRUE(f.isReady());
94 static string doWorkStatic(Try<string>&& t) {
95 return t.value() + ";static";
98 TEST(Future, thenFunction) {
100 string doWork(Try<string>&& t) {
101 return t.value() + ";class";
103 static string doWorkStatic(Try<string>&& t) {
104 return t.value() + ";class-static";
108 auto f = makeFuture<string>("start")
110 .then(Worker::doWorkStatic)
111 .then(&w, &Worker::doWork);
113 EXPECT_EQ(f.value(), "start;static;class-static;class");
116 static Future<string> doWorkStaticFuture(Try<string>&& t) {
117 return makeFuture(t.value() + ";static");
120 TEST(Future, thenFunctionFuture) {
122 Future<string> doWorkFuture(Try<string>&& t) {
123 return makeFuture(t.value() + ";class");
125 static Future<string> doWorkStaticFuture(Try<string>&& t) {
126 return makeFuture(t.value() + ";class-static");
130 auto f = makeFuture<string>("start")
131 .then(doWorkStaticFuture)
132 .then(Worker::doWorkStaticFuture)
133 .then(&w, &Worker::doWorkFuture);
135 EXPECT_EQ(f.value(), "start;static;class-static;class");
138 TEST(Future, value) {
139 auto f = makeFuture(unique_ptr<int>(new int(42)));
140 auto up = std::move(f.value());
143 EXPECT_THROW(makeFuture<int>(eggs).value(), eggs_t);
146 TEST(Future, isReady) {
148 auto f = p.getFuture();
149 EXPECT_FALSE(f.isReady());
151 EXPECT_TRUE(f.isReady());
154 TEST(Future, hasException) {
155 EXPECT_TRUE(makeFuture<int>(eggs).getTry().hasException());
156 EXPECT_FALSE(makeFuture(42).getTry().hasException());
159 TEST(Future, hasValue) {
160 EXPECT_TRUE(makeFuture(42).getTry().hasValue());
161 EXPECT_FALSE(makeFuture<int>(eggs).getTry().hasValue());
164 TEST(Future, makeFuture) {
165 EXPECT_TYPE(makeFuture(42), Future<int>);
166 EXPECT_EQ(42, makeFuture(42).value());
168 EXPECT_TYPE(makeFuture<float>(42), Future<float>);
169 EXPECT_EQ(42, makeFuture<float>(42).value());
171 auto fun = [] { return 42; };
172 EXPECT_TYPE(makeFutureTry(fun), Future<int>);
173 EXPECT_EQ(42, makeFutureTry(fun).value());
175 auto failfun = []() -> int { throw eggs; };
176 EXPECT_TYPE(makeFutureTry(failfun), Future<int>);
177 EXPECT_THROW(makeFutureTry(failfun).value(), eggs_t);
179 EXPECT_TYPE(makeFuture(), Future<void>);
184 TEST(Promise, special) {
185 EXPECT_FALSE(std::is_copy_constructible<Promise<int>>::value);
186 EXPECT_FALSE(std::is_copy_assignable<Promise<int>>::value);
187 EXPECT_TRUE(std::is_move_constructible<Promise<int>>::value);
188 EXPECT_TRUE(std::is_move_assignable<Promise<int>>::value);
191 TEST(Promise, getFuture) {
193 Future<int> f = p.getFuture();
194 EXPECT_FALSE(f.isReady());
197 TEST(Promise, setValue) {
199 auto ffund = fund.getFuture();
201 EXPECT_EQ(42, ffund.value());
209 auto fpod = pod.getFuture();
210 Foo f = {"the answer", 42};
212 Foo f2 = fpod.value();
213 EXPECT_EQ(f.name, f2.name);
214 EXPECT_EQ(f.value, f2.value);
216 pod = Promise<Foo>();
217 fpod = pod.getFuture();
218 pod.setValue(std::move(f2));
219 Foo f3 = fpod.value();
220 EXPECT_EQ(f.name, f3.name);
221 EXPECT_EQ(f.value, f3.value);
223 Promise<unique_ptr<int>> mov;
224 auto fmov = mov.getFuture();
225 mov.setValue(unique_ptr<int>(new int(42)));
226 unique_ptr<int> ptr = std::move(fmov.value());
230 auto fv = v.getFuture();
232 EXPECT_TRUE(fv.isReady());
235 TEST(Promise, setException) {
238 auto f = p.getFuture();
239 p.setException(eggs);
240 EXPECT_THROW(f.value(), eggs_t);
244 auto f = p.getFuture();
248 p.setException(std::current_exception());
250 EXPECT_THROW(f.value(), eggs_t);
254 TEST(Promise, fulfil) {
257 auto f = p.getFuture();
258 p.fulfil([] { return 42; });
259 EXPECT_EQ(42, f.value());
263 auto f = p.getFuture();
264 p.fulfil([]() -> int { throw eggs; });
265 EXPECT_THROW(f.value(), eggs_t);
269 TEST(Future, finish) {
270 auto x = std::make_shared<int>(0);
272 auto f = p.getFuture().then([x](Try<int>&& t) { *x = t.value(); });
274 // The continuation hasn't executed
277 // The continuation has a reference to x
278 EXPECT_EQ(2, x.use_count());
282 // the continuation has executed
285 // the continuation has been destructed
286 // and has released its reference to x
287 EXPECT_EQ(1, x.use_count());
290 TEST(Future, unwrap) {
294 auto fa = a.getFuture();
295 auto fb = b.getFuture();
300 // do a, then do b, and get the result of a + b.
301 Future<int> f = fa.then([&](Try<int>&& ta) {
302 auto va = ta.value();
304 return fb.then([va, &flag2](Try<int>&& tb) {
306 return va + tb.value();
312 EXPECT_FALSE(f.isReady());
317 EXPECT_FALSE(f.isReady());
322 EXPECT_EQ(7, f.value());
325 TEST(Future, whenAll) {
326 // returns a vector variant
328 vector<Promise<int>> promises(10);
329 vector<Future<int>> futures;
331 for (auto& p : promises)
332 futures.push_back(p.getFuture());
334 auto allf = whenAll(futures.begin(), futures.end());
336 random_shuffle(promises.begin(), promises.end());
337 for (auto& p : promises) {
338 EXPECT_FALSE(allf.isReady());
342 EXPECT_TRUE(allf.isReady());
343 auto& results = allf.value();
344 for (auto& t : results) {
345 EXPECT_EQ(42, t.value());
349 // check error semantics
351 vector<Promise<int>> promises(4);
352 vector<Future<int>> futures;
354 for (auto& p : promises)
355 futures.push_back(p.getFuture());
357 auto allf = whenAll(futures.begin(), futures.end());
360 promises[0].setValue(42);
361 promises[1].setException(eggs);
363 EXPECT_FALSE(allf.isReady());
365 promises[2].setValue(42);
367 EXPECT_FALSE(allf.isReady());
369 promises[3].setException(eggs);
371 EXPECT_TRUE(allf.isReady());
372 EXPECT_FALSE(allf.getTry().hasException());
374 auto& results = allf.value();
375 EXPECT_EQ(42, results[0].value());
376 EXPECT_TRUE(results[1].hasException());
377 EXPECT_EQ(42, results[2].value());
378 EXPECT_TRUE(results[3].hasException());
381 // check that futures are ready in then()
383 vector<Promise<void>> promises(10);
384 vector<Future<void>> futures;
386 for (auto& p : promises)
387 futures.push_back(p.getFuture());
389 auto allf = whenAll(futures.begin(), futures.end())
390 .then([](Try<vector<Try<void>>>&& ts) {
391 for (auto& f : ts.value())
395 random_shuffle(promises.begin(), promises.end());
396 for (auto& p : promises)
398 EXPECT_TRUE(allf.isReady());
403 TEST(Future, whenAny) {
405 vector<Promise<int>> promises(10);
406 vector<Future<int>> futures;
408 for (auto& p : promises)
409 futures.push_back(p.getFuture());
411 for (auto& f : futures) {
412 EXPECT_FALSE(f.isReady());
415 auto anyf = whenAny(futures.begin(), futures.end());
417 /* futures were moved in, so these are invalid now */
418 EXPECT_FALSE(anyf.isReady());
420 promises[7].setValue(42);
421 EXPECT_TRUE(anyf.isReady());
422 auto& idx_fut = anyf.value();
424 auto i = idx_fut.first;
427 auto& f = idx_fut.second;
428 EXPECT_EQ(42, f.value());
433 vector<Promise<void>> promises(10);
434 vector<Future<void>> futures;
436 for (auto& p : promises)
437 futures.push_back(p.getFuture());
439 for (auto& f : futures) {
440 EXPECT_FALSE(f.isReady());
443 auto anyf = whenAny(futures.begin(), futures.end());
445 EXPECT_FALSE(anyf.isReady());
447 promises[3].setException(eggs);
448 EXPECT_TRUE(anyf.isReady());
449 EXPECT_TRUE(anyf.value().second.hasException());
454 vector<Promise<int>> promises(10);
455 vector<Future<int>> futures;
457 for (auto& p : promises)
458 futures.push_back(p.getFuture());
460 auto anyf = whenAny(futures.begin(), futures.end())
461 .then([](Try<pair<size_t, Try<int>>>&& f) {
462 EXPECT_EQ(42, f.value().second.value());
465 promises[3].setValue(42);
466 EXPECT_TRUE(anyf.isReady());
471 TEST(when, already_completed) {
473 vector<Future<void>> fs;
474 for (int i = 0; i < 10; i++)
475 fs.push_back(makeFuture());
477 whenAll(fs.begin(), fs.end())
478 .then([&](Try<vector<Try<void>>>&& t) {
479 EXPECT_EQ(fs.size(), t.value().size());
483 vector<Future<int>> fs;
484 for (int i = 0; i < 10; i++)
485 fs.push_back(makeFuture(i));
487 whenAny(fs.begin(), fs.end())
488 .then([&](Try<pair<size_t, Try<int>>>&& t) {
490 EXPECT_EQ(p.first, p.second.value());
496 vector<Promise<void>> promises(10);
497 vector<Future<void>> futures;
499 for (auto& p : promises)
500 futures.push_back(p.getFuture());
504 whenN(futures.begin(), futures.end(), n)
505 .then([&](Try<vector<pair<size_t, Try<void>>>>&& t) {
508 EXPECT_EQ(n, v.size());
510 EXPECT_TRUE(tt.second.hasValue());
513 promises[0].setValue();
515 promises[1].setValue();
517 promises[2].setValue();
521 /* Ensure that we can compile when_{all,any} with folly::small_vector */
522 TEST(when, small_vector) {
524 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<void>),
525 "Futures should not be trivially copyable");
526 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<int>),
527 "Futures should not be trivially copyable");
529 using folly::small_vector;
531 small_vector<Future<void>> futures;
533 for (int i = 0; i < 10; i++)
534 futures.push_back(makeFuture());
536 auto anyf = whenAny(futures.begin(), futures.end());
540 small_vector<Future<void>> futures;
542 for (int i = 0; i < 10; i++)
543 futures.push_back(makeFuture());
545 auto allf = whenAll(futures.begin(), futures.end());
549 TEST(Future, whenAllVariadic) {
552 Future<bool> fb = pb.getFuture();
553 Future<int> fi = pi.getFuture();
555 whenAll(std::move(fb), std::move(fi))
556 .then([&](Try<std::tuple<Try<bool>, Try<int>>>&& t) {
558 EXPECT_TRUE(t.hasValue());
559 EXPECT_TRUE(std::get<0>(t.value()).hasValue());
560 EXPECT_EQ(std::get<0>(t.value()).value(), true);
561 EXPECT_TRUE(std::get<1>(t.value()).hasValue());
562 EXPECT_EQ(std::get<1>(t.value()).value(), 42);
570 TEST(Future, whenAllVariadicReferences) {
573 Future<bool> fb = pb.getFuture();
574 Future<int> fi = pi.getFuture();
577 .then([&](Try<std::tuple<Try<bool>, Try<int>>>&& t) {
579 EXPECT_TRUE(t.hasValue());
580 EXPECT_TRUE(std::get<0>(t.value()).hasValue());
581 EXPECT_EQ(std::get<0>(t.value()).value(), true);
582 EXPECT_TRUE(std::get<1>(t.value()).hasValue());
583 EXPECT_EQ(std::get<1>(t.value()).value(), 42);
591 TEST(Future, whenAll_none) {
592 vector<Future<int>> fs;
593 auto f = whenAll(fs.begin(), fs.end());
594 EXPECT_TRUE(f.isReady());
597 TEST(Future, throwCaughtInImmediateThen) {
598 // Neither of these should throw "Promise already satisfied"
600 [=](Try<void>&&) -> int { throw std::exception(); });
602 [=](Try<void>&&) -> Future<int> { throw std::exception(); });
605 TEST(Future, throwIfFailed) {
606 makeFuture<void>(eggs)
607 .then([=](Try<void>&& t) {
608 EXPECT_THROW(t.throwIfFailed(), eggs_t);
611 .then([=](Try<void>&& t) {
612 EXPECT_NO_THROW(t.throwIfFailed());
615 makeFuture<int>(eggs)
616 .then([=](Try<int>&& t) {
617 EXPECT_THROW(t.throwIfFailed(), eggs_t);
620 .then([=](Try<int>&& t) {
621 EXPECT_NO_THROW(t.throwIfFailed());