suppress warnings in tests for deprecated functions
[folly.git] / folly / futures / test / SemiFutureTest.cpp
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>
20 #include <folly/futures/Future.h>
21 #include <folly/io/async/EventBase.h>
22 #include <folly/portability/GTest.h>
23 #include <folly/synchronization/Baton.h>
24
25 #include <algorithm>
26 #include <atomic>
27 #include <memory>
28 #include <numeric>
29 #include <string>
30 #include <thread>
31 #include <type_traits>
32
33 using namespace folly;
34
35 #define EXPECT_TYPE(x, T) EXPECT_TRUE((std::is_same<decltype(x), T>::value))
36
37 typedef FutureException eggs_t;
38 static eggs_t eggs("eggs");
39
40 // Future
41
42 TEST(SemiFuture, makeEmpty) {
43   auto f = SemiFuture<int>::makeEmpty();
44   EXPECT_THROW(f.isReady(), NoState);
45 }
46
47 TEST(SemiFuture, futureDefaultCtor) {
48   SemiFuture<Unit>();
49 }
50
51 TEST(SemiFuture, makeSemiFutureWithUnit) {
52   int count = 0;
53   SemiFuture<Unit> fu = makeSemiFutureWith([&] { count++; });
54   EXPECT_EQ(1, count);
55 }
56
57 namespace {
58 SemiFuture<int> onErrorHelperEggs(const eggs_t&) {
59   return makeSemiFuture(10);
60 }
61 SemiFuture<int> onErrorHelperGeneric(const std::exception&) {
62   return makeSemiFuture(20);
63 }
64 } // namespace
65
66 TEST(SemiFuture, special) {
67   EXPECT_FALSE(std::is_copy_constructible<SemiFuture<int>>::value);
68   EXPECT_FALSE(std::is_copy_assignable<SemiFuture<int>>::value);
69   EXPECT_TRUE(std::is_move_constructible<SemiFuture<int>>::value);
70   EXPECT_TRUE(std::is_move_assignable<SemiFuture<int>>::value);
71 }
72
73 TEST(SemiFuture, value) {
74   auto f = makeSemiFuture(std::make_unique<int>(42));
75   auto up = std::move(f.value());
76   EXPECT_EQ(42, *up);
77
78   EXPECT_THROW(makeSemiFuture<int>(eggs).value(), eggs_t);
79
80   EXPECT_TYPE(std::declval<SemiFuture<int>&>().value(), int&);
81   EXPECT_TYPE(std::declval<SemiFuture<int> const&>().value(), int const&);
82   EXPECT_TYPE(std::declval<SemiFuture<int>&&>().value(), int&&);
83   EXPECT_TYPE(std::declval<SemiFuture<int> const&&>().value(), int const&&);
84 }
85
86 TEST(SemiFuture, hasException) {
87   EXPECT_TRUE(makeSemiFuture<int>(eggs).getTry().hasException());
88   EXPECT_FALSE(makeSemiFuture(42).getTry().hasException());
89 }
90
91 TEST(SemiFuture, hasValue) {
92   EXPECT_TRUE(makeSemiFuture(42).getTry().hasValue());
93   EXPECT_FALSE(makeSemiFuture<int>(eggs).getTry().hasValue());
94 }
95
96 TEST(SemiFuture, makeSemiFuture) {
97   EXPECT_TYPE(makeSemiFuture(42), SemiFuture<int>);
98   EXPECT_EQ(42, makeSemiFuture(42).value());
99
100   EXPECT_TYPE(makeSemiFuture<float>(42), SemiFuture<float>);
101   EXPECT_EQ(42, makeSemiFuture<float>(42).value());
102
103   auto fun = [] { return 42; };
104   EXPECT_TYPE(makeSemiFutureWith(fun), SemiFuture<int>);
105   EXPECT_EQ(42, makeSemiFutureWith(fun).value());
106
107   auto funf = [] { return makeSemiFuture<int>(43); };
108   EXPECT_TYPE(makeSemiFutureWith(funf), SemiFuture<int>);
109   EXPECT_EQ(43, makeSemiFutureWith(funf).value());
110
111   auto failfun = []() -> int { throw eggs; };
112   EXPECT_TYPE(makeSemiFutureWith(failfun), SemiFuture<int>);
113   EXPECT_NO_THROW(makeSemiFutureWith(failfun));
114   EXPECT_THROW(makeSemiFutureWith(failfun).value(), eggs_t);
115
116   auto failfunf = []() -> SemiFuture<int> { throw eggs; };
117   EXPECT_TYPE(makeSemiFutureWith(failfunf), SemiFuture<int>);
118   EXPECT_NO_THROW(makeSemiFutureWith(failfunf));
119   EXPECT_THROW(makeSemiFutureWith(failfunf).value(), eggs_t);
120
121   EXPECT_TYPE(makeSemiFuture(), SemiFuture<Unit>);
122 }
123
124 TEST(SemiFuture, Constructor) {
125   auto f1 = []() -> SemiFuture<int> { return SemiFuture<int>(3); }();
126   EXPECT_EQ(f1.value(), 3);
127   auto f2 = []() -> SemiFuture<Unit> { return SemiFuture<Unit>(); }();
128   EXPECT_NO_THROW(f2.value());
129 }
130
131 TEST(SemiFuture, ImplicitConstructor) {
132   auto f1 = []() -> SemiFuture<int> { return 3; }();
133   EXPECT_EQ(f1.value(), 3);
134 }
135
136 TEST(SemiFuture, InPlaceConstructor) {
137   auto f = SemiFuture<std::pair<int, double>>(in_place, 5, 3.2);
138   EXPECT_EQ(5, f.value().first);
139 }
140
141 TEST(SemiFuture, makeSemiFutureNoThrow) {
142   makeSemiFuture().value();
143 }
144
145 TEST(SemiFuture, ViaThrowOnNull) {
146   EXPECT_THROW(makeSemiFuture().via(nullptr), NoExecutor);
147 }
148
149 TEST(SemiFuture, ConstructSemiFutureFromEmptyFuture) {
150   auto f = SemiFuture<int>{Future<int>::makeEmpty()};
151   EXPECT_THROW(f.isReady(), NoState);
152 }
153
154 TEST(SemiFuture, ConstructSemiFutureFromFutureDefaultCtor) {
155   SemiFuture<Unit>(Future<Unit>{});
156 }
157
158 TEST(SemiFuture, MakeSemiFutureFromFutureWithUnit) {
159   int count = 0;
160   SemiFuture<Unit> fu = SemiFuture<Unit>{makeFutureWith([&] { count++; })};
161   EXPECT_EQ(1, count);
162 }
163
164 TEST(SemiFuture, MakeSemiFutureFromFutureWithValue) {
165   auto f =
166       SemiFuture<std::unique_ptr<int>>{makeFuture(std::make_unique<int>(42))};
167   auto up = std::move(f.value());
168   EXPECT_EQ(42, *up);
169 }
170
171 TEST(SemiFuture, MakeSemiFutureFromReadyFuture) {
172   Promise<int> p;
173   auto f = p.getSemiFuture();
174   EXPECT_FALSE(f.isReady());
175   p.setValue(42);
176   EXPECT_TRUE(f.isReady());
177 }
178
179 TEST(SemiFuture, MakeSemiFutureFromNotReadyFuture) {
180   Promise<int> p;
181   auto f = p.getSemiFuture();
182   EXPECT_THROW(f.value(), eggs_t);
183 }
184
185 TEST(SemiFuture, MakeFutureFromSemiFuture) {
186   folly::EventBase e;
187   Promise<int> p;
188   std::atomic<int> result{0};
189   auto f = p.getSemiFuture();
190   auto future = std::move(f).via(&e).then([&](int value) {
191     result = value;
192     return value;
193   });
194   e.loop();
195   EXPECT_EQ(result, 0);
196   EXPECT_FALSE(future.isReady());
197   p.setValue(42);
198   e.loop();
199   EXPECT_TRUE(future.isReady());
200   ASSERT_EQ(future.value(), 42);
201   ASSERT_EQ(result, 42);
202 }
203
204 TEST(SemiFuture, MakeFutureFromSemiFutureReturnFuture) {
205   folly::EventBase e;
206   Promise<int> p;
207   int result{0};
208   auto f = p.getSemiFuture();
209   auto future = std::move(f).via(&e).then([&](int value) {
210     result = value;
211     return folly::makeFuture(std::move(value));
212   });
213   e.loop();
214   EXPECT_EQ(result, 0);
215   EXPECT_FALSE(future.isReady());
216   p.setValue(42);
217   e.loop();
218   EXPECT_TRUE(future.isReady());
219   ASSERT_EQ(future.value(), 42);
220   ASSERT_EQ(result, 42);
221 }
222
223 TEST(SemiFuture, MakeFutureFromSemiFutureReturnSemiFuture) {
224   folly::EventBase e;
225   Promise<int> p;
226   int result{0};
227   auto f = p.getSemiFuture();
228   auto future = std::move(f)
229                     .via(&e)
230                     .then([&](int value) {
231                       result = value;
232                       return folly::makeSemiFuture(std::move(value));
233                     })
234                     .then([&](int value) {
235                       return folly::makeSemiFuture(std::move(value));
236                     });
237   e.loop();
238   EXPECT_EQ(result, 0);
239   EXPECT_FALSE(future.isReady());
240   p.setValue(42);
241   e.loop();
242   EXPECT_TRUE(future.isReady());
243   ASSERT_EQ(future.value(), 42);
244   ASSERT_EQ(result, 42);
245 }
246
247 TEST(SemiFuture, MakeFutureFromSemiFutureLValue) {
248   folly::EventBase e;
249   Promise<int> p;
250   std::atomic<int> result{0};
251   auto f = p.getSemiFuture();
252   auto future = std::move(f).via(&e).then([&](int value) {
253     result = value;
254     return value;
255   });
256   e.loop();
257   EXPECT_EQ(result, 0);
258   EXPECT_FALSE(future.isReady());
259   p.setValue(42);
260   e.loop();
261   EXPECT_TRUE(future.isReady());
262   ASSERT_EQ(future.value(), 42);
263   ASSERT_EQ(result, 42);
264 }
265
266 TEST(SemiFuture, SimpleGet) {
267   EventBase e2;
268   Promise<int> p;
269   auto sf = p.getSemiFuture();
270   p.setValue(3);
271   auto v = std::move(sf).get();
272   ASSERT_EQ(v, 3);
273 }
274
275 TEST(SemiFuture, SimpleGetTry) {
276   EventBase e2;
277   Promise<int> p;
278   auto sf = p.getSemiFuture();
279   p.setValue(3);
280   auto v = std::move(sf).getTry();
281   ASSERT_EQ(v.value(), 3);
282 }
283
284 TEST(SemiFuture, SimpleTimedGet) {
285   EventBase e2;
286   Promise<folly::Unit> p;
287   auto sf = p.getSemiFuture();
288   EXPECT_THROW(std::move(sf).get(std::chrono::seconds(1)), TimedOut);
289 }
290
291 TEST(SemiFuture, SimpleTimedGetTry) {
292   EventBase e2;
293   Promise<folly::Unit> p;
294   auto sf = p.getSemiFuture();
295   EXPECT_THROW(std::move(sf).getTry(std::chrono::seconds(1)), TimedOut);
296 }
297
298 TEST(SemiFuture, SimpleValue) {
299   EventBase e2;
300   Promise<int> p;
301   auto sf = p.getSemiFuture();
302   p.setValue(3);
303   auto v = std::move(sf).value();
304   ASSERT_EQ(v, 3);
305 }
306
307 TEST(SemiFuture, SimpleValueThrow) {
308   EventBase e2;
309   Promise<folly::Unit> p;
310   auto sf = p.getSemiFuture();
311   EXPECT_THROW(std::move(sf).value(), FutureNotReady);
312 }
313
314 TEST(SemiFuture, SimpleResult) {
315   EventBase e2;
316   Promise<int> p;
317   auto sf = p.getSemiFuture();
318   p.setValue(3);
319   auto v = std::move(sf).result();
320   ASSERT_EQ(v.value(), 3);
321 }
322
323 TEST(SemiFuture, SimpleResultThrow) {
324   EventBase e2;
325   Promise<folly::Unit> p;
326   auto sf = p.getSemiFuture();
327   EXPECT_THROW(std::move(sf).result(), FutureNotReady);
328 }
329
330 TEST(SemiFuture, SimpleDefer) {
331   std::atomic<int> innerResult{0};
332   Promise<folly::Unit> p;
333   auto f = p.getFuture();
334   auto sf = std::move(f).semi().defer([&]() { innerResult = 17; });
335   p.setValue();
336   // Run "F" here inline in the calling thread
337   std::move(sf).get();
338   ASSERT_EQ(innerResult, 17);
339 }
340
341 TEST(SemiFuture, DeferWithGetVia) {
342   std::atomic<int> innerResult{0};
343   EventBase e2;
344   Promise<folly::Unit> p;
345   auto f = p.getFuture();
346   auto sf = std::move(f).semi().defer([&]() { innerResult = 17; });
347   p.setValue();
348   std::move(sf).getVia(&e2);
349   ASSERT_EQ(innerResult, 17);
350 }
351
352 TEST(SemiFuture, DeferWithVia) {
353   std::atomic<int> innerResult{0};
354   EventBase e2;
355   Promise<folly::Unit> p;
356   auto f = p.getFuture();
357   auto sf = std::move(f).semi().defer([&]() { innerResult = 17; });
358   // Run "F" here inline in the calling thread
359   auto tf = std::move(sf).via(&e2);
360   p.setValue();
361   tf.getVia(&e2);
362   ASSERT_EQ(innerResult, 17);
363 }
364
365 TEST(SemiFuture, ChainingDefertoThen) {
366   std::atomic<int> innerResult{0};
367   std::atomic<int> result{0};
368   EventBase e2;
369   Promise<folly::Unit> p;
370   auto f = p.getFuture();
371   auto sf = std::move(f).semi().defer([&]() { innerResult = 17; });
372   // Run "F" here inline in a task running on the eventbase
373   auto tf = std::move(sf).via(&e2).then([&]() { result = 42; });
374   p.setValue();
375   tf.getVia(&e2);
376   ASSERT_EQ(innerResult, 17);
377   ASSERT_EQ(result, 42);
378 }
379
380 TEST(SemiFuture, SimpleDeferWithValue) {
381   std::atomic<int> innerResult{0};
382   Promise<int> p;
383   auto f = p.getFuture();
384   auto sf = std::move(f).semi().defer([&](int a) { innerResult = a; });
385   p.setValue(7);
386   // Run "F" here inline in the calling thread
387   std::move(sf).get();
388   ASSERT_EQ(innerResult, 7);
389 }
390
391 TEST(SemiFuture, ChainingDefertoThenWithValue) {
392   std::atomic<int> innerResult{0};
393   std::atomic<int> result{0};
394   EventBase e2;
395   Promise<int> p;
396   auto f = p.getFuture();
397   auto sf = std::move(f).semi().defer([&](int a) {
398     innerResult = a;
399     return a;
400   });
401   // Run "F" here inline in a task running on the eventbase
402   auto tf = std::move(sf).via(&e2).then([&](int a) { result = a; });
403   p.setValue(7);
404   tf.getVia(&e2);
405   ASSERT_EQ(innerResult, 7);
406   ASSERT_EQ(result, 7);
407 }
408
409 TEST(SemiFuture, MakeSemiFutureFromFutureWithTry) {
410   Promise<int> p;
411   auto f = p.getFuture();
412   auto sf = std::move(f).semi().defer([&](Try<int> t) {
413     if (auto err = t.tryGetExceptionObject<std::logic_error>()) {
414       return Try<std::string>(err->what());
415     }
416     return Try<std::string>(
417         make_exception_wrapper<std::logic_error>("Exception"));
418   });
419   p.setException(make_exception_wrapper<std::logic_error>("Try"));
420   auto tryResult = std::move(sf).get();
421   ASSERT_EQ(tryResult.value(), "Try");
422 }