1/*
2 * Copyright 2014-present Facebook, Inc.
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17#include <folly/futures/Future.h>
18#include <folly/Executor.h>
19#include <folly/Memory.h>
20#include <folly/Unit.h>
21#include <folly/dynamic.h>
22#include <folly/executors/ManualExecutor.h>
23#include <folly/portability/GTest.h>
24#include <folly/synchronization/Baton.h>
25
26#include <algorithm>
27#include <atomic>
28#include <memory>
29#include <numeric>
30#include <queue>
31#include <string>
32#include <thread>
33#include <type_traits>
34
35using namespace folly;
36
37#define EXPECT_TYPE(x, T) EXPECT_TRUE((std::is_same<decltype(x), T>::value))
38
39typedef FutureException eggs_t;
40static eggs_t eggs("eggs");
41
42// Future
43
44TEST(Future, makeEmpty) {
45 auto f = Future<int>::makeEmpty();
46 EXPECT_THROW(f.isReady(), FutureInvalid);
47}
48
49TEST(Future, futureDefaultCtor) {
50 Future<Unit>();
51}
52
53TEST(Future, futureToUnit) {
54 Future<Unit> fu = makeFuture(42).unit();
55 fu.value();
56 EXPECT_TRUE(makeFuture<int>(eggs).unit().hasException());
57}
58
59TEST(Future, voidFutureToUnit) {
60 Future<Unit> fu = makeFuture().unit();
61 fu.value();
62 EXPECT_TRUE(makeFuture<Unit>(eggs).unit().hasException());
63}
64
65TEST(Future, unitFutureToUnitIdentity) {
66 Future<Unit> fu = makeFuture(Unit{}).unit();
67 fu.value();
68 EXPECT_TRUE(makeFuture<Unit>(eggs).unit().hasException());
69}
70
71TEST(Future, toUnitWhileInProgress) {
72 Promise<int> p;
73 Future<Unit> fu = p.getFuture().unit();
74 EXPECT_FALSE(fu.isReady());
75 p.setValue(42);
76 EXPECT_TRUE(fu.isReady());
77}
78
79TEST(Future, makeFutureWithUnit) {
80 int count = 0;
81 Future<Unit> fu = makeFutureWith([&] { count++; });
82 EXPECT_EQ(1, count);
83}
84
85TEST(Future, getRequiresOnlyMoveCtor) {
86 struct MoveCtorOnly {
87 explicit MoveCtorOnly(int id) : id_(id) {}
88 MoveCtorOnly(const MoveCtorOnly&) = delete;
89 MoveCtorOnly(MoveCtorOnly&&) = default;
90 void operator=(MoveCtorOnly const&) = delete;
91 void operator=(MoveCtorOnly&&) = delete;
92 int id_;
93 };
94 {
95 auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
96 EXPECT_TRUE(f.valid());
97 EXPECT_TRUE(f.isReady());
98 auto v = std::move(f).get();
99 EXPECT_EQ(v.id_, 42);
100 }
101 {
102 auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
103 EXPECT_TRUE(f.valid());
104 EXPECT_TRUE(f.isReady());
105 auto v = std::move(f).get();
106 EXPECT_EQ(v.id_, 42);
107 }
108 {
109 auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
110 EXPECT_TRUE(f.valid());
111 EXPECT_TRUE(f.isReady());
112 auto v = std::move(f).get(std::chrono::milliseconds(10));
113 EXPECT_EQ(v.id_, 42);
114 }
115 {
116 auto f = makeFuture<MoveCtorOnly>(MoveCtorOnly(42));
117 EXPECT_TRUE(f.valid());
118 EXPECT_TRUE(f.isReady());
119 auto v = std::move(f).get(std::chrono::milliseconds(10));
120 EXPECT_EQ(v.id_, 42);
121 }
122}
123
124namespace {
125auto makeValid() {
126 auto valid = makeFuture<int>(42);
127 EXPECT_TRUE(valid.valid());
128 return valid;
129}
130auto makeInvalid() {
131 auto invalid = Future<int>::makeEmpty();
132 EXPECT_FALSE(invalid.valid());
133 return invalid;
134}
135} // namespace
136
137TEST(Future, ctorPostconditionValid) {
138 // Ctors/factories that promise valid -- postcondition: valid()
139
140#define DOIT(CREATION_EXPR) \
141 do { \
142 auto f1 = (CREATION_EXPR); \
143 EXPECT_TRUE(f1.valid()); \
144 auto f2 = std::move(f1); \
145 EXPECT_FALSE(f1.valid()); \
146 EXPECT_TRUE(f2.valid()); \
147 } while (false)
148
149 auto const except = std::logic_error("foo");
150 auto const ewrap = folly::exception_wrapper(except);
151
152 DOIT(makeValid());
153 DOIT(Future<int>(42));
154 DOIT(Future<int>{42});
155 DOIT(Future<Unit>());
156 DOIT(Future<Unit>{});
157 DOIT(makeFuture());
158 DOIT(makeFuture(Unit{}));
159 DOIT(makeFuture<Unit>(Unit{}));
160 DOIT(makeFuture(42));
161 DOIT(makeFuture<int>(42));
162 DOIT(makeFuture<int>(except));
163 DOIT(makeFuture<int>(ewrap));
164 DOIT(makeFuture(Try<int>(42)));
165 DOIT(makeFuture<int>(Try<int>(42)));
166 DOIT(makeFuture<int>(Try<int>(ewrap)));
167
168#undef DOIT
169}
170
171TEST(Future, ctorPostconditionInvalid) {
172 // Ctors/factories that promise invalid -- postcondition: !valid()
173
174#define DOIT(CREATION_EXPR) \
175 do { \
176 auto f1 = (CREATION_EXPR); \
177 EXPECT_FALSE(f1.valid()); \
178 auto f2 = std::move(f1); \
179 EXPECT_FALSE(f1.valid()); \
180 EXPECT_FALSE(f2.valid()); \
181 } while (false)
182
183 DOIT(makeInvalid());
184 DOIT(Future<int>::makeEmpty());
185
186#undef DOIT
187}
188
189TEST(Future, lacksPreconditionValid) {
190 // Ops that don't throw FutureInvalid if !valid() --
191 // without precondition: valid()
192
193#define DOIT(STMT) \
194 do { \
195 auto f = makeValid(); \
196 { STMT; } \
197 copy(std::move(f)); \
198 EXPECT_NO_THROW(STMT); \
199 } while (false)
200
201 // .valid() itself
202 DOIT(f.valid());
203
204 // move-ctor - move-copy to local, copy(), pass-by-move-value
205 DOIT(auto other = std::move(f));
206 DOIT(copy(std::move(f)));
207 DOIT(([](auto) {})(std::move(f)));
208
209 // move-assignment into either {valid | invalid}
210 DOIT({
211 auto other = makeValid();
212 other = std::move(f);
213 });
214 DOIT({
215 auto other = makeInvalid();
216 other = std::move(f);
217 });
218
219#undef DOIT
220}
221
222TEST(Future, hasPreconditionValid) {
223 // Ops that require validity; precondition: valid();
224 // throw FutureInvalid if !valid()
225
226#define DOIT(STMT) \
227 do { \
228 auto f = makeValid(); \
229 EXPECT_NO_THROW(STMT); \
230 copy(std::move(f)); \
231 EXPECT_THROW(STMT, FutureInvalid); \
232 } while (false)
233
234 DOIT(f.isReady());
235 DOIT(f.result());
236 DOIT(std::move(f).get());
237 DOIT(std::move(f).get(std::chrono::milliseconds(10)));
238 DOIT(f.getTry());
239 DOIT(f.hasValue());
240 DOIT(f.hasException());
241 DOIT(f.value());
242 DOIT(f.poll());
243 DOIT(std::move(f).then());
244 DOIT(std::move(f).thenValue([](auto&&) {}));
245
246#undef DOIT
247}
248
249TEST(Future, hasPostconditionValid) {
250 // Ops that preserve validity -- postcondition: valid()
251
252#define DOIT(STMT) \
253 do { \
254 auto f = makeValid(); \
255 EXPECT_NO_THROW(STMT); \
256 EXPECT_TRUE(f.valid()); \
257 } while (false)
258
259 auto const swallow = [](auto) {};
260
261 DOIT(swallow(f.valid())); // f.valid() itself preserves validity
262 DOIT(swallow(f.isReady()));
263 DOIT(swallow(f.hasValue()));
264 DOIT(swallow(f.hasException()));
265 DOIT(swallow(f.value()));
266 DOIT(swallow(f.getTry()));
267 DOIT(swallow(f.poll()));
268 DOIT(f.raise(std::logic_error("foo")));
269 DOIT(f.cancel());
270 DOIT(swallow(f.getTry()));
271 DOIT(f.wait());
272 DOIT(std::move(f.wait()));
273
274#undef DOIT
275}
276
277TEST(Future, hasPostconditionInvalid) {
278 // Ops that consume *this -- postcondition: !valid()
279
280#define DOIT(CTOR, STMT) \
281 do { \
282 auto f = (CTOR); \
283 EXPECT_NO_THROW(STMT); \
284 EXPECT_FALSE(f.valid()); \
285 } while (false)
286
287 // move-ctor of {valid|invalid}
288 DOIT(makeValid(), { auto other{std::move(f)}; });
289 DOIT(makeInvalid(), { auto other{std::move(f)}; });
290
291 // move-assignment of {valid|invalid} into {valid|invalid}
292 DOIT(makeValid(), {
293 auto other = makeValid();
294 other = std::move(f);
295 });
296 DOIT(makeValid(), {
297 auto other = makeInvalid();
298 other = std::move(f);
299 });
300 DOIT(makeInvalid(), {
301 auto other = makeValid();
302 other = std::move(f);
303 });
304 DOIT(makeInvalid(), {
305 auto other = makeInvalid();
306 other = std::move(f);
307 });
308
309 // pass-by-value of {valid|invalid}
310 DOIT(makeValid(), {
311 auto const byval = [](auto) {};
312 byval(std::move(f));
313 });
314 DOIT(makeInvalid(), {
315 auto const byval = [](auto) {};
316 byval(std::move(f));
317 });
318
319 // other consuming ops
320 auto const swallow = [](auto) {};
321 DOIT(makeValid(), swallow(std::move(f).wait()));
322 DOIT(makeValid(), swallow(std::move(f.wait())));
323 DOIT(makeValid(), swallow(std::move(f).get()));
324 DOIT(makeValid(), swallow(std::move(f).get(std::chrono::milliseconds(10))));
325 DOIT(makeValid(), swallow(std::move(f).semi()));
326
327#undef DOIT
328}
329
330namespace {
331Future<int> onErrorHelperEggs(const eggs_t&) {
332 return makeFuture(10);
333}
334Future<int> onErrorHelperGeneric(const std::exception&) {
335 return makeFuture(20);
336}
337Future<int> onErrorHelperWrapper(folly::exception_wrapper&&) {
338 return makeFuture(30);
339}
340} // namespace
341
342TEST(Future, onError) {
343 bool theFlag = false;
344 auto flag = [&] { theFlag = true; };
345#define EXPECT_FLAG() \
346 do { \
347 EXPECT_TRUE(theFlag); \
348 theFlag = false; \
349 } while (0);
350
351#define EXPECT_NO_FLAG() \
352 do { \
353 EXPECT_FALSE(theFlag); \
354 theFlag = false; \
355 } while (0);
356
357 // By reference
358 {
359 auto f = makeFuture()
360 .thenValue([](auto&&) { throw eggs; })
361 .onError([&](eggs_t& /* e */) { flag(); });
362 EXPECT_FLAG();
363 EXPECT_NO_THROW(f.value());
364 }
365
366 {
367 auto f = makeFuture()
368 .thenValue([](auto&&) { throw eggs; })
369 .onError([&](eggs_t& /* e */) {
370 flag();
371 return makeFuture();
372 });
373 EXPECT_FLAG();
374 EXPECT_NO_THROW(f.value());
375 }
376
377 // By value
378 {
379 auto f = makeFuture()
380 .thenValue([](auto&&) { throw eggs; })
381 .onError([&](eggs_t /* e */) { flag(); });
382 EXPECT_FLAG();
383 EXPECT_NO_THROW(f.value());
384 }
385
386 {
387 auto f = makeFuture()
388 .thenValue([](auto&&) { throw eggs; })
389 .onError([&](eggs_t /* e */) {
390 flag();
391 return makeFuture();
392 });
393 EXPECT_FLAG();
394 EXPECT_NO_THROW(f.value());
395 }
396
397 // Polymorphic
398 {
399 auto f = makeFuture()
400 .thenValue([](auto&&) { throw eggs; })
401 .onError([&](std::exception& /* e */) { flag(); });
402 EXPECT_FLAG();
403 EXPECT_NO_THROW(f.value());
404 }
405
406 {
407 auto f = makeFuture()
408 .thenValue([](auto&&) { throw eggs; })
409 .onError([&](std::exception& /* e */) {
410 flag();
411 return makeFuture();
412 });
413 EXPECT_FLAG();
414 EXPECT_NO_THROW(f.value());
415 }
416
417 // Non-exceptions
418 {
419 auto f = makeFuture()
420 .thenValue([](auto&&) { throw - 1; })
421 .onError([&](int /* e */) { flag(); });
422 EXPECT_FLAG();
423 EXPECT_NO_THROW(f.value());
424 }
425
426 {
427 auto f = makeFuture()
428 .thenValue([](auto&&) { throw - 1; })
429 .onError([&](int /* e */) {
430 flag();
431 return makeFuture();
432 });
433 EXPECT_FLAG();
434 EXPECT_NO_THROW(f.value());
435 }
436
437 // Mutable lambda
438 {
439 auto f = makeFuture()
440 .thenValue([](auto&&) { throw eggs; })
441 .onError([&](eggs_t& /* e */) mutable { flag(); });
442 EXPECT_FLAG();
443 EXPECT_NO_THROW(f.value());
444 }
445
446 {
447 auto f = makeFuture()
448 .thenValue([](auto&&) { throw eggs; })
449 .onError([&](eggs_t& /* e */) mutable {
450 flag();
451 return makeFuture();
452 });
453 EXPECT_FLAG();
454 EXPECT_NO_THROW(f.value());
455 }
456
457 // Function pointer
458 {
459 auto f = makeFuture()
460 .thenValue([](auto &&) -> int { throw eggs; })
461 .onError(onErrorHelperEggs)
462 .onError(onErrorHelperGeneric);
463 EXPECT_EQ(10, f.value());
464 }
465 {
466 auto f =
467 makeFuture()
468 .thenValue([](auto &&) -> int { throw std::runtime_error("test"); })
469 .onError(onErrorHelperEggs)
470 .onError(onErrorHelperGeneric);
471 EXPECT_EQ(20, f.value());
472 }
473 {
474 auto f =
475 makeFuture()
476 .thenValue([](auto &&) -> int { throw std::runtime_error("test"); })
477 .onError(onErrorHelperEggs);
478 EXPECT_THROW(f.value(), std::runtime_error);
479 }
480 {
481 auto f = makeFuture()
482 .thenValue([](auto &&) -> int { throw eggs; })
483 .thenError<eggs_t>(onErrorHelperEggs)
484 .thenError<std::exception>(onErrorHelperGeneric);
485 EXPECT_EQ(10, f.value());
486 }
487 {
488 auto f =
489 makeFuture()
490 .thenValue([](auto &&) -> int { throw std::runtime_error("test"); })
491 .thenError<eggs_t>(onErrorHelperEggs)
492 .thenError(onErrorHelperWrapper);
493 EXPECT_EQ(30, f.value());
494 }
495 {
496 auto f =
497 makeFuture()
498 .thenValue([](auto &&) -> int { throw std::runtime_error("test"); })
499 .thenError<eggs_t>(onErrorHelperEggs);
500 EXPECT_THROW(f.value(), std::runtime_error);
501 }
502
503 // No throw
504 {
505 auto f = makeFuture()
506 .thenValue([](auto&&) { return 42; })
507 .onError([&](eggs_t& /* e */) {
508 flag();
509 return -1;
510 });
511 EXPECT_NO_FLAG();
512 EXPECT_EQ(42, f.value());
513 }
514
515 {
516 auto f = makeFuture()
517 .thenValue([](auto&&) { return 42; })
518 .onError([&](eggs_t& /* e */) {
519 flag();
520 return makeFuture<int>(-1);
521 });
522 EXPECT_NO_FLAG();
523 EXPECT_EQ(42, f.value());
524 }
525
526 // Catch different exception
527 {
528 auto f = makeFuture()
529 .thenValue([](auto&&) { throw eggs; })
530 .onError([&](std::runtime_error& /* e */) { flag(); });
531 EXPECT_NO_FLAG();
532 EXPECT_THROW(f.value(), eggs_t);
533 }
534
535 {
536 auto f = makeFuture()
537 .thenValue([](auto&&) { throw eggs; })
538 .onError([&](std::runtime_error& /* e */) {
539 flag();
540 return makeFuture();
541 });
542 EXPECT_NO_FLAG();
543 EXPECT_THROW(f.value(), eggs_t);
544 }
545
546 // Returned value propagates
547 {
548 auto f = makeFuture()
549 .thenValue([](auto &&) -> int { throw eggs; })
550 .onError([&](eggs_t& /* e */) { return 42; });
551 EXPECT_EQ(42, f.value());
552 }
553
554 // Returned future propagates
555 {
556 auto f = makeFuture()
557 .thenValue([](auto &&) -> int { throw eggs; })
558 .onError([&](eggs_t& /* e */) { return makeFuture<int>(42); });
559 EXPECT_EQ(42, f.value());
560 }
561
562 // Throw in callback
563 {
564 auto f = makeFuture()
565 .thenValue([](auto &&) -> int { throw eggs; })
566 .onError([&](eggs_t& e) -> int { throw e; });
567 EXPECT_THROW(f.value(), eggs_t);
568 }
569
570 {
571 auto f = makeFuture()
572 .thenValue([](auto &&) -> int { throw eggs; })
573 .onError([&](eggs_t& e) -> Future<int> { throw e; });
574 EXPECT_THROW(f.value(), eggs_t);
575 }
576
577 // exception_wrapper, return Future<T>
578 {
579 auto f = makeFuture()
580 .thenValue([](auto&&) { throw eggs; })
581 .onError([&](exception_wrapper /* e */) {
582 flag();
583 return makeFuture();
584 });
585 EXPECT_FLAG();
586 EXPECT_NO_THROW(f.value());
587 }
588
589 // exception_wrapper, return Future<T> but throw
590 {
591 auto f = makeFuture()
592 .thenValue([](auto &&) -> int { throw eggs; })
593 .onError([&](exception_wrapper /* e */) -> Future<int> {
594 flag();
595 throw eggs;
596 });
597 EXPECT_FLAG();
598 EXPECT_THROW(f.value(), eggs_t);
599 }
600
601 // exception_wrapper, return T
602 {
603 auto f = makeFuture()
604 .thenValue([](auto &&) -> int { throw eggs; })
605 .onError([&](exception_wrapper /* e */) {
606 flag();
607 return -1;
608 });
609 EXPECT_FLAG();
610 EXPECT_EQ(-1, f.value());
611 }
612
613 // exception_wrapper, return T but throw
614 {
615 auto f = makeFuture()
616 .thenValue([](auto &&) -> int { throw eggs; })
617 .onError([&](exception_wrapper /* e */) -> int {
618 flag();
619 throw eggs;
620 });
621 EXPECT_FLAG();
622 EXPECT_THROW(f.value(), eggs_t);
623 }
624
625 // const exception_wrapper&
626 {
627 auto f = makeFuture()
628 .thenValue([](auto&&) { throw eggs; })
629 .onError([&](const exception_wrapper& /* e */) {
630 flag();
631 return makeFuture();
632 });
633 EXPECT_FLAG();
634 EXPECT_NO_THROW(f.value());
635 }
636#undef EXPECT_FLAG
637#undef EXPECT_NO_FLAG
638}
639
640TEST(Future, thenError) {
641 bool theFlag = false;
642 auto flag = [&] { theFlag = true; };
643#define EXPECT_FLAG() \
644 do { \
645 EXPECT_TRUE(theFlag); \
646 theFlag = false; \
647 } while (0);
648
649#define EXPECT_NO_FLAG() \
650 do { \
651 EXPECT_FALSE(theFlag); \
652 theFlag = false; \
653 } while (0);
654
655 // By reference
656 {
657 auto f = makeFuture()
658 .thenValue([](auto&&) { throw eggs; })
659 .thenError<eggs_t>([&](const eggs_t& /* e */) { flag(); });
660 EXPECT_FLAG();
661 EXPECT_NO_THROW(f.value());
662 }
663
664 // By auto reference
665 {
666 auto f = makeFuture()
667 .thenValue([](auto&&) { throw eggs; })
668 .thenError<eggs_t>([&](auto const& /* e */) { flag(); });
669 EXPECT_FLAG();
670 EXPECT_NO_THROW(f.value());
671 }
672
673 {
674 auto f = makeFuture()
675 .thenValue([](auto&&) { throw eggs; })
676 .onError([&](eggs_t& /* e */) {
677 flag();
678 return makeFuture();
679 });
680 EXPECT_FLAG();
681 EXPECT_NO_THROW(f.value());
682 }
683
684 // By value
685 {
686 auto f = makeFuture()
687 .thenValue([](auto&&) { throw eggs; })
688 .onError([&](eggs_t /* e */) { flag(); });
689 EXPECT_FLAG();
690 EXPECT_NO_THROW(f.value());
691 }
692
693 {
694 auto f = makeFuture()
695 .thenValue([](auto&&) { throw eggs; })
696 .onError([&](eggs_t /* e */) {
697 flag();
698 return makeFuture();
699 });
700 EXPECT_FLAG();
701 EXPECT_NO_THROW(f.value());
702 }
703
704 // Polymorphic
705 {
706 auto f = makeFuture()
707 .thenValue([](auto&&) { throw eggs; })
708 .onError([&](std::exception& /* e */) { flag(); });
709 EXPECT_FLAG();
710 EXPECT_NO_THROW(f.value());
711 }
712
713 {
714 auto f = makeFuture()
715 .thenValue([](auto&&) { throw eggs; })
716 .onError([&](std::exception& /* e */) {
717 flag();
718 return makeFuture();
719 });
720 EXPECT_FLAG();
721 EXPECT_NO_THROW(f.value());
722 }
723
724 // Non-exceptions
725 {
726 auto f = makeFuture()
727 .thenValue([](auto&&) { throw - 1; })
728 .onError([&](int /* e */) { flag(); });
729 EXPECT_FLAG();
730 EXPECT_NO_THROW(f.value());
731 }
732
733 {
734 auto f = makeFuture()
735 .thenValue([](auto&&) { throw - 1; })
736 .onError([&](int /* e */) {
737 flag();
738 return makeFuture();
739 });
740 EXPECT_FLAG();
741 EXPECT_NO_THROW(f.value());
742 }
743
744 // Mutable lambda
745 {
746 auto f = makeFuture()
747 .thenValue([](auto&&) { throw eggs; })
748 .onError([&](eggs_t& /* e */) mutable { flag(); });
749 EXPECT_FLAG();
750 EXPECT_NO_THROW(f.value());
751 }
752
753 {
754 auto f = makeFuture()
755 .thenValue([](auto&&) { throw eggs; })
756 .onError([&](eggs_t& /* e */) mutable {
757 flag();
758 return makeFuture();
759 });
760 EXPECT_FLAG();
761 EXPECT_NO_THROW(f.value());
762 }
763
764 // Function pointer
765 {
766 auto f = makeFuture()
767 .thenValue([](auto &&) -> int { throw eggs; })
768 .onError(onErrorHelperEggs)
769 .onError(onErrorHelperGeneric);
770 EXPECT_EQ(10, f.value());
771 }
772 {
773 auto f =
774 makeFuture()
775 .thenValue([](auto &&) -> int { throw std::runtime_error("test"); })
776 .onError(onErrorHelperEggs)
777 .onError(onErrorHelperGeneric);
778 EXPECT_EQ(20, f.value());
779 }
780 {
781 auto f =
782 makeFuture()
783 .thenValue([](auto &&) -> int { throw std::runtime_error("test"); })
784 .onError(onErrorHelperEggs);
785 EXPECT_THROW(f.value(), std::runtime_error);
786 }
787
788 // No throw
789 {
790 auto f = makeFuture()
791 .thenValue([](auto&&) { return 42; })
792 .onError([&](eggs_t& /* e */) {
793 flag();
794 return -1;
795 });
796 EXPECT_NO_FLAG();
797 EXPECT_EQ(42, f.value());
798 }
799
800 {
801 auto f = makeFuture()
802 .thenValue([](auto&&) { return 42; })
803 .onError([&](eggs_t& /* e */) {
804 flag();
805 return makeFuture<int>(-1);
806 });
807 EXPECT_NO_FLAG();
808 EXPECT_EQ(42, f.value());
809 }
810
811 // Catch different exception
812 {
813 auto f = makeFuture()
814 .thenValue([](auto&&) { throw eggs; })
815 .onError([&](std::runtime_error& /* e */) { flag(); });
816 EXPECT_NO_FLAG();
817 EXPECT_THROW(f.value(), eggs_t);
818 }
819
820 {
821 auto f = makeFuture()
822 .thenValue([](auto&&) { throw eggs; })
823 .onError([&](std::runtime_error& /* e */) {
824 flag();
825 return makeFuture();
826 });
827 EXPECT_NO_FLAG();
828 EXPECT_THROW(f.value(), eggs_t);
829 }
830
831 // Returned value propagates
832 {
833 auto f = makeFuture()
834 .thenValue([](auto &&) -> int { throw eggs; })
835 .onError([&](eggs_t& /* e */) { return 42; });
836 EXPECT_EQ(42, f.value());
837 }
838
839 // Returned future propagates
840 {
841 auto f = makeFuture()
842 .thenValue([](auto &&) -> int { throw eggs; })
843 .onError([&](eggs_t& /* e */) { return makeFuture<int>(42); });
844 EXPECT_EQ(42, f.value());
845 }
846
847 // Throw in callback
848 {
849 auto f = makeFuture()
850 .thenValue([](auto &&) -> int { throw eggs; })
851 .onError([&](eggs_t& e) -> int { throw e; });
852 EXPECT_THROW(f.value(), eggs_t);
853 }
854
855 {
856 auto f = makeFuture()
857 .thenValue([](auto &&) -> int { throw eggs; })
858 .onError([&](eggs_t& e) -> Future<int> { throw e; });
859 EXPECT_THROW(f.value(), eggs_t);
860 }
861
862 // exception_wrapper, return Future<T>
863 {
864 auto f = makeFuture()
865 .thenValue([](auto&&) { throw eggs; })
866 .onError([&](exception_wrapper /* e */) {
867 flag();
868 return makeFuture();
869 });
870 EXPECT_FLAG();
871 EXPECT_NO_THROW(f.value());
872 }
873
874 // exception_wrapper, return Future<T> but throw
875 {
876 auto f = makeFuture()
877 .thenValue([](auto &&) -> int { throw eggs; })
878 .onError([&](exception_wrapper /* e */) -> Future<int> {
879 flag();
880 throw eggs;
881 });
882 EXPECT_FLAG();
883 EXPECT_THROW(f.value(), eggs_t);
884 }
885
886 // exception_wrapper, return T
887 {
888 auto f = makeFuture()
889 .thenValue([](auto &&) -> int { throw eggs; })
890 .onError([&](exception_wrapper /* e */) {
891 flag();
892 return -1;
893 });
894 EXPECT_FLAG();
895 EXPECT_EQ(-1, f.value());
896 }
897
898 // exception_wrapper, return T but throw
899 {
900 auto f = makeFuture()
901 .thenValue([](auto &&) -> int { throw eggs; })
902 .onError([&](exception_wrapper /* e */) -> int {
903 flag();
904 throw eggs;
905 });
906 EXPECT_FLAG();
907 EXPECT_THROW(f.value(), eggs_t);
908 }
909
910 // const exception_wrapper&
911 {
912 auto f = makeFuture()
913 .thenValue([](auto&&) { throw eggs; })
914 .onError([&](const exception_wrapper& /* e */) {
915 flag();
916 return makeFuture();
917 });
918 EXPECT_FLAG();
919 EXPECT_NO_THROW(f.value());
920 }
921#undef EXPECT_FLAG
922#undef EXPECT_NO_FLAG
923}
924
925TEST(Future, special) {
926 EXPECT_FALSE(std::is_copy_constructible<Future<int>>::value);
927 EXPECT_FALSE(std::is_copy_assignable<Future<int>>::value);
928 EXPECT_TRUE(std::is_move_constructible<Future<int>>::value);
929 EXPECT_TRUE(std::is_move_assignable<Future<int>>::value);
930}
931
932TEST(Future, then) {
933 auto f =
934 makeFuture<std::string>("0")
935 .thenValue([](auto&&) { return makeFuture<std::string>("1"); })
936 .then(
937 [](Try<std::string>&& t) { return makeFuture(t.value() + ";2"); })
938 .then([](const Try<std::string>&& t) {
939 return makeFuture(t.value() + ";3");
940 })
941 .then([](const Try<std::string>& t) {
942 return makeFuture(t.value() + ";4");
943 })
944 .then([](Try<std::string> t) { return makeFuture(t.value() + ";5"); })
945 .then([](const Try<std::string> t) {
946 return makeFuture(t.value() + ";6");
947 })
948 .thenValue([](std::string&& s) { return makeFuture(s + ";7"); })
949 .thenValue([](const std::string&& s) { return makeFuture(s + ";8"); })
950 .thenValue([](const std::string& s) { return makeFuture(s + ";9"); })
951 .thenValue([](std::string s) { return makeFuture(s + ";10"); })
952 .thenValue([](const std::string s) { return makeFuture(s + ";11"); });
953 EXPECT_EQ(f.value(), "1;2;3;4;5;6;7;8;9;10;11");
954}
955
956static folly::Future<std::string> doWorkStaticTry(Try<std::string>&& t) {
957 return makeFuture(t.value() + ";7");
958}
959
960TEST(Future, thenTrythenValue) {
961 auto f =
962 makeFuture()
963 .thenTry([](auto&&) { return makeFuture<std::string>("1"); })
964 .thenTry(
965 [](Try<std::string>&& t) { return makeFuture(t.value() + ";2"); })
966 .thenTry([](const Try<std::string>&& t) {
967 return makeFuture(t.value() + ";3");
968 })
969 .thenTry([](const Try<std::string>& t) {
970 return makeFuture(t.value() + ";4");
971 })
972 .thenTry(
973 [](Try<std::string> t) { return makeFuture(t.value() + ";5"); })
974 .thenTry([](const Try<std::string> t) {
975 return makeFuture(t.value() + ";6");
976 })
977 .thenTry(doWorkStaticTry)
978 .thenValue([](std::string&& s) { return makeFuture(s + ";8"); })
979 .thenValue([](const std::string&& s) { return makeFuture(s + ";9"); })
980 .thenValue([](const std::string& s) { return makeFuture(s + ";10"); })
981 .thenValue([](std::string s) { return makeFuture(s + ";11"); })
982 .thenValue([](const std::string s) { return makeFuture(s + ";12"); });
983 EXPECT_EQ(f.value(), "1;2;3;4;5;6;7;8;9;10;11;12");
984}
985
986TEST(Future, thenTry) {
987 bool flag = false;
988
989 makeFuture<int>(42).then([&](Try<int>&& t) {
990 flag = true;
991 EXPECT_EQ(42, t.value());
992 });
993 EXPECT_TRUE(flag);
994 flag = false;
995
996 makeFuture<int>(42)
997 .then([](Try<int>&& t) { return t.value(); })
998 .then([&](Try<int>&& t) {
999 flag = true;
1000 EXPECT_EQ(42, t.value());
1001 });
1002 EXPECT_TRUE(flag);
1003 flag = false;
1004
1005 makeFuture().then([&](Try<Unit>&& t) {
1006 flag = true;
1007 t.value();
1008 });
1009 EXPECT_TRUE(flag);
1010 flag = false;
1011
1012 Promise<Unit> p;
1013 auto f = p.getFuture().then([&](Try<Unit>&& /* t */) { flag = true; });
1014 EXPECT_FALSE(flag);
1015 EXPECT_FALSE(f.isReady());
1016 p.setValue();
1017 EXPECT_TRUE(flag);
1018 EXPECT_TRUE(f.isReady());
1019}
1020
1021TEST(Future, thenValue) {
1022 bool flag = false;
1023 makeFuture<int>(42).thenValue([&](int i) {
1024 EXPECT_EQ(42, i);
1025 flag = true;
1026 });
1027 EXPECT_TRUE(flag);
1028 flag = false;
1029
1030 makeFuture<int>(42).thenValue([](int i) { return i; }).thenValue([&](int i) {
1031 flag = true;
1032 EXPECT_EQ(42, i);
1033 });
1034 EXPECT_TRUE(flag);
1035 flag = false;
1036
1037 makeFuture().thenValue([&](auto&&) { flag = true; });
1038 EXPECT_TRUE(flag);
1039 flag = false;
1040
1041 auto f = makeFuture<int>(eggs).thenValue([&](int /* i */) {});
1042 EXPECT_THROW(f.value(), eggs_t);
1043
1044 f = makeFuture<Unit>(eggs).thenValue([&](auto&&) {});
1045 EXPECT_THROW(f.value(), eggs_t);
1046}
1047
1048TEST(Future, thenValueFuture) {
1049 bool flag = false;
1050 makeFuture<int>(42)
1051 .thenValue([](int i) { return makeFuture<int>(std::move(i)); })
1052 .then([&](Try<int>&& t) {
1053 flag = true;
1054 EXPECT_EQ(42, t.value());
1055 });
1056 EXPECT_TRUE(flag);
1057 flag = false;
1058
1059 makeFuture()
1060 .thenValue([](auto&&) { return makeFuture(); })
1061 .then([&](Try<Unit>&& /* t */) { flag = true; });
1062 EXPECT_TRUE(flag);
1063 flag = false;
1064}
1065
1066static std::string doWorkStatic(Try<std::string>&& t) {
1067 return t.value() + ";static";
1068}
1069
1070static std::string doWorkStaticValue(std::string&& t) {
1071 return t + ";value";
1072}
1073
1074TEST(Future, thenFunction) {
1075 struct Worker {
1076 std::string doWork(Try<std::string>&& t) {
1077 return t.value() + ";class";
1078 }
1079 static std::string doWorkStatic(Try<std::string>&& t) {
1080 return t.value() + ";class-static";
1081 }
1082 } w;
1083
1084 auto f = makeFuture<std::string>("start")
1085 .then(doWorkStatic)
1086 .then(Worker::doWorkStatic)
1087 .then(&Worker::doWork, &w)
1088 .thenValue(doWorkStaticValue);
1089
1090 EXPECT_EQ(f.value(), "start;static;class-static;class;value");
1091}
1092
1093static Future<std::string> doWorkStaticFuture(Try<std::string>&& t) {
1094 return makeFuture(t.value() + ";static");
1095}
1096
1097TEST(Future, thenFunctionFuture) {
1098 struct Worker {
1099 Future<std::string> doWorkFuture(Try<std::string>&& t) {
1100 return makeFuture(t.value() + ";class");
1101 }
1102 static Future<std::string> doWorkStaticFuture(Try<std::string>&& t) {
1103 return makeFuture(t.value() + ";class-static");
1104 }
1105 } w;
1106
1107 auto f = makeFuture<std::string>("start")
1108 .then(doWorkStaticFuture)
1109 .then(Worker::doWorkStaticFuture)
1110 .then(&Worker::doWorkFuture, &w);
1111
1112 EXPECT_EQ(f.value(), "start;static;class-static;class");
1113}
1114
1115TEST(Future, thenStdFunction) {
1116 {
1117 std::function<int(folly::Unit)> fn = [](folly::Unit) { return 42; };
1118 auto f = makeFuture().thenValue(std::move(fn));
1119 EXPECT_EQ(f.value(), 42);
1120 }
1121 {
1122 std::function<int(int)> fn = [](int i) { return i + 23; };
1123 auto f = makeFuture(19).thenValue(std::move(fn));
1124 EXPECT_EQ(f.value(), 42);
1125 }
1126 {
1127 std::function<int(Try<int>)> fn = [](Try<int> t) { return t.value() + 2; };
1128 auto f = makeFuture(1).then(std::move(fn));
1129 EXPECT_EQ(f.value(), 3);
1130 }
1131 {
1132 bool flag = false;
1133 std::function<void(folly::Unit)> fn = [&flag](folly::Unit) { flag = true; };
1134 auto f = makeFuture().thenValue(std::move(fn));
1135 EXPECT_TRUE(f.isReady());
1136 EXPECT_TRUE(flag);
1137 }
1138}
1139
1140TEST(Future, thenBind) {
1141 auto l = [](folly::Unit) { return makeFuture("bind"); };
1142 auto b = std::bind(l, std::placeholders::_1);
1143 auto f = makeFuture().thenValue(std::move(b));
1144 EXPECT_EQ(f.value(), "bind");
1145}
1146
1147TEST(Future, thenBindTry) {
1148 auto l = [](Try<std::string>&& t) { return makeFuture(t.value() + ";bind"); };
1149 auto b = std::bind(l, std::placeholders::_1);
1150 auto f = makeFuture<std::string>("start").then(std::move(b));
1151
1152 EXPECT_EQ(f.value(), "start;bind");
1153}
1154
1155TEST(Future, value) {
1156 auto f = makeFuture(std::make_unique<int>(42));
1157 auto up = std::move(f.value());
1158 EXPECT_EQ(42, *up);
1159
1160 EXPECT_THROW(makeFuture<int>(eggs).value(), eggs_t);
1161}
1162
1163TEST(Future, isReady) {
1164 Promise<int> p;
1165 auto f = p.getFuture();
1166 EXPECT_FALSE(f.isReady());
1167 p.setValue(42);
1168 EXPECT_TRUE(f.isReady());
1169}
1170
1171TEST(Future, futureNotReady) {
1172 Promise<int> p;
1173 Future<int> f = p.getFuture();
1174 EXPECT_THROW(f.value(), eggs_t);
1175}
1176
1177TEST(Future, hasException) {
1178 EXPECT_TRUE(makeFuture<int>(eggs).getTry().hasException());
1179 EXPECT_FALSE(makeFuture(42).getTry().hasException());
1180}
1181
1182TEST(Future, hasValue) {
1183 EXPECT_TRUE(makeFuture(42).getTry().hasValue());
1184 EXPECT_FALSE(makeFuture<int>(eggs).getTry().hasValue());
1185}
1186
1187TEST(Future, makeFuture) {
1188 EXPECT_TYPE(makeFuture(42), Future<int>);
1189 EXPECT_EQ(42, makeFuture(42).value());
1190
1191 EXPECT_TYPE(makeFuture<float>(42), Future<float>);
1192 EXPECT_EQ(42, makeFuture<float>(42).value());
1193
1194 auto fun = [] { return 42; };
1195 EXPECT_TYPE(makeFutureWith(fun), Future<int>);
1196 EXPECT_EQ(42, makeFutureWith(fun).value());
1197
1198 auto funf = [] { return makeFuture<int>(43); };
1199 EXPECT_TYPE(makeFutureWith(funf), Future<int>);
1200 EXPECT_EQ(43, makeFutureWith(funf).value());
1201
1202 auto failfun = []() -> int { throw eggs; };
1203 EXPECT_TYPE(makeFutureWith(failfun), Future<int>);
1204 EXPECT_NO_THROW(makeFutureWith(failfun));
1205 EXPECT_THROW(makeFutureWith(failfun).value(), eggs_t);
1206
1207 auto failfunf = []() -> Future<int> { throw eggs; };
1208 EXPECT_TYPE(makeFutureWith(failfunf), Future<int>);
1209 EXPECT_NO_THROW(makeFutureWith(failfunf));
1210 EXPECT_THROW(makeFutureWith(failfunf).value(), eggs_t);
1211
1212 EXPECT_TYPE(makeFuture(), Future<Unit>);
1213}
1214
1215TEST(Future, finish) {
1216 auto x = std::make_shared<int>(0);
1217
1218 Promise<int> p;
1219 auto f = p.getFuture().then([x](Try<int>&& t) { *x = t.value(); });
1220
1221 // The callback hasn't executed
1222 EXPECT_EQ(0, *x);
1223
1224 // The callback has a reference to x
1225 EXPECT_EQ(2, x.use_count());
1226
1227 p.setValue(42);
1228
1229 // the callback has executed
1230 EXPECT_EQ(42, *x);
1231
1232 // the callback has been destructed
1233 // and has released its reference to x
1234 EXPECT_EQ(1, x.use_count());
1235}
1236
1237TEST(Future, finishBigLambda) {
1238 auto x = std::make_shared<int>(0);
1239
1240 // bulk_data, to be captured in the lambda passed to Future::then.
1241 // This is meant to force that the lambda can't be stored inside
1242 // the Future object.
1243 std::array<char, sizeof(futures::detail::Core<int>)> bulk_data = {{0}};
1244
1245 // suppress gcc warning about bulk_data not being used
1246 EXPECT_EQ(bulk_data[0], 0);
1247
1248 Promise<int> p;
1249 auto f = p.getFuture().then([x, bulk_data](Try<int>&& t) {
1250 (void)bulk_data;
1251 *x = t.value();
1252 });
1253
1254 // The callback hasn't executed
1255 EXPECT_EQ(0, *x);
1256
1257 // The callback has a reference to x
1258 EXPECT_EQ(2, x.use_count());
1259
1260 p.setValue(42);
1261
1262 // the callback has executed
1263 EXPECT_EQ(42, *x);
1264
1265 // the callback has been destructed
1266 // and has released its reference to x
1267 EXPECT_EQ(1, x.use_count());
1268}
1269
1270TEST(Future, unwrap) {
1271 Promise<int> a;
1272 Promise<int> b;
1273
1274 auto fa = a.getFuture();
1275 auto fb = b.getFuture();
1276
1277 bool flag1 = false;
1278 bool flag2 = false;
1279
1280 // do a, then do b, and get the result of a + b.
1281 Future<int> f = std::move(fa).then([&](Try<int>&& ta) {
1282 auto va = ta.value();
1283 flag1 = true;
1284 return std::move(fb).then([va, &flag2](Try<int>&& tb) {
1285 flag2 = true;
1286 return va + tb.value();
1287 });
1288 });
1289
1290 EXPECT_FALSE(flag1);
1291 EXPECT_FALSE(flag2);
1292 EXPECT_FALSE(f.isReady());
1293
1294 a.setValue(3);
1295 EXPECT_TRUE(flag1);
1296 EXPECT_FALSE(flag2);
1297 EXPECT_FALSE(f.isReady());
1298
1299 b.setValue(4);
1300 EXPECT_TRUE(flag1);
1301 EXPECT_TRUE(flag2);
1302 EXPECT_EQ(7, f.value());
1303}
1304
1305TEST(Future, throwCaughtInImmediateThen) {
1306 // Neither of these should throw "Promise already satisfied"
1307 makeFuture().then([=](Try<Unit> &&) -> int { throw std::exception(); });
1308 makeFuture().then(
1309 [=](Try<Unit> &&) -> Future<int> { throw std::exception(); });
1310}
1311
1312TEST(Future, throwIfFailed) {
1313 makeFuture<Unit>(eggs).then(
1314 [=](Try<Unit>&& t) { EXPECT_THROW(t.throwIfFailed(), eggs_t); });
1315 makeFuture().then([=](Try<Unit>&& t) { EXPECT_NO_THROW(t.throwIfFailed()); });
1316
1317 makeFuture<int>(eggs).then(
1318 [=](Try<int>&& t) { EXPECT_THROW(t.throwIfFailed(), eggs_t); });
1319 makeFuture<int>(42).then(
1320 [=](Try<int>&& t) { EXPECT_NO_THROW(t.throwIfFailed()); });
1321}
1322
1323TEST(Future, getFutureAfterSetValue) {
1324 Promise<int> p;
1325 p.setValue(42);
1326 EXPECT_EQ(42, p.getFuture().value());
1327}
1328
1329TEST(Future, getFutureAfterSetException) {
1330 Promise<Unit> p;
1331 p.setWith([]() -> void { throw std::logic_error("foo"); });
1332 EXPECT_THROW(p.getFuture().value(), std::logic_error);
1333}
1334
1335TEST(Future, detachRace) {
1336 // Task #5438209
1337 // This test is designed to detect a race that was in Core::detachOne()
1338 // where detached_ was incremented and then tested, and that
1339 // allowed a race where both Promise and Future would think they were the
1340 // second and both try to delete. This showed up at scale but was very
1341 // difficult to reliably repro in a test. As it is, this only fails about
1342 // once in every 1,000 executions. Doing this 1,000 times is going to make a
1343 // slow test so I won't do that but if it ever fails, take it seriously, and
1344 // run the test binary with "--gtest_repeat=10000 --gtest_filter=*detachRace"
1345 // (Don't forget to enable ASAN)
1346 auto p = std::make_unique<Promise<bool>>();
1347 auto f = std::make_unique<Future<bool>>(p->getFuture());
1348 folly::Baton<> baton;
1349 std::thread t1([&] {
1350 baton.post();
1351 p.reset();
1352 });
1353 baton.wait();
1354 f.reset();
1355 t1.join();
1356}
1357
1358// Test of handling of a circular dependency. It's never recommended
1359// to have one because of possible memory leaks. Here we test that
1360// we can handle freeing of the Future while it is running.
1361TEST(Future, CircularDependencySharedPtrSelfReset) {
1362 Promise<int64_t> promise;
1363 auto ptr = std::make_shared<Future<int64_t>>(promise.getFuture());
1364
1365 std::move(*ptr).thenTry([ptr](folly::Try<int64_t>&& /* uid */) mutable {
1366 EXPECT_EQ(1, ptr.use_count());
1367
1368 // Leaving no references to ourselves.
1369 ptr.reset();
1370 EXPECT_EQ(0, ptr.use_count());
1371 });
1372
1373 EXPECT_EQ(2, ptr.use_count());
1374
1375 ptr.reset();
1376
1377 promise.setValue(1);
1378}
1379
1380TEST(Future, Constructor) {
1381 auto f1 = []() -> Future<int> { return Future<int>(3); }();
1382 EXPECT_EQ(f1.value(), 3);
1383 auto f2 = []() -> Future<Unit> { return Future<Unit>(); }();
1384 EXPECT_NO_THROW(f2.value());
1385}
1386
1387TEST(Future, ImplicitConstructor) {
1388 auto f1 = []() -> Future<int> { return 3; }();
1389 EXPECT_EQ(f1.value(), 3);
1390 // Unfortunately, the C++ standard does not allow the
1391 // following implicit conversion to work:
1392 // auto f2 = []() -> Future<Unit> { }();
1393}
1394
1395TEST(Future, InPlaceConstructor) {
1396 auto f = Future<std::pair<int, double>>(in_place, 5, 3.2);
1397 EXPECT_EQ(5, f.value().first);
1398}
1399
1400TEST(Future, thenDynamic) {
1401 // folly::dynamic has a constructor that takes any T, this test makes
1402 // sure that we call the then lambda with folly::dynamic and not
1403 // Try<folly::dynamic> because that then fails to compile
1404 Promise<folly::dynamic> p;
1405 Future<folly::dynamic> f = p.getFuture().thenValue(
1406 [](const folly::dynamic& d) { return folly::dynamic(d.asInt() + 3); });
1407 p.setValue(2);
1408 EXPECT_EQ(std::move(f).get(), 5);
1409}
1410
1411TEST(Future, RequestContext) {
1412 class NewThreadExecutor : public Executor {
1413 public:
1414 ~NewThreadExecutor() override {
1415 std::for_each(v_.begin(), v_.end(), [](std::thread& t) { t.join(); });
1416 }
1417 void add(Func f) override {
1418 if (throwsOnAdd_) {
1419 throw std::exception();
1420 }
1421 v_.emplace_back(std::move(f));
1422 }
1423 void addWithPriority(Func f, int8_t /* prio */) override {
1424 add(std::move(f));
1425 }
1426 uint8_t getNumPriorities() const override {
1427 return numPriorities_;
1428 }
1429
1430 void setHandlesPriorities() {
1431 numPriorities_ = 2;
1432 }
1433 void setThrowsOnAdd() {
1434 throwsOnAdd_ = true;
1435 }
1436
1437 private:
1438 std::vector<std::thread> v_;
1439 uint8_t numPriorities_ = 1;
1440 bool throwsOnAdd_ = false;
1441 };
1442
1443 struct MyRequestData : RequestData {
1444 MyRequestData(bool value_ = false) : value(value_) {}
1445
1446 bool hasCallback() override {
1447 return false;
1448 }
1449
1450 bool value;
1451 };
1452
1453 Promise<int> p1, p2;
1454 NewThreadExecutor e;
1455 {
1456 folly::RequestContextScopeGuard rctx;
1457 RequestContext::get()->setContextData(
1458 "key", std::make_unique<MyRequestData>(true));
1459 auto checker = [](int lineno) {
1460 return [lineno](Try<int>&& /* t */) {
1461 auto d = static_cast<MyRequestData*>(
1462 RequestContext::get()->getContextData("key"));
1463 EXPECT_TRUE(d && d->value) << "on line " << lineno;
1464 };
1465 };
1466
1467 makeFuture(1).via(&e).then(checker(__LINE__));
1468
1469 e.setHandlesPriorities();
1470 makeFuture(2).via(&e).then(checker(__LINE__));
1471
1472 p1.getFuture().then(checker(__LINE__));
1473
1474 e.setThrowsOnAdd();
1475 p2.getFuture().via(&e).then(checker(__LINE__));
1476 }
1477 // Assert that no RequestContext is set
1478 EXPECT_FALSE(RequestContext::saveContext());
1479 p1.setValue(3);
1480 p2.setValue(4);
1481}
1482
1483TEST(Future, makeFutureNoThrow) {
1484 makeFuture().value();
1485}
1486
1487TEST(Future, invokeCallbackReturningValueAsRvalue) {
1488 struct Foo {
1489 int operator()(int x) & {
1490 return x + 1;
1491 }
1492 int operator()(int x) const& {
1493 return x + 2;
1494 }
1495 int operator()(int x) && {
1496 return x + 3;
1497 }
1498 };
1499
1500 Foo foo;
1501 Foo const cfoo;
1502
1503 // The continuation will be forward-constructed - copied if given as & and
1504 // moved if given as && - everywhere construction is required.
1505 // The continuation will be invoked with the same cvref as it is passed.
1506 EXPECT_EQ(101, makeFuture<int>(100).thenValue(foo).value());
1507 EXPECT_EQ(202, makeFuture<int>(200).thenValue(cfoo).value());
1508 EXPECT_EQ(303, makeFuture<int>(300).thenValue(Foo()).value());
1509}
1510
1511TEST(Future, invokeCallbackReturningFutureAsRvalue) {
1512 struct Foo {
1513 Future<int> operator()(int x) & {
1514 return x + 1;
1515 }
1516 Future<int> operator()(int x) const& {
1517 return x + 2;
1518 }
1519 Future<int> operator()(int x) && {
1520 return x + 3;
1521 }
1522 };
1523
1524 Foo foo;
1525 Foo const cfoo;
1526
1527 // The continuation will be forward-constructed - copied if given as & and
1528 // moved if given as && - everywhere construction is required.
1529 // The continuation will be invoked with the same cvref as it is passed.
1530 EXPECT_EQ(101, makeFuture<int>(100).thenValue(foo).value());
1531 EXPECT_EQ(202, makeFuture<int>(200).thenValue(cfoo).value());
1532 EXPECT_EQ(303, makeFuture<int>(300).thenValue(Foo()).value());
1533}
1534
1535TEST(Future, futureWithinCtxCleanedUpWhenTaskFinishedInTime) {
1536 // Used to track the use_count of callbackInput even outside of its scope
1537 std::weak_ptr<int> target;
1538 {
1539 Promise<std::shared_ptr<int>> promise;
1540 auto input = std::make_shared<int>(1);
1541 auto longEnough = std::chrono::milliseconds(1000);
1542
1543 promise.getFuture()
1544 .within(longEnough)
1545 .then([&target](
1546 folly::Try<std::shared_ptr<int>>&& callbackInput) mutable {
1547 target = callbackInput.value();
1548 });
1549 promise.setValue(input);
1550 }
1551 // After promise's life cycle is finished, make sure no one is holding the
1552 // input anymore, in other words, ctx should have been cleaned up.
1553 EXPECT_EQ(0, target.use_count());
1554}
1555
1556TEST(Future, futureWithinNoValueReferenceWhenTimeOut) {
1557 Promise<std::shared_ptr<int>> promise;
1558 auto veryShort = std::chrono::milliseconds(1);
1559
1560 promise.getFuture().within(veryShort).then(
1561 [](folly::Try<std::shared_ptr<int>>&& callbackInput) {
1562 // Timeout is fired. Verify callbackInput is not referenced
1563 EXPECT_EQ(0, callbackInput.value().use_count());
1564 });
1565}
1566
1567TEST(Future, makePromiseContract) {
1568 class ManualExecutor : public Executor {
1569 private:
1570 std::queue<Func> queue_;
1571
1572 public:
1573 void add(Func f) override {
1574 queue_.push(std::move(f));
1575 }
1576 void drain() {
1577 while (!queue_.empty()) {
1578 auto f = std::move(queue_.front());
1579 queue_.pop();
1580 f();
1581 }
1582 }
1583 };
1584
1585 ManualExecutor e;
1586 auto c = makePromiseContract<int>(&e);
1587 c.second = std::move(c.second).thenValue([](int _) { return _ + 1; });
1588 EXPECT_FALSE(c.second.isReady());
1589 c.first.setValue(3);
1590 EXPECT_FALSE(c.second.isReady());
1591 e.drain();
1592 ASSERT_TRUE(c.second.isReady());
1593 EXPECT_EQ(4, std::move(c.second).get());
1594}
1595
1596Future<bool> call(int depth, Executor* executor) {
1597 return makeFuture().then(executor, [=] { return depth == 0; });
1598}
1599
1600Future<int> recursion(Executor* executor, int depth) {
1601 return makeFuture().thenValue([=](auto) {
1602 return call(depth, executor).thenValue([=](auto result) {
1603 if (result) {
1604 return folly::makeFuture(42);
1605 }
1606
1607 return recursion(executor, depth - 1);
1608 });
1609 });
1610}
1611
1612TEST(Future, ThenRecursion) {
1613 ManualExecutor executor;
1614
1615 EXPECT_EQ(42, recursion(&executor, 100000).getVia(&executor));
1616}
1617