2 * Copyright 2017-present Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
31 #include <type_traits>
33 using namespace folly;
35 #define EXPECT_TYPE(x, T) EXPECT_TRUE((std::is_same<decltype(x), T>::value))
37 typedef FutureException eggs_t;
38 static eggs_t eggs("eggs");
42 TEST(SemiFuture, makeEmpty) {
43 auto f = SemiFuture<int>::makeEmpty();
44 EXPECT_THROW(f.isReady(), NoState);
47 TEST(SemiFuture, futureDefaultCtor) {
51 TEST(SemiFuture, makeSemiFutureWithUnit) {
53 SemiFuture<Unit> fu = makeSemiFutureWith([&] { count++; });
58 SemiFuture<int> onErrorHelperEggs(const eggs_t&) {
59 return makeSemiFuture(10);
61 SemiFuture<int> onErrorHelperGeneric(const std::exception&) {
62 return makeSemiFuture(20);
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);
73 TEST(SemiFuture, value) {
74 auto f = makeSemiFuture(std::make_unique<int>(42));
75 auto up = std::move(f.value());
78 EXPECT_THROW(makeSemiFuture<int>(eggs).value(), eggs_t);
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&&);
86 TEST(SemiFuture, hasException) {
87 EXPECT_TRUE(makeSemiFuture<int>(eggs).getTry().hasException());
88 EXPECT_FALSE(makeSemiFuture(42).getTry().hasException());
91 TEST(SemiFuture, hasValue) {
92 EXPECT_TRUE(makeSemiFuture(42).getTry().hasValue());
93 EXPECT_FALSE(makeSemiFuture<int>(eggs).getTry().hasValue());
96 TEST(SemiFuture, makeSemiFuture) {
97 EXPECT_TYPE(makeSemiFuture(42), SemiFuture<int>);
98 EXPECT_EQ(42, makeSemiFuture(42).value());
100 EXPECT_TYPE(makeSemiFuture<float>(42), SemiFuture<float>);
101 EXPECT_EQ(42, makeSemiFuture<float>(42).value());
103 auto fun = [] { return 42; };
104 EXPECT_TYPE(makeSemiFutureWith(fun), SemiFuture<int>);
105 EXPECT_EQ(42, makeSemiFutureWith(fun).value());
107 auto funf = [] { return makeSemiFuture<int>(43); };
108 EXPECT_TYPE(makeSemiFutureWith(funf), SemiFuture<int>);
109 EXPECT_EQ(43, makeSemiFutureWith(funf).value());
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);
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);
121 EXPECT_TYPE(makeSemiFuture(), SemiFuture<Unit>);
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());
131 TEST(SemiFuture, ImplicitConstructor) {
132 auto f1 = []() -> SemiFuture<int> { return 3; }();
133 EXPECT_EQ(f1.value(), 3);
136 TEST(SemiFuture, InPlaceConstructor) {
137 auto f = SemiFuture<std::pair<int, double>>(in_place, 5, 3.2);
138 EXPECT_EQ(5, f.value().first);
141 TEST(SemiFuture, makeSemiFutureNoThrow) {
142 makeSemiFuture().value();
145 TEST(SemiFuture, ViaThrowOnNull) {
146 EXPECT_THROW(makeSemiFuture().via(nullptr), NoExecutor);
149 TEST(SemiFuture, ConstructSemiFutureFromEmptyFuture) {
150 auto f = SemiFuture<int>{Future<int>::makeEmpty()};
151 EXPECT_THROW(f.isReady(), NoState);
154 TEST(SemiFuture, ConstructSemiFutureFromFutureDefaultCtor) {
155 SemiFuture<Unit>(Future<Unit>{});
158 TEST(SemiFuture, MakeSemiFutureFromFutureWithUnit) {
160 SemiFuture<Unit> fu = SemiFuture<Unit>{makeFutureWith([&] { count++; })};
164 TEST(SemiFuture, MakeSemiFutureFromFutureWithValue) {
166 SemiFuture<std::unique_ptr<int>>{makeFuture(std::make_unique<int>(42))};
167 auto up = std::move(f.value());
171 TEST(SemiFuture, MakeSemiFutureFromReadyFuture) {
173 auto f = p.getSemiFuture();
174 EXPECT_FALSE(f.isReady());
176 EXPECT_TRUE(f.isReady());
179 TEST(SemiFuture, MakeSemiFutureFromNotReadyFuture) {
181 auto f = p.getSemiFuture();
182 EXPECT_THROW(f.value(), eggs_t);
185 TEST(SemiFuture, MakeFutureFromSemiFuture) {
188 std::atomic<int> result{0};
189 auto f = p.getSemiFuture();
190 auto future = std::move(f).via(&e).then([&](int value) {
195 EXPECT_EQ(result, 0);
196 EXPECT_FALSE(future.isReady());
199 EXPECT_TRUE(future.isReady());
200 ASSERT_EQ(future.value(), 42);
201 ASSERT_EQ(result, 42);
204 TEST(SemiFuture, MakeFutureFromSemiFutureReturnFuture) {
208 auto f = p.getSemiFuture();
209 auto future = std::move(f).via(&e).then([&](int value) {
211 return folly::makeFuture(std::move(value));
214 EXPECT_EQ(result, 0);
215 EXPECT_FALSE(future.isReady());
218 EXPECT_TRUE(future.isReady());
219 ASSERT_EQ(future.value(), 42);
220 ASSERT_EQ(result, 42);
223 TEST(SemiFuture, MakeFutureFromSemiFutureReturnSemiFuture) {
227 auto f = p.getSemiFuture();
228 auto future = std::move(f)
230 .then([&](int value) {
232 return folly::makeSemiFuture(std::move(value));
234 .then([&](int value) {
235 return folly::makeSemiFuture(std::move(value));
238 EXPECT_EQ(result, 0);
239 EXPECT_FALSE(future.isReady());
242 EXPECT_TRUE(future.isReady());
243 ASSERT_EQ(future.value(), 42);
244 ASSERT_EQ(result, 42);
247 TEST(SemiFuture, MakeFutureFromSemiFutureLValue) {
250 std::atomic<int> result{0};
251 auto f = p.getSemiFuture();
252 auto future = std::move(f).via(&e).then([&](int value) {
257 EXPECT_EQ(result, 0);
258 EXPECT_FALSE(future.isReady());
261 EXPECT_TRUE(future.isReady());
262 ASSERT_EQ(future.value(), 42);
263 ASSERT_EQ(result, 42);
266 TEST(SemiFuture, SimpleGet) {
269 auto sf = p.getSemiFuture();
271 auto v = std::move(sf).get();
275 TEST(SemiFuture, SimpleGetTry) {
278 auto sf = p.getSemiFuture();
280 auto v = std::move(sf).getTry();
281 ASSERT_EQ(v.value(), 3);
284 TEST(SemiFuture, SimpleTimedGet) {
286 Promise<folly::Unit> p;
287 auto sf = p.getSemiFuture();
288 EXPECT_THROW(std::move(sf).get(std::chrono::seconds(1)), TimedOut);
291 TEST(SemiFuture, SimpleTimedGetTry) {
293 Promise<folly::Unit> p;
294 auto sf = p.getSemiFuture();
295 EXPECT_THROW(std::move(sf).getTry(std::chrono::seconds(1)), TimedOut);
298 TEST(SemiFuture, SimpleValue) {
301 auto sf = p.getSemiFuture();
303 auto v = std::move(sf).value();
307 TEST(SemiFuture, SimpleValueThrow) {
309 Promise<folly::Unit> p;
310 auto sf = p.getSemiFuture();
311 EXPECT_THROW(std::move(sf).value(), FutureNotReady);
314 TEST(SemiFuture, SimpleResult) {
317 auto sf = p.getSemiFuture();
319 auto v = std::move(sf).result();
320 ASSERT_EQ(v.value(), 3);
323 TEST(SemiFuture, SimpleResultThrow) {
325 Promise<folly::Unit> p;
326 auto sf = p.getSemiFuture();
327 EXPECT_THROW(std::move(sf).result(), FutureNotReady);
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; });
336 // Run "F" here inline in the calling thread
338 ASSERT_EQ(innerResult, 17);
341 TEST(SemiFuture, DeferWithGetVia) {
342 std::atomic<int> innerResult{0};
344 Promise<folly::Unit> p;
345 auto f = p.getFuture();
346 auto sf = std::move(f).semi().defer([&]() { innerResult = 17; });
348 std::move(sf).getVia(&e2);
349 ASSERT_EQ(innerResult, 17);
352 TEST(SemiFuture, DeferWithVia) {
353 std::atomic<int> innerResult{0};
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);
362 ASSERT_EQ(innerResult, 17);
365 TEST(SemiFuture, ChainingDefertoThen) {
366 std::atomic<int> innerResult{0};
367 std::atomic<int> result{0};
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; });
376 ASSERT_EQ(innerResult, 17);
377 ASSERT_EQ(result, 42);
380 TEST(SemiFuture, SimpleDeferWithValue) {
381 std::atomic<int> innerResult{0};
383 auto f = p.getFuture();
384 auto sf = std::move(f).semi().defer([&](int a) { innerResult = a; });
386 // Run "F" here inline in the calling thread
388 ASSERT_EQ(innerResult, 7);
391 TEST(SemiFuture, ChainingDefertoThenWithValue) {
392 std::atomic<int> innerResult{0};
393 std::atomic<int> result{0};
396 auto f = p.getFuture();
397 auto sf = std::move(f).semi().defer([&](int a) {
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; });
405 ASSERT_EQ(innerResult, 7);
406 ASSERT_EQ(result, 7);
409 TEST(SemiFuture, MakeSemiFutureFromFutureWithTry) {
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());
416 return Try<std::string>(
417 make_exception_wrapper<std::logic_error>("Exception"));
419 p.setException(make_exception_wrapper<std::logic_error>("Try"));
420 auto tryResult = std::move(sf).get();
421 ASSERT_EQ(tryResult.value(), "Try");