proxygen
SemiFutureTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-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 #include <folly/Executor.h>
17 #include <folly/Memory.h>
18 #include <folly/Unit.h>
19 #include <folly/dynamic.h>
21 #include <folly/futures/Future.h>
25 
26 #include <algorithm>
27 #include <atomic>
28 #include <future>
29 #include <memory>
30 #include <numeric>
31 #include <string>
32 #include <thread>
33 #include <type_traits>
34 
35 using namespace folly;
36 
37 #define EXPECT_TYPE(x, T) EXPECT_TRUE((std::is_same<decltype(x), T>::value))
38 
40 static eggs_t eggs("eggs");
41 
42 // Future
43 
44 TEST(SemiFuture, makeEmpty) {
46  EXPECT_THROW(f.isReady(), FutureInvalid);
47 }
48 
49 TEST(SemiFuture, futureDefaultCtor) {
51 }
52 
53 TEST(SemiFuture, makeSemiFutureWithUnit) {
54  int count = 0;
55  SemiFuture<Unit> fu = makeSemiFutureWith([&] { count++; });
56  EXPECT_EQ(1, count);
57 }
58 
59 namespace {
60 auto makeValid() {
61  auto valid = makeSemiFuture<int>(42);
62  EXPECT_TRUE(valid.valid());
63  return valid;
64 }
65 auto makeInvalid() {
66  auto invalid = SemiFuture<int>::makeEmpty();
67  EXPECT_FALSE(invalid.valid());
68  return invalid;
69 }
70 } // namespace
71 
72 TEST(SemiFuture, ctorPostconditionValid) {
73  // Ctors/factories that promise valid -- postcondition: valid()
74 
75 #define DOIT(CREATION_EXPR) \
76  do { \
77  auto f1 = (CREATION_EXPR); \
78  EXPECT_TRUE(f1.valid()); \
79  auto f2 = std::move(f1); \
80  EXPECT_FALSE(f1.valid()); \
81  EXPECT_TRUE(f2.valid()); \
82  } while (false)
83 
84  auto const except = std::logic_error("foo");
85  auto const ewrap = folly::exception_wrapper(except);
86 
87  DOIT(makeValid());
88  DOIT(SemiFuture<int>(42));
89  DOIT(SemiFuture<int>{42});
94  DOIT(makeSemiFuture<Unit>(Unit{}));
95  DOIT(makeSemiFuture(42));
96  DOIT(makeSemiFuture<int>(42));
97  DOIT(makeSemiFuture<int>(except));
98  DOIT(makeSemiFuture<int>(ewrap));
100  DOIT(makeSemiFuture<int>(Try<int>(42)));
101  DOIT(makeSemiFuture<int>(Try<int>(ewrap)));
102 
103 #undef DOIT
104 }
105 
106 TEST(SemiFuture, ctorPostconditionInvalid) {
107  // Ctors/factories that promise invalid -- postcondition: !valid()
108 
109 #define DOIT(CREATION_EXPR) \
110  do { \
111  auto f1 = (CREATION_EXPR); \
112  EXPECT_FALSE(f1.valid()); \
113  auto f2 = std::move(f1); \
114  EXPECT_FALSE(f1.valid()); \
115  EXPECT_FALSE(f2.valid()); \
116  } while (false)
117 
118  DOIT(makeInvalid());
120 
121 #undef DOIT
122 }
123 
124 TEST(SemiFuture, lacksPreconditionValid) {
125  // Ops that don't throw FutureInvalid if !valid() --
126  // without precondition: valid()
127 
128 #define DOIT(STMT) \
129  do { \
130  auto f = makeValid(); \
131  { STMT; } \
132  copy(std::move(f)); \
133  EXPECT_NO_THROW(STMT); \
134  } while (false)
135 
136  // .valid() itself
137  DOIT(f.valid());
138 
139  // move-ctor - move-copy to local, copy(), pass-by-move-value
140  DOIT(auto other = std::move(f));
141  DOIT(copy(std::move(f)));
142  DOIT(([](auto) {})(std::move(f)));
143 
144  // move-assignment into either {valid | invalid}
145  DOIT({
146  auto other = makeValid();
147  other = std::move(f);
148  });
149  DOIT({
150  auto other = makeInvalid();
151  other = std::move(f);
152  });
153 
154 #undef DOIT
155 }
156 
157 TEST(SemiFuture, hasPreconditionValid) {
158  // Ops that require validity; precondition: valid();
159  // throw FutureInvalid if !valid()
160 
161 #define DOIT(STMT) \
162  do { \
163  auto f = makeValid(); \
164  EXPECT_NO_THROW(STMT); \
165  copy(std::move(f)); \
166  EXPECT_THROW(STMT, FutureInvalid); \
167  } while (false)
168 
169  DOIT(f.isReady());
170  DOIT(f.result());
171  DOIT(std::move(f).getTry());
172  DOIT(f.hasValue());
173  DOIT(f.hasException());
174  DOIT(f.value());
175 
176 #undef DOIT
177 }
178 
179 TEST(SemiFuture, hasPostconditionValid) {
180  // Ops that preserve validity -- postcondition: valid()
181 
182 #define DOIT(STMT) \
183  do { \
184  auto f = makeValid(); \
185  EXPECT_NO_THROW(STMT); \
186  EXPECT_TRUE(f.valid()); \
187  } while (false)
188 
189  auto const swallow = [](auto) {};
190 
191  DOIT(swallow(f.valid())); // f.valid() itself preserves validity
192  DOIT(swallow(f.isReady()));
193  DOIT(swallow(f.hasValue()));
194  DOIT(swallow(f.hasException()));
195  DOIT(swallow(f.value()));
196  DOIT(swallow(f.poll()));
197  DOIT(f.raise(std::logic_error("foo")));
198  DOIT(f.cancel());
199  DOIT(f.wait());
200  DOIT(std::move(f.wait()));
201 
202 #undef DOIT
203 }
204 
205 TEST(SemiFuture, hasPostconditionInvalid) {
206  // Ops that consume *this -- postcondition: !valid()
207 
208 #define DOIT(CTOR, STMT) \
209  do { \
210  auto f = (CTOR); \
211  EXPECT_NO_THROW(STMT); \
212  EXPECT_FALSE(f.valid()); \
213  } while (false)
214 
215  // move-ctor of {valid|invalid}
216  DOIT(makeValid(), { auto other{std::move(f)}; });
217  DOIT(makeInvalid(), { auto other{std::move(f)}; });
218 
219  // move-assignment of {valid|invalid} into {valid|invalid}
220  DOIT(makeValid(), {
221  auto other = makeValid();
222  other = std::move(f);
223  });
224  DOIT(makeValid(), {
225  auto other = makeInvalid();
226  other = std::move(f);
227  });
228  DOIT(makeInvalid(), {
229  auto other = makeValid();
230  other = std::move(f);
231  });
232  DOIT(makeInvalid(), {
233  auto other = makeInvalid();
234  other = std::move(f);
235  });
236 
237  // pass-by-value of {valid|invalid}
238  DOIT(makeValid(), {
239  auto const byval = [](auto) {};
240  byval(std::move(f));
241  });
242  DOIT(makeInvalid(), {
243  auto const byval = [](auto) {};
244  byval(std::move(f));
245  });
246 
247  // other consuming ops
248  auto const swallow = [](auto) {};
249  DOIT(makeValid(), swallow(std::move(f).get()));
250  DOIT(makeValid(), swallow(std::move(f).getTry()));
251  DOIT(makeValid(), swallow(std::move(f).wait()));
252  DOIT(makeValid(), swallow(std::move(f.wait())));
253 
254 #undef DOIT
255 }
256 
257 namespace {
258 int onErrorHelperEggs(const eggs_t&) {
259  return 10;
260 }
261 int onErrorHelperGeneric(const folly::exception_wrapper&) {
262  return 20;
263 }
264 } // namespace
265 
266 TEST(SemiFuture, special) {
267  EXPECT_FALSE(std::is_copy_constructible<SemiFuture<int>>::value);
268  EXPECT_FALSE(std::is_copy_assignable<SemiFuture<int>>::value);
269  EXPECT_TRUE(std::is_move_constructible<SemiFuture<int>>::value);
270  EXPECT_TRUE(std::is_move_assignable<SemiFuture<int>>::value);
271 }
272 
274  auto f = makeSemiFuture(std::make_unique<int>(42));
275  auto up = std::move(f.value());
276  EXPECT_EQ(42, *up);
277 
278  EXPECT_THROW(makeSemiFuture<int>(eggs).value(), eggs_t);
279 
280  EXPECT_TYPE(std::declval<SemiFuture<int>&>().value(), int&);
281  EXPECT_TYPE(std::declval<SemiFuture<int> const&>().value(), int const&);
282  EXPECT_TYPE(std::declval<SemiFuture<int>&&>().value(), int&&);
283  EXPECT_TYPE(std::declval<SemiFuture<int> const&&>().value(), int const&&);
284 }
285 
286 TEST(SemiFuture, hasException) {
287  EXPECT_TRUE(makeSemiFuture<int>(eggs).getTry().hasException());
288  EXPECT_FALSE(makeSemiFuture(42).getTry().hasException());
289 }
290 
291 TEST(SemiFuture, hasValue) {
292  EXPECT_TRUE(makeSemiFuture(42).getTry().hasValue());
293  EXPECT_FALSE(makeSemiFuture<int>(eggs).getTry().hasValue());
294 }
295 
298  EXPECT_EQ(42, makeSemiFuture(42).value());
299 
300  EXPECT_TYPE(makeSemiFuture<float>(42), SemiFuture<float>);
301  EXPECT_EQ(42, makeSemiFuture<float>(42).value());
302 
303  auto fun = [] { return 42; };
306 
307  auto funf = [] { return makeSemiFuture<int>(43); };
309  EXPECT_EQ(43, makeSemiFutureWith(funf).value());
310 
311  auto failfun = []() -> int { throw eggs; };
315 
316  auto failfunf = []() -> SemiFuture<int> { throw eggs; };
320 
321  auto futurefun = [] { return makeFuture<int>(44); };
323  EXPECT_EQ(44, makeSemiFutureWith(futurefun).value());
324 
326 }
327 
328 TEST(SemiFuture, Constructor) {
329  auto f1 = []() -> SemiFuture<int> { return SemiFuture<int>(3); }();
330  EXPECT_EQ(f1.value(), 3);
331  auto f2 = []() -> SemiFuture<Unit> { return SemiFuture<Unit>(); }();
332  EXPECT_NO_THROW(f2.value());
333 }
334 
335 TEST(SemiFuture, ImplicitConstructor) {
336  auto f1 = []() -> SemiFuture<int> { return 3; }();
337  EXPECT_EQ(f1.value(), 3);
338 }
339 
340 TEST(SemiFuture, InPlaceConstructor) {
342  EXPECT_EQ(5, f.value().first);
343 }
344 
345 TEST(SemiFuture, makeSemiFutureNoThrow) {
346  makeSemiFuture().value();
347 }
348 
349 TEST(SemiFuture, ViaThrowOnNull) {
351 }
352 
353 TEST(SemiFuture, ConstructSemiFutureFromEmptyFuture) {
355  EXPECT_THROW(f.isReady(), FutureInvalid);
356 }
357 
358 TEST(SemiFuture, ConstructSemiFutureFromFutureDefaultCtor) {
360 }
361 
362 TEST(SemiFuture, MakeSemiFutureFromFutureWithUnit) {
363  int count = 0;
364  SemiFuture<Unit> fu = SemiFuture<Unit>{makeFutureWith([&] { count++; })};
365  EXPECT_EQ(1, count);
366 }
367 
368 TEST(SemiFuture, MakeSemiFutureFromFutureWithValue) {
369  auto f =
370  SemiFuture<std::unique_ptr<int>>{makeFuture(std::make_unique<int>(42))};
371  auto up = std::move(f.value());
372  EXPECT_EQ(42, *up);
373 }
374 
375 TEST(SemiFuture, MakeSemiFutureFromReadyFuture) {
376  Promise<int> p;
377  auto f = p.getSemiFuture();
378  EXPECT_FALSE(f.isReady());
379  p.setValue(42);
380  EXPECT_TRUE(f.isReady());
381 }
382 
383 TEST(SemiFuture, MakeSemiFutureFromNotReadyFuture) {
384  Promise<int> p;
385  auto f = p.getSemiFuture();
386  EXPECT_THROW(f.value(), eggs_t);
387 }
388 
389 TEST(SemiFuture, MakeFutureFromSemiFuture) {
391  Promise<int> p;
392  std::atomic<int> result{0};
393  auto f = p.getSemiFuture();
394  auto future = std::move(f).via(&e).then([&](int value) {
395  result = value;
396  return value;
397  });
398  e.loopOnce();
399  EXPECT_EQ(result, 0);
400  EXPECT_FALSE(future.isReady());
401  p.setValue(42);
402  e.loopOnce();
403  EXPECT_TRUE(future.isReady());
404  ASSERT_EQ(future.value(), 42);
405  ASSERT_EQ(result, 42);
406 }
407 
408 TEST(SemiFuture, MakeFutureFromSemiFutureReturnFuture) {
410  Promise<int> p;
411  int result{0};
412  auto f = p.getSemiFuture();
413  auto future = std::move(f).via(&e).then([&](int value) {
414  result = value;
415  return folly::makeFuture(std::move(value));
416  });
417  e.loopOnce();
418  EXPECT_EQ(result, 0);
419  EXPECT_FALSE(future.isReady());
420  p.setValue(42);
421  e.loopOnce();
422  EXPECT_TRUE(future.isReady());
423  ASSERT_EQ(future.value(), 42);
424  ASSERT_EQ(result, 42);
425 }
426 
427 TEST(SemiFuture, MakeFutureFromSemiFutureReturnSemiFuture) {
429  Promise<int> p;
430  int result{0};
431  auto f = p.getSemiFuture();
432  auto future = std::move(f)
433  .via(&e)
434  .then([&](int value) {
435  result = value;
436  return folly::makeSemiFuture(std::move(value));
437  })
438  .then([&](int value) {
439  return folly::makeSemiFuture(std::move(value));
440  });
441  e.loopOnce();
442  EXPECT_EQ(result, 0);
443  EXPECT_FALSE(future.isReady());
444  p.setValue(42);
445  e.loopOnce();
446  e.loopOnce();
447  EXPECT_TRUE(future.isReady());
448  ASSERT_EQ(future.value(), 42);
449  ASSERT_EQ(result, 42);
450 }
451 
452 TEST(SemiFuture, MakeFutureFromSemiFutureLValue) {
454  Promise<int> p;
455  std::atomic<int> result{0};
456  auto f = p.getSemiFuture();
457  auto future = std::move(f).via(&e).then([&](int value) {
458  result = value;
459  return value;
460  });
461  e.loopOnce();
462  EXPECT_EQ(result, 0);
463  EXPECT_FALSE(future.isReady());
464  p.setValue(42);
465  e.loopOnce();
466  EXPECT_TRUE(future.isReady());
467  ASSERT_EQ(future.value(), 42);
468  ASSERT_EQ(result, 42);
469 }
470 
471 TEST(SemiFuture, SimpleGet) {
472  EventBase e2;
473  Promise<int> p;
474  auto sf = p.getSemiFuture();
475  p.setValue(3);
476  auto v = std::move(sf).get();
477  ASSERT_EQ(v, 3);
478 }
479 
480 TEST(SemiFuture, SimpleGetTry) {
481  EventBase e2;
482  Promise<int> p;
483  auto sf = p.getSemiFuture();
484  p.setValue(3);
485  auto v = std::move(sf).getTry();
486  ASSERT_EQ(v.value(), 3);
487 }
488 
489 TEST(SemiFuture, SimpleTimedGet) {
491  auto sf = p.getSemiFuture();
492  EXPECT_THROW(
493  std::move(sf).get(std::chrono::milliseconds(100)), FutureTimeout);
494 }
495 
496 TEST(SemiFuture, SimpleTimedGetViaFromSemiFuture) {
499  auto sf = p.getSemiFuture();
500  EXPECT_THROW(
501  std::move(sf).via(&e2).getVia(&e2, std::chrono::milliseconds(100)),
502  FutureTimeout);
503 }
504 
505 TEST(SemiFuture, SimpleTimedGetTry) {
507  auto sf = p.getSemiFuture();
508  EXPECT_THROW(
509  std::move(sf).getTry(std::chrono::milliseconds(100)), FutureTimeout);
510 }
511 
512 TEST(SemiFuture, SimpleTimedGetTryViaFromSemiFuture) {
515  auto sf = p.getSemiFuture();
516  EXPECT_THROW(
517  std::move(sf).via(&e2).getTryVia(&e2, std::chrono::milliseconds(100)),
518  FutureTimeout);
519 }
520 
521 TEST(SemiFuture, SimpleValue) {
522  Promise<int> p;
523  auto sf = p.getSemiFuture();
524  p.setValue(3);
525  auto v = std::move(sf).value();
526  ASSERT_EQ(v, 3);
527 }
528 
529 TEST(SemiFuture, SimpleValueThrow) {
531  auto sf = p.getSemiFuture();
533 }
534 
535 TEST(SemiFuture, SimpleResult) {
536  EventBase e2;
537  Promise<int> p;
538  auto sf = p.getSemiFuture();
539  p.setValue(3);
540  auto v = std::move(sf).result();
541  ASSERT_EQ(v.value(), 3);
542 }
543 
544 TEST(SemiFuture, SimpleResultThrow) {
545  EventBase e2;
547  auto sf = p.getSemiFuture();
548  EXPECT_THROW(std::move(sf).result(), FutureNotReady);
549 }
550 
551 TEST(SemiFuture, SimpleDefer) {
552  std::atomic<int> innerResult{0};
554  auto f = p.getSemiFuture().toUnsafeFuture();
555  auto sf = std::move(f).semi().defer([&](auto&&) { innerResult = 17; });
556  p.setValue();
557  // Run "F" here inline in the calling thread
558  std::move(sf).get();
559  ASSERT_EQ(innerResult, 17);
560 }
561 
562 TEST(SemiFuture, DeferWithDelayedSetValue) {
563  EventBase e2;
565  auto f = p.getSemiFuture().toUnsafeFuture();
566  auto sf = std::move(f).semi().defer([&](auto&&) { return 17; });
567 
568  // Start thread and have it blocking in the semifuture before we satisfy the
569  // promise
570  auto resultF =
571  std::async(std::launch::async, [&]() { return std::move(sf).get(); });
572 
573  // Check that future is not already satisfied before setting the promise
574  // Async task should be blocked on sf.
575  ASSERT_EQ(
576  resultF.wait_for(std::chrono::milliseconds(100)),
577  std::future_status::timeout);
578  p.setValue();
579  ASSERT_EQ(resultF.get(), 17);
580 }
581 
582 TEST(SemiFuture, DeferWithViaAndDelayedSetValue) {
583  EventBase e2;
585  auto f = p.getSemiFuture().toUnsafeFuture();
586  auto sf = std::move(f).semi().defer([&](auto&&) { return 17; }).via(&e2);
587  // Start thread and have it blocking in the semifuture before we satisfy the
588  // promise.
589  auto resultF =
590  std::async(std::launch::async, [&]() { return std::move(sf).get(); });
591  std::thread t([&]() { e2.loopForever(); });
592  // Check that future is not already satisfied before setting the promise
593  // Async task should be blocked on sf.
594  ASSERT_EQ(
595  resultF.wait_for(std::chrono::milliseconds(100)),
596  std::future_status::timeout);
597  p.setValue();
598  e2.terminateLoopSoon();
599  t.join();
600  ASSERT_EQ(resultF.get(), 17);
601 }
602 
603 TEST(SemiFuture, DeferWithGetTimedGet) {
604  std::atomic<int> innerResult{0};
606  auto f = p.getSemiFuture().toUnsafeFuture();
607  auto sf = std::move(f).semi().defer([&](auto&&) { innerResult = 17; });
608  EXPECT_THROW(
609  std::move(sf).get(std::chrono::milliseconds(100)), FutureTimeout);
610  ASSERT_EQ(innerResult, 0);
611 }
612 
613 TEST(SemiFuture, DeferWithVia) {
614  std::atomic<int> innerResult{0};
615  EventBase e2;
617  auto f = p.getSemiFuture().toUnsafeFuture();
618  auto sf = std::move(f).semi().defer([&](auto&&) { innerResult = 17; });
619  // Run "F" here inline in the calling thread
620  auto tf = std::move(sf).via(&e2);
621  p.setValue();
622  tf.getVia(&e2);
623  ASSERT_EQ(innerResult, 17);
624 }
625 
626 TEST(SemiFuture, ChainingDefertoThen) {
627  std::atomic<int> innerResult{0};
628  std::atomic<int> result{0};
629  EventBase e2;
631  auto f = p.getSemiFuture().toUnsafeFuture();
632  auto sf = std::move(f).semi().defer([&](auto&&) { innerResult = 17; });
633  // Run "F" here inline in a task running on the eventbase
634  auto tf = std::move(sf).via(&e2).thenValue([&](auto&&) { result = 42; });
635  p.setValue();
636  tf.getVia(&e2);
637  ASSERT_EQ(innerResult, 17);
638  ASSERT_EQ(result, 42);
639 }
640 
641 TEST(SemiFuture, SimpleDeferWithValue) {
642  std::atomic<int> innerResult{0};
643  Promise<int> p;
644  auto f = p.getSemiFuture().toUnsafeFuture();
645  auto sf = std::move(f).semi().deferValue([&](int a) { innerResult = a; });
646  p.setValue(7);
647  // Run "F" here inline in the calling thread
648  std::move(sf).get();
649  ASSERT_EQ(innerResult, 7);
650 }
651 
652 namespace {
653 int deferValueHelper(int a) {
654  return a;
655 }
656 
657 } // namespace
658 TEST(SemiFuture, SimpleDeferWithValueFunctionReference) {
659  Promise<int> p;
660  auto f = p.getSemiFuture().toUnsafeFuture();
661  auto sf = std::move(f).semi().deferValue(deferValueHelper);
662  p.setValue(7);
663  // Run "F" here inline in the calling thread
664  ASSERT_EQ(std::move(sf).get(), 7);
665 }
666 
667 TEST(SemiFuture, ChainingDefertoThenWithValue) {
668  std::atomic<int> innerResult{0};
669  std::atomic<int> result{0};
670  EventBase e2;
671  Promise<int> p;
672  auto f = p.getSemiFuture().toUnsafeFuture();
673  auto sf = std::move(f).semi().deferValue([&](int a) {
674  innerResult = a;
675  return a;
676  });
677  // Run "F" here inline in a task running on the eventbase
678  auto tf = std::move(sf).via(&e2).then([&](int a) { result = a; });
679  p.setValue(7);
680  tf.getVia(&e2);
681  ASSERT_EQ(innerResult, 7);
682  ASSERT_EQ(result, 7);
683 }
684 
685 TEST(SemiFuture, MakeSemiFutureFromFutureWithTry) {
686  Promise<int> p;
687  auto f = p.getSemiFuture().toUnsafeFuture();
688  auto sf = std::move(f).semi().defer([&](Try<int> t) {
689  if (auto err = t.tryGetExceptionObject<std::logic_error>()) {
690  return Try<std::string>(err->what());
691  }
692  return Try<std::string>(
693  make_exception_wrapper<std::logic_error>("Exception"));
694  });
695  p.setException(make_exception_wrapper<std::logic_error>("Try"));
696  auto tryResult = std::move(sf).get();
697  ASSERT_EQ(tryResult.value(), "Try");
698 }
699 
700 namespace {
701 [[noreturn]] void deferHelper(folly::Try<folly::Unit>&&) {
702  throw eggs;
703 }
704 } // namespace
705 
706 TEST(SemiFuture, DeferWithinContinuation) {
707  std::atomic<int> innerResult{0};
708  std::atomic<int> result{0};
709  EventBase e2;
710  Promise<int> p;
711  Promise<int> p2;
712  auto f = p.getSemiFuture().via(&e2);
713  auto resultF = std::move(f).then([&, p3 = std::move(p2)](int outer) mutable {
714  result = outer;
715  return makeSemiFuture<int>(std::move(outer))
716  .deferValue([&, p4 = std::move(p3)](int inner) mutable {
717  innerResult = inner;
718  p4.setValue(inner);
719  return inner;
720  });
721  });
722  p.setValue(7);
723  auto r = resultF.getVia(&e2);
724  ASSERT_EQ(r, 7);
725  ASSERT_EQ(innerResult, 7);
726  ASSERT_EQ(result, 7);
727 }
728 
729 TEST(SemiFuture, onError) {
730  bool theFlag = false;
731  auto flag = [&] { theFlag = true; };
732 #define EXPECT_FLAG() \
733  do { \
734  EXPECT_TRUE(theFlag); \
735  theFlag = false; \
736  } while (0);
737 
738 #define EXPECT_NO_FLAG() \
739  do { \
740  EXPECT_FALSE(theFlag); \
741  theFlag = false; \
742  } while (0);
743 
744  // By reference
745  {
746  auto f = makeSemiFuture()
747  .defer([](auto&&) { throw eggs; })
748  .deferError<eggs_t>([&](eggs_t const& /* e */) { flag(); });
749  EXPECT_NO_THROW(std::move(f).get());
750  EXPECT_FLAG();
751  }
752 
753  {
754  auto f = makeSemiFuture()
755  .defer(deferHelper)
756  .deferError<eggs_t>([&](eggs_t const& /* e */) { flag(); });
757  EXPECT_NO_THROW(std::move(f).get());
758  EXPECT_FLAG();
759  }
760 
761  // By auto reference
762  {
763  auto f = makeSemiFuture()
764  .defer([](auto&&) { throw eggs; })
765  .deferError<eggs_t>([&](auto& /* e */) { flag(); });
766  EXPECT_NO_THROW(std::move(f).get());
767  EXPECT_FLAG();
768  }
769 
770  // By value
771  {
772  auto f = makeSemiFuture()
773  .defer([](auto&&) { throw eggs; })
774  .deferError<eggs_t>([&](eggs_t /* e */) { flag(); });
775  EXPECT_NO_THROW(std::move(f).get());
776  EXPECT_FLAG();
777  }
778 
779  // auto value
780  {
781  auto f = makeSemiFuture()
782  .defer([](auto&&) { throw eggs; })
783  .deferError<eggs_t>([&](auto /* e */) { flag(); });
784  EXPECT_NO_THROW(std::move(f).get());
785  EXPECT_FLAG();
786  }
787 
788  // Polymorphic
789  {
790  auto f =
792  .defer([](auto&&) { throw eggs; })
793  .deferError<std::exception>([&](auto const& /* e */) { flag(); });
794  EXPECT_NO_THROW(std::move(f).get());
795  EXPECT_FLAG();
796  }
797 
798  // Non-exceptions
799  {
800  auto f = makeSemiFuture()
801  .defer([](auto&&) { throw - 1; })
802  .deferError<int>([&](auto /* e */) { flag(); });
803  EXPECT_NO_THROW(std::move(f).get());
804  EXPECT_FLAG();
805  }
806 
807  // Mutable lambda
808  {
809  auto f =
811  .defer([](auto&&) { throw eggs; })
812  .deferError<eggs_t>([&](auto const& /* e */) mutable { flag(); });
813  EXPECT_NO_THROW(std::move(f).get());
814  EXPECT_FLAG();
815  }
816 
817  // Function pointer
818  {
819  auto f = makeSemiFuture()
820  .defer([](auto &&) -> int { throw eggs; })
821  .deferError<eggs_t>(onErrorHelperEggs)
822  .deferError(onErrorHelperGeneric);
823  EXPECT_EQ(10, std::move(f).get());
824  }
825  {
826  auto f =
828  .defer([](auto &&) -> int { throw std::runtime_error("test"); })
829  .deferError<eggs_t>(onErrorHelperEggs)
830  .deferError(onErrorHelperGeneric);
831  EXPECT_EQ(20, std::move(f).get());
832  }
833  {
834  auto f =
836  .defer([](auto &&) -> int { throw std::runtime_error("test"); })
837  .deferError<eggs_t>(onErrorHelperEggs);
838  EXPECT_THROW(std::move(f).get(), std::runtime_error);
839  }
840 
841  // No throw
842  {
843  auto f = makeSemiFuture()
844  .defer([](auto&&) { return 42; })
845  .deferError<eggs_t>([&](auto& /* e */) {
846  flag();
847  return -1;
848  });
849  EXPECT_NO_FLAG();
850  EXPECT_EQ(42, std::move(f).get());
851  EXPECT_NO_FLAG();
852  }
853 
854  // Catch different exception
855  {
856  auto f = makeSemiFuture()
857  .defer([](auto&&) { throw eggs; })
858  .deferError<std::runtime_error>(
859  [&](auto const& /* e */) { flag(); });
860  EXPECT_THROW(std::move(f).get(), eggs_t);
861  EXPECT_NO_FLAG();
862  }
863 
864  // Returned value propagates
865  {
866  auto f = makeSemiFuture()
867  .defer([](auto &&) -> int { throw eggs; })
868  .deferError<eggs_t>([&](auto const& /* e */) { return 42; });
869  EXPECT_EQ(42, std::move(f).get());
870  }
871 
872  // Throw in callback
873  {
874  auto f = makeSemiFuture()
875  .defer([](auto &&) -> int { throw eggs; })
876  .deferError<eggs_t>([&](auto const& e) -> int { throw e; });
877  EXPECT_THROW(std::move(f).get(), eggs_t);
878  }
879 
880  // exception_wrapper, return T
881  {
882  auto f = makeSemiFuture()
883  .defer([](auto &&) -> int { throw eggs; })
884  .deferError([&](exception_wrapper /* e */) {
885  flag();
886  return -1;
887  });
888  EXPECT_EQ(-1, std::move(f).get());
889  EXPECT_FLAG();
890  }
891 
892  // exception_wrapper, return T but throw
893  {
894  auto f = makeSemiFuture()
895  .defer([](auto &&) -> int { throw eggs; })
896  .deferError([&](exception_wrapper /* e */) -> int {
897  flag();
898  throw eggs;
899  });
900  EXPECT_THROW(std::move(f).get(), eggs_t);
901  EXPECT_FLAG();
902  }
903 
904  // const exception_wrapper&
905  {
906  auto f = makeSemiFuture()
907  .defer([](auto&&) { throw eggs; })
908  .deferError([&](const exception_wrapper& /* e */) { flag(); });
909  EXPECT_NO_THROW(std::move(f).get());
910  EXPECT_FLAG();
911  }
912 }
913 
915  auto c = makePromiseContract<int>();
916  c.first.setValue(3);
917  c.second = std::move(c.second).deferValue([](int _) { return _ + 1; });
918  EXPECT_EQ(4, std::move(c.second).get());
919 }
920 
921 TEST(SemiFuture, invokeCallbackWithOriginalCVRef) {
922  struct Foo {
923  int operator()(int x) & {
924  return x + 1;
925  }
926  int operator()(int x) const& {
927  return x + 2;
928  }
929  int operator()(int x) && {
930  return x + 3;
931  }
932  };
933 
934  Foo foo;
935  Foo const cfoo;
936 
937  // The continuation will be forward-constructed - copied if given as & and
938  // moved if given as && - everywhere construction is required.
939  // The continuation will be invoked with the same cvref as it is passed.
940  EXPECT_EQ(101, makeSemiFuture<int>(100).deferValue(foo).wait().value());
941  EXPECT_EQ(202, makeSemiFuture<int>(200).deferValue(cfoo).wait().value());
942  EXPECT_EQ(303, makeSemiFuture<int>(300).deferValue(Foo()).wait().value());
943 }
944 
945 TEST(SemiFuture, semiFutureWithinCtxCleanedUpWhenTaskFinishedInTime) {
946  // Used to track the use_count of callbackInput even outside of its scope
947  std::weak_ptr<int> target;
948  {
950  auto input = std::make_shared<int>(1);
951  auto longEnough = std::chrono::milliseconds(1000);
952 
953  promise.getSemiFuture()
954  .within(longEnough)
955  .toUnsafeFuture()
956  .then([&target](
957  folly::Try<std::shared_ptr<int>>&& callbackInput) mutable {
958  target = callbackInput.value();
959  });
960  promise.setValue(input);
961  }
962  // After promise's life cycle is finished, make sure no one is holding the
963  // input anymore, in other words, ctx should have been cleaned up.
964  EXPECT_EQ(0, target.use_count());
965 }
966 
967 TEST(SemiFuture, semiFutureWithinNoValueReferenceWhenTimeOut) {
969  auto veryShort = std::chrono::milliseconds(1);
970 
971  promise.getSemiFuture().within(veryShort).toUnsafeFuture().then(
972  [](folly::Try<std::shared_ptr<int>>&& callbackInput) {
973  // Timeout is fired. Verify callbackInput is not referenced
974  EXPECT_EQ(0, callbackInput.value().use_count());
975  });
976 }
977 
978 TEST(SemiFuture, collectAllSemiFutureDeferredWork) {
979  {
980  Promise<int> promise1;
981  Promise<int> promise2;
982 
983  auto future = collectAllSemiFuture(
984  promise1.getSemiFuture().deferValue([](int x) { return x * 2; }),
985  promise2.getSemiFuture().deferValue([](int x) { return x * 2; }));
986 
987  promise1.setValue(1);
988  promise2.setValue(2);
989 
990  auto result = std::move(future).getTry(std::chrono::milliseconds{100});
991 
992  EXPECT_TRUE(result.hasValue());
993 
994  EXPECT_EQ(2, *std::get<0>(*result));
995  EXPECT_EQ(4, *std::get<1>(*result));
996  }
997 
998  {
999  Promise<int> promise1;
1000  Promise<int> promise2;
1001 
1002  auto future = collectAllSemiFuture(
1003  promise1.getSemiFuture().deferValue([](int x) { return x * 2; }),
1004  promise2.getSemiFuture().deferValue([](int x) { return x * 2; }));
1005 
1006  promise1.setValue(1);
1007  promise2.setValue(2);
1008 
1010 
1011  auto value = std::move(future).via(&executor).getVia(&executor);
1012 
1013  EXPECT_EQ(2, *std::get<0>(value));
1014  EXPECT_EQ(4, *std::get<1>(value));
1015  }
1016 
1017  {
1018  Promise<int> promise1;
1019  Promise<int> promise2;
1020 
1021  std::vector<SemiFuture<int>> futures;
1022  futures.push_back(
1023  promise1.getSemiFuture().deferValue([](int x) { return x * 2; }));
1024  futures.push_back(
1025  promise2.getSemiFuture().deferValue([](int x) { return x * 2; }));
1026 
1027  auto future = collectAllSemiFuture(futures);
1028 
1029  promise1.setValue(1);
1030  promise2.setValue(2);
1031 
1032  EXPECT_TRUE(future.wait().isReady());
1033 
1034  auto value = std::move(future).get();
1035  EXPECT_EQ(2, *value[0]);
1036  EXPECT_EQ(4, *value[1]);
1037  }
1038 
1039  {
1040  bool deferredDestroyed = false;
1041 
1042  {
1043  Promise<int> promise;
1044  auto guard = makeGuard([&] { deferredDestroyed = true; });
1045  collectAllSemiFuture(promise.getSemiFuture().deferValue(
1046  [guard = std::move(guard)](int x) { return x; }));
1047  }
1048 
1049  EXPECT_TRUE(deferredDestroyed);
1050  }
1051 }
1052 
1053 TEST(SemiFuture, DeferWithNestedSemiFuture) {
1055  auto future = futures::sleep(std::chrono::milliseconds{100})
1056  .semi()
1057  .deferValue([](auto&&) {
1058  return futures::sleep(std::chrono::milliseconds{200});
1059  });
1060  future.wait();
1061  EXPECT_TRUE(future.hasValue());
1062  EXPECT_GE(
1063  std::chrono::steady_clock::now() - start, std::chrono::milliseconds{300});
1064 }
Definition: InvokeTest.cpp:58
auto f
static SemiFuture< T > makeEmpty()
Definition: Future-inl.h:775
#define EXPECT_NO_THROW(statement)
Definition: gtest.h:1845
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
auto async(F &&fn)
Definition: Async.h:24
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Future< Unit > sleep(Duration dur, Timekeeper *tk)
Definition: Future.cpp:42
std::chrono::steady_clock::time_point now()
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
const int x
void setException(exception_wrapper ew)
Definition: Promise-inl.h:111
SemiFuture< std::tuple< Try< typename remove_cvref_t< Fs >::value_type >... > > collectAllSemiFuture(Fs &&...fs)
Definition: Future-inl.h:1441
#define EXPECT_NO_FLAG()
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
in_place_tag in_place(in_place_tag={})
Definition: Utility.h:235
static once_flag flag
Definition: Random.cpp:75
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
#define EXPECT_FLAG()
std::enable_if< isFutureOrSemiFuture< invoke_result_t< F > >::value, SemiFuture< typename invoke_result_t< F >::value_type > >::type makeSemiFutureWith(F &&func)
Definition: Future-inl.h:721
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
Definition: Utility.h:72
auto const foo
Definition: LazyTest.cpp:49
#define EXPECT_TYPE(x, T)
#define DOIT(CREATION_EXPR)
bool loopOnce(int flags=0)
Definition: EventBase.cpp:271
void terminateLoopSoon()
Definition: EventBase.cpp:493
GuardImpl guard(ErrorHandler &&handler)
Definition: Base.h:840
bool wait(Waiter *waiter, bool shouldSleep, Waiter *&next)
char a
std::exception * tryGetExceptionObject()
Definition: Try.h:292
auto start
Definition: Try.h:51
int * count
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
std::enable_if< std::is_same< Unit, B >::value, void >::type setValue()
Definition: Promise.h:326
SemiFuture< T > getSemiFuture()
Definition: Promise-inl.h:88
FOLLY_NODISCARD detail::ScopeGuardImplDecay< F, true > makeGuard(F &&f) noexcept(noexcept(detail::ScopeGuardImplDecay< F, true >(static_cast< F && >(f))))
Definition: ScopeGuard.h:184
std::pair< Promise< T >, SemiFuture< T > > makePromiseContract()
Definition: Future.h:925
void fun()
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
auto via(Executor *x, Func &&func) -> Future< typename isFutureOrSemiFuture< decltype(std::declval< Func >()())>::Inner >
Definition: Future-inl.h:1290
FutureException eggs_t
const internal::AnythingMatcher _
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
static eggs_t eggs("eggs")
char c
TEST(SequencedExecutor, CPUThreadPoolExecutor)
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
std::enable_if< isFuture< invoke_result_t< F > >::value, invoke_result_t< F > >::type makeFutureWith(F &&func)
Definition: Future-inl.h:1322
static Future< T > makeEmpty()
Definition: Future-inl.h:951
SemiFuture< typename std::decay< T >::type > makeSemiFuture(T &&t)
Definition: Future-inl.h:712