1f0fad3c005317d3ac38cbe641c609a3cc3e054d
[folly.git] / folly / wangle / test / FutureTest.cpp
1 /*
2  * Copyright 2014 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 <algorithm>
18 #include <atomic>
19 #include <folly/small_vector.h>
20 #include <gtest/gtest.h>
21 #include <memory>
22 #include <string>
23 #include <thread>
24 #include <type_traits>
25 #include <unistd.h>
26 #include <folly/wangle/Executor.h>
27 #include <folly/wangle/Future.h>
28 #include <folly/wangle/ManualExecutor.h>
29
30 using namespace folly::wangle;
31 using std::pair;
32 using std::string;
33 using std::unique_ptr;
34 using std::vector;
35
36 #define EXPECT_TYPE(x, T) \
37   EXPECT_TRUE((std::is_same<decltype(x), T>::value))
38
39 typedef WangleException eggs_t;
40 static eggs_t eggs("eggs");
41
42 // Future
43
44 TEST(Future, try) {
45   class A {
46    public:
47     A(int x) : x_(x) {}
48
49     int x() const {
50       return x_;
51     }
52    private:
53     int x_;
54   };
55
56   A a(5);
57   Try<A> t_a(std::move(a));
58
59   Try<void> t_void;
60
61   EXPECT_EQ(5, t_a.value().x());
62 }
63
64 TEST(Future, special) {
65   EXPECT_FALSE(std::is_copy_constructible<Future<int>>::value);
66   EXPECT_FALSE(std::is_copy_assignable<Future<int>>::value);
67   EXPECT_TRUE(std::is_move_constructible<Future<int>>::value);
68   EXPECT_TRUE(std::is_move_assignable<Future<int>>::value);
69 }
70
71 TEST(Future, then) {
72   bool flag = false;
73
74   makeFuture<int>(42).then([&](Try<int>&& t) {
75                               flag = true;
76                               EXPECT_EQ(42, t.value());
77                             });
78   EXPECT_TRUE(flag); flag = false;
79
80   makeFuture<int>(42)
81     .then([](Try<int>&& t) { return t.value(); })
82     .then([&](Try<int>&& t) { flag = true; EXPECT_EQ(42, t.value()); });
83   EXPECT_TRUE(flag); flag = false;
84
85   makeFuture().then([&](Try<void>&& t) { flag = true; t.value(); });
86   EXPECT_TRUE(flag); flag = false;
87
88   Promise<void> p;
89   auto f = p.getFuture().then([&](Try<void>&& t) { flag = true; });
90   EXPECT_FALSE(flag);
91   EXPECT_FALSE(f.isReady());
92   p.setValue();
93   EXPECT_TRUE(flag);
94   EXPECT_TRUE(f.isReady());
95 }
96
97 static string doWorkStatic(Try<string>&& t) {
98   return t.value() + ";static";
99 }
100
101 TEST(Future, thenFunction) {
102   struct Worker {
103     string doWork(Try<string>&& t) {
104       return t.value() + ";class";
105     }
106     static string doWorkStatic(Try<string>&& t) {
107       return t.value() + ";class-static";
108     }
109   } w;
110
111   auto f = makeFuture<string>("start")
112     .then(doWorkStatic)
113     .then(Worker::doWorkStatic)
114     .then(&w, &Worker::doWork);
115
116   EXPECT_EQ(f.value(), "start;static;class-static;class");
117 }
118
119 static Future<string> doWorkStaticFuture(Try<string>&& t) {
120   return makeFuture(t.value() + ";static");
121 }
122
123 TEST(Future, thenFunctionFuture) {
124   struct Worker {
125     Future<string> doWorkFuture(Try<string>&& t) {
126       return makeFuture(t.value() + ";class");
127     }
128     static Future<string> doWorkStaticFuture(Try<string>&& t) {
129       return makeFuture(t.value() + ";class-static");
130     }
131   } w;
132
133   auto f = makeFuture<string>("start")
134     .then(doWorkStaticFuture)
135     .then(Worker::doWorkStaticFuture)
136     .then(&w, &Worker::doWorkFuture);
137
138   EXPECT_EQ(f.value(), "start;static;class-static;class");
139 }
140
141 TEST(Future, value) {
142   auto f = makeFuture(unique_ptr<int>(new int(42)));
143   auto up = std::move(f.value());
144   EXPECT_EQ(42, *up);
145
146   EXPECT_THROW(makeFuture<int>(eggs).value(), eggs_t);
147 }
148
149 TEST(Future, isReady) {
150   Promise<int> p;
151   auto f = p.getFuture();
152   EXPECT_FALSE(f.isReady());
153   p.setValue(42);
154   EXPECT_TRUE(f.isReady());
155   }
156
157 TEST(Future, futureNotReady) {
158   Promise<int> p;
159   Future<int> f = p.getFuture();
160   EXPECT_THROW(f.value(), eggs_t);
161 }
162
163 TEST(Future, hasException) {
164   EXPECT_TRUE(makeFuture<int>(eggs).getTry().hasException());
165   EXPECT_FALSE(makeFuture(42).getTry().hasException());
166 }
167
168 TEST(Future, hasValue) {
169   EXPECT_TRUE(makeFuture(42).getTry().hasValue());
170   EXPECT_FALSE(makeFuture<int>(eggs).getTry().hasValue());
171 }
172
173 TEST(Future, makeFuture) {
174   EXPECT_TYPE(makeFuture(42), Future<int>);
175   EXPECT_EQ(42, makeFuture(42).value());
176
177   EXPECT_TYPE(makeFuture<float>(42), Future<float>);
178   EXPECT_EQ(42, makeFuture<float>(42).value());
179
180   auto fun = [] { return 42; };
181   EXPECT_TYPE(makeFutureTry(fun), Future<int>);
182   EXPECT_EQ(42, makeFutureTry(fun).value());
183
184   auto failfun = []() -> int { throw eggs; };
185   EXPECT_TYPE(makeFutureTry(failfun), Future<int>);
186   EXPECT_THROW(makeFutureTry(failfun).value(), eggs_t);
187
188   EXPECT_TYPE(makeFuture(), Future<void>);
189 }
190
191 // Promise
192
193 TEST(Promise, special) {
194   EXPECT_FALSE(std::is_copy_constructible<Promise<int>>::value);
195   EXPECT_FALSE(std::is_copy_assignable<Promise<int>>::value);
196   EXPECT_TRUE(std::is_move_constructible<Promise<int>>::value);
197   EXPECT_TRUE(std::is_move_assignable<Promise<int>>::value);
198 }
199
200 TEST(Promise, getFuture) {
201   Promise<int> p;
202   Future<int> f = p.getFuture();
203   EXPECT_FALSE(f.isReady());
204 }
205
206 TEST(Promise, setValue) {
207   Promise<int> fund;
208   auto ffund = fund.getFuture();
209   fund.setValue(42);
210   EXPECT_EQ(42, ffund.value());
211
212   struct Foo {
213     string name;
214     int value;
215   };
216
217   Promise<Foo> pod;
218   auto fpod = pod.getFuture();
219   Foo f = {"the answer", 42};
220   pod.setValue(f);
221   Foo f2 = fpod.value();
222   EXPECT_EQ(f.name, f2.name);
223   EXPECT_EQ(f.value, f2.value);
224
225   pod = Promise<Foo>();
226   fpod = pod.getFuture();
227   pod.setValue(std::move(f2));
228   Foo f3 = fpod.value();
229   EXPECT_EQ(f.name, f3.name);
230   EXPECT_EQ(f.value, f3.value);
231
232   Promise<unique_ptr<int>> mov;
233   auto fmov = mov.getFuture();
234   mov.setValue(unique_ptr<int>(new int(42)));
235   unique_ptr<int> ptr = std::move(fmov.value());
236   EXPECT_EQ(42, *ptr);
237
238   Promise<void> v;
239   auto fv = v.getFuture();
240   v.setValue();
241   EXPECT_TRUE(fv.isReady());
242 }
243
244 TEST(Promise, setException) {
245   {
246     Promise<void> p;
247     auto f = p.getFuture();
248     p.setException(eggs);
249     EXPECT_THROW(f.value(), eggs_t);
250   }
251   {
252     Promise<void> p;
253     auto f = p.getFuture();
254     try {
255       throw eggs;
256     } catch (...) {
257       p.setException(std::current_exception());
258     }
259     EXPECT_THROW(f.value(), eggs_t);
260   }
261 }
262
263 TEST(Promise, fulfil) {
264   {
265     Promise<int> p;
266     auto f = p.getFuture();
267     p.fulfil([] { return 42; });
268     EXPECT_EQ(42, f.value());
269   }
270   {
271     Promise<int> p;
272     auto f = p.getFuture();
273     p.fulfil([]() -> int { throw eggs; });
274     EXPECT_THROW(f.value(), eggs_t);
275   }
276 }
277
278 TEST(Future, finish) {
279   auto x = std::make_shared<int>(0);
280   {
281     Promise<int> p;
282     auto f = p.getFuture().then([x](Try<int>&& t) { *x = t.value(); });
283
284     // The callback hasn't executed
285     EXPECT_EQ(0, *x);
286
287     // The callback has a reference to x
288     EXPECT_EQ(2, x.use_count());
289
290     p.setValue(42);
291
292     // the callback has executed
293     EXPECT_EQ(42, *x);
294   }
295   // the callback has been destructed
296   // and has released its reference to x
297   EXPECT_EQ(1, x.use_count());
298 }
299
300 TEST(Future, unwrap) {
301   Promise<int> a;
302   Promise<int> b;
303
304   auto fa = a.getFuture();
305   auto fb = b.getFuture();
306
307   bool flag1 = false;
308   bool flag2 = false;
309
310   // do a, then do b, and get the result of a + b.
311   Future<int> f = fa.then([&](Try<int>&& ta) {
312     auto va = ta.value();
313     flag1 = true;
314     return fb.then([va, &flag2](Try<int>&& tb) {
315       flag2 = true;
316       return va + tb.value();
317     });
318   });
319
320   EXPECT_FALSE(flag1);
321   EXPECT_FALSE(flag2);
322   EXPECT_FALSE(f.isReady());
323
324   a.setValue(3);
325   EXPECT_TRUE(flag1);
326   EXPECT_FALSE(flag2);
327   EXPECT_FALSE(f.isReady());
328
329   b.setValue(4);
330   EXPECT_TRUE(flag1);
331   EXPECT_TRUE(flag2);
332   EXPECT_EQ(7, f.value());
333 }
334
335 TEST(Future, whenAll) {
336   // returns a vector variant
337   {
338     vector<Promise<int>> promises(10);
339     vector<Future<int>> futures;
340
341     for (auto& p : promises)
342       futures.push_back(p.getFuture());
343
344     auto allf = whenAll(futures.begin(), futures.end());
345
346     random_shuffle(promises.begin(), promises.end());
347     for (auto& p : promises) {
348       EXPECT_FALSE(allf.isReady());
349       p.setValue(42);
350     }
351
352     EXPECT_TRUE(allf.isReady());
353     auto& results = allf.value();
354     for (auto& t : results) {
355       EXPECT_EQ(42, t.value());
356     }
357   }
358
359   // check error semantics
360   {
361     vector<Promise<int>> promises(4);
362     vector<Future<int>> futures;
363
364     for (auto& p : promises)
365       futures.push_back(p.getFuture());
366
367     auto allf = whenAll(futures.begin(), futures.end());
368
369
370     promises[0].setValue(42);
371     promises[1].setException(eggs);
372
373     EXPECT_FALSE(allf.isReady());
374
375     promises[2].setValue(42);
376
377     EXPECT_FALSE(allf.isReady());
378
379     promises[3].setException(eggs);
380
381     EXPECT_TRUE(allf.isReady());
382     EXPECT_FALSE(allf.getTry().hasException());
383
384     auto& results = allf.value();
385     EXPECT_EQ(42, results[0].value());
386     EXPECT_TRUE(results[1].hasException());
387     EXPECT_EQ(42, results[2].value());
388     EXPECT_TRUE(results[3].hasException());
389   }
390
391   // check that futures are ready in then()
392   {
393     vector<Promise<void>> promises(10);
394     vector<Future<void>> futures;
395
396     for (auto& p : promises)
397       futures.push_back(p.getFuture());
398
399     auto allf = whenAll(futures.begin(), futures.end())
400       .then([](Try<vector<Try<void>>>&& ts) {
401         for (auto& f : ts.value())
402           f.value();
403       });
404
405     random_shuffle(promises.begin(), promises.end());
406     for (auto& p : promises)
407       p.setValue();
408     EXPECT_TRUE(allf.isReady());
409   }
410 }
411
412
413 TEST(Future, whenAny) {
414   {
415     vector<Promise<int>> promises(10);
416     vector<Future<int>> futures;
417
418     for (auto& p : promises)
419       futures.push_back(p.getFuture());
420
421     for (auto& f : futures) {
422       EXPECT_FALSE(f.isReady());
423     }
424
425     auto anyf = whenAny(futures.begin(), futures.end());
426
427     /* futures were moved in, so these are invalid now */
428     EXPECT_FALSE(anyf.isReady());
429
430     promises[7].setValue(42);
431     EXPECT_TRUE(anyf.isReady());
432     auto& idx_fut = anyf.value();
433
434     auto i = idx_fut.first;
435     EXPECT_EQ(7, i);
436
437     auto& f = idx_fut.second;
438     EXPECT_EQ(42, f.value());
439   }
440
441   // error
442   {
443     vector<Promise<void>> promises(10);
444     vector<Future<void>> futures;
445
446     for (auto& p : promises)
447       futures.push_back(p.getFuture());
448
449     for (auto& f : futures) {
450       EXPECT_FALSE(f.isReady());
451     }
452
453     auto anyf = whenAny(futures.begin(), futures.end());
454
455     EXPECT_FALSE(anyf.isReady());
456
457     promises[3].setException(eggs);
458     EXPECT_TRUE(anyf.isReady());
459     EXPECT_TRUE(anyf.value().second.hasException());
460   }
461
462   // then()
463   {
464     vector<Promise<int>> promises(10);
465     vector<Future<int>> futures;
466
467     for (auto& p : promises)
468       futures.push_back(p.getFuture());
469
470     auto anyf = whenAny(futures.begin(), futures.end())
471       .then([](Try<pair<size_t, Try<int>>>&& f) {
472         EXPECT_EQ(42, f.value().second.value());
473       });
474
475     promises[3].setValue(42);
476     EXPECT_TRUE(anyf.isReady());
477   }
478 }
479
480
481 TEST(when, already_completed) {
482   {
483     vector<Future<void>> fs;
484     for (int i = 0; i < 10; i++)
485       fs.push_back(makeFuture());
486
487     whenAll(fs.begin(), fs.end())
488       .then([&](Try<vector<Try<void>>>&& t) {
489         EXPECT_EQ(fs.size(), t.value().size());
490       });
491   }
492   {
493     vector<Future<int>> fs;
494     for (int i = 0; i < 10; i++)
495       fs.push_back(makeFuture(i));
496
497     whenAny(fs.begin(), fs.end())
498       .then([&](Try<pair<size_t, Try<int>>>&& t) {
499         auto& p = t.value();
500         EXPECT_EQ(p.first, p.second.value());
501       });
502   }
503 }
504
505 TEST(when, whenN) {
506   vector<Promise<void>> promises(10);
507   vector<Future<void>> futures;
508
509   for (auto& p : promises)
510     futures.push_back(p.getFuture());
511
512   bool flag = false;
513   size_t n = 3;
514   whenN(futures.begin(), futures.end(), n)
515     .then([&](Try<vector<pair<size_t, Try<void>>>>&& t) {
516       flag = true;
517       auto v = t.value();
518       EXPECT_EQ(n, v.size());
519       for (auto& tt : v)
520         EXPECT_TRUE(tt.second.hasValue());
521     });
522
523   promises[0].setValue();
524   EXPECT_FALSE(flag);
525   promises[1].setValue();
526   EXPECT_FALSE(flag);
527   promises[2].setValue();
528   EXPECT_TRUE(flag);
529 }
530
531 /* Ensure that we can compile when_{all,any} with folly::small_vector */
532 TEST(when, small_vector) {
533
534   static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<void>),
535                 "Futures should not be trivially copyable");
536   static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(Future<int>),
537                 "Futures should not be trivially copyable");
538
539   using folly::small_vector;
540   {
541     small_vector<Future<void>> futures;
542
543     for (int i = 0; i < 10; i++)
544       futures.push_back(makeFuture());
545
546     auto anyf = whenAny(futures.begin(), futures.end());
547   }
548
549   {
550     small_vector<Future<void>> futures;
551
552     for (int i = 0; i < 10; i++)
553       futures.push_back(makeFuture());
554
555     auto allf = whenAll(futures.begin(), futures.end());
556   }
557 }
558
559 TEST(Future, whenAllVariadic) {
560   Promise<bool> pb;
561   Promise<int> pi;
562   Future<bool> fb = pb.getFuture();
563   Future<int> fi = pi.getFuture();
564   bool flag = false;
565   whenAll(std::move(fb), std::move(fi))
566     .then([&](Try<std::tuple<Try<bool>, Try<int>>>&& t) {
567       flag = true;
568       EXPECT_TRUE(t.hasValue());
569       EXPECT_TRUE(std::get<0>(t.value()).hasValue());
570       EXPECT_EQ(std::get<0>(t.value()).value(), true);
571       EXPECT_TRUE(std::get<1>(t.value()).hasValue());
572       EXPECT_EQ(std::get<1>(t.value()).value(), 42);
573     });
574   pb.setValue(true);
575   EXPECT_FALSE(flag);
576   pi.setValue(42);
577   EXPECT_TRUE(flag);
578 }
579
580 TEST(Future, whenAllVariadicReferences) {
581   Promise<bool> pb;
582   Promise<int> pi;
583   Future<bool> fb = pb.getFuture();
584   Future<int> fi = pi.getFuture();
585   bool flag = false;
586   whenAll(fb, fi)
587     .then([&](Try<std::tuple<Try<bool>, Try<int>>>&& t) {
588       flag = true;
589       EXPECT_TRUE(t.hasValue());
590       EXPECT_TRUE(std::get<0>(t.value()).hasValue());
591       EXPECT_EQ(std::get<0>(t.value()).value(), true);
592       EXPECT_TRUE(std::get<1>(t.value()).hasValue());
593       EXPECT_EQ(std::get<1>(t.value()).value(), 42);
594     });
595   pb.setValue(true);
596   EXPECT_FALSE(flag);
597   pi.setValue(42);
598   EXPECT_TRUE(flag);
599 }
600
601 TEST(Future, whenAll_none) {
602   vector<Future<int>> fs;
603   auto f = whenAll(fs.begin(), fs.end());
604   EXPECT_TRUE(f.isReady());
605 }
606
607 TEST(Future, throwCaughtInImmediateThen) {
608   // Neither of these should throw "Promise already satisfied"
609   makeFuture().then(
610     [=](Try<void>&&) -> int { throw std::exception(); });
611   makeFuture().then(
612     [=](Try<void>&&) -> Future<int> { throw std::exception(); });
613 }
614
615 TEST(Future, throwIfFailed) {
616   makeFuture<void>(eggs)
617     .then([=](Try<void>&& t) {
618       EXPECT_THROW(t.throwIfFailed(), eggs_t);
619     });
620   makeFuture()
621     .then([=](Try<void>&& t) {
622       EXPECT_NO_THROW(t.throwIfFailed());
623     });
624
625   makeFuture<int>(eggs)
626     .then([=](Try<int>&& t) {
627       EXPECT_THROW(t.throwIfFailed(), eggs_t);
628     });
629   makeFuture<int>(42)
630     .then([=](Try<int>&& t) {
631       EXPECT_NO_THROW(t.throwIfFailed());
632     });
633 }
634
635 TEST(Future, waitWithSemaphoreImmediate) {
636   waitWithSemaphore(makeFuture());
637   auto done = waitWithSemaphore(makeFuture(42)).value();
638   EXPECT_EQ(42, done);
639
640   vector<int> v{1,2,3};
641   auto done_v = waitWithSemaphore(makeFuture(v)).value();
642   EXPECT_EQ(v.size(), done_v.size());
643   EXPECT_EQ(v, done_v);
644
645   vector<Future<void>> v_f;
646   v_f.push_back(makeFuture());
647   v_f.push_back(makeFuture());
648   auto done_v_f = waitWithSemaphore(whenAll(v_f.begin(), v_f.end())).value();
649   EXPECT_EQ(2, done_v_f.size());
650
651   vector<Future<bool>> v_fb;
652   v_fb.push_back(makeFuture(true));
653   v_fb.push_back(makeFuture(false));
654   auto fut = whenAll(v_fb.begin(), v_fb.end());
655   auto done_v_fb = std::move(waitWithSemaphore(std::move(fut)).value());
656   EXPECT_EQ(2, done_v_fb.size());
657 }
658
659 TEST(Future, waitWithSemaphore) {
660   Promise<int> p;
661   Future<int> f = p.getFuture();
662   std::atomic<bool> flag{false};
663   std::atomic<int> result{1};
664   std::atomic<std::thread::id> id;
665
666   std::thread t([&](Future<int>&& tf){
667       auto n = tf.then([&](Try<int> && t) {
668           id = std::this_thread::get_id();
669           return t.value();
670         });
671       flag = true;
672       result.store(waitWithSemaphore(std::move(n)).value());
673       LOG(INFO) << result;
674     },
675     std::move(f)
676     );
677   while(!flag){}
678   EXPECT_EQ(result.load(), 1);
679   p.setValue(42);
680   t.join();
681   // validate that the callback ended up executing in this thread, which
682   // is more to ensure that this test actually tests what it should
683   EXPECT_EQ(id, std::this_thread::get_id());
684   EXPECT_EQ(result.load(), 42);
685 }
686
687 TEST(Future, waitWithSemaphoreForTime) {
688  {
689   Promise<int> p;
690   Future<int> f = p.getFuture();
691   auto t = waitWithSemaphore(std::move(f),
692     std::chrono::microseconds(1));
693   EXPECT_FALSE(t.isReady());
694   p.setValue(1);
695   EXPECT_TRUE(t.isReady());
696  }
697  {
698   Promise<int> p;
699   Future<int> f = p.getFuture();
700   p.setValue(1);
701   auto t = waitWithSemaphore(std::move(f),
702     std::chrono::milliseconds(1));
703   EXPECT_TRUE(t.isReady());
704  }
705  {
706   vector<Future<bool>> v_fb;
707   v_fb.push_back(makeFuture(true));
708   v_fb.push_back(makeFuture(false));
709   auto f = whenAll(v_fb.begin(), v_fb.end());
710   auto t = waitWithSemaphore(std::move(f),
711     std::chrono::milliseconds(1));
712   EXPECT_TRUE(t.isReady());
713   EXPECT_EQ(2, t.value().size());
714  }
715  {
716   vector<Future<bool>> v_fb;
717   Promise<bool> p1;
718   Promise<bool> p2;
719   v_fb.push_back(p1.getFuture());
720   v_fb.push_back(p2.getFuture());
721   auto f = whenAll(v_fb.begin(), v_fb.end());
722   auto t = waitWithSemaphore(std::move(f),
723     std::chrono::milliseconds(1));
724   EXPECT_FALSE(t.isReady());
725   p1.setValue(true);
726   EXPECT_FALSE(t.isReady());
727   p2.setValue(true);
728   EXPECT_TRUE(t.isReady());
729  }
730  {
731   auto t = waitWithSemaphore(makeFuture(),
732     std::chrono::milliseconds(1));
733   EXPECT_TRUE(t.isReady());
734  }
735 }
736
737 TEST(Future, callbackAfterActivate) {
738   Promise<void> p;
739   auto f = p.getFuture();
740   f.deactivate();
741
742   size_t count = 0;
743   f.then([&](Try<void>&&) { count++; });
744
745   p.setValue();
746   EXPECT_EQ(0, count);
747
748   f.activate();
749   EXPECT_EQ(1, count);
750 }
751
752 TEST(Future, activateOnDestruct) {
753   Promise<void> p;
754   auto f = p.getFuture();
755   f.deactivate();
756
757   size_t count = 0;
758   f.then([&](Try<void>&&) { count++; });
759
760   p.setValue();
761   EXPECT_EQ(0, count);
762
763   f = makeFuture(); // force destruction of old f
764   EXPECT_EQ(1, count);
765 }
766
767 TEST(Future, viaIsCold) {
768   ManualExecutor x;
769   size_t count = 0;
770
771   auto fv = makeFuture().via(&x);
772   fv.then([&](Try<void>&&) { count++; });
773
774   EXPECT_EQ(0, count);
775
776   fv.activate();
777
778   EXPECT_EQ(1, x.run());
779   EXPECT_EQ(1, count);
780 }
781
782 TEST(Future, getFuture_after_setValue) {
783   Promise<int> p;
784   p.setValue(42);
785   EXPECT_EQ(42, p.getFuture().value());
786 }
787
788 TEST(Future, getFuture_after_setException) {
789   Promise<void> p;
790   p.fulfil([]() -> void { throw std::logic_error("foo"); });
791   EXPECT_THROW(p.getFuture().value(), std::logic_error);
792 }