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