2 * Copyright 2017 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.
17 #include <folly/Baton.h>
18 #include <folly/Executor.h>
19 #include <folly/Memory.h>
20 #include <folly/Unit.h>
21 #include <folly/dynamic.h>
22 #include <folly/futures/Future.h>
23 #include <folly/io/async/EventBase.h>
24 #include <folly/portability/GTest.h>
32 #include <type_traits>
34 using namespace folly;
36 #define EXPECT_TYPE(x, T) EXPECT_TRUE((std::is_same<decltype(x), T>::value))
38 typedef FutureException eggs_t;
39 static eggs_t eggs("eggs");
43 TEST(SemiFuture, makeEmpty) {
44 auto f = SemiFuture<int>::makeEmpty();
45 EXPECT_THROW(f.isReady(), NoState);
48 TEST(SemiFuture, futureDefaultCtor) {
52 TEST(SemiFuture, makeSemiFutureWithUnit) {
54 SemiFuture<Unit> fu = makeSemiFutureWith([&] { count++; });
59 SemiFuture<int> onErrorHelperEggs(const eggs_t&) {
60 return makeSemiFuture(10);
62 SemiFuture<int> onErrorHelperGeneric(const std::exception&) {
63 return makeSemiFuture(20);
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);
74 TEST(SemiFuture, value) {
75 auto f = makeSemiFuture(std::make_unique<int>(42));
76 auto up = std::move(f.value());
79 EXPECT_THROW(makeSemiFuture<int>(eggs).value(), eggs_t);
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&&);
87 TEST(SemiFuture, hasException) {
88 EXPECT_TRUE(makeSemiFuture<int>(eggs).getTry().hasException());
89 EXPECT_FALSE(makeSemiFuture(42).getTry().hasException());
92 TEST(SemiFuture, hasValue) {
93 EXPECT_TRUE(makeSemiFuture(42).getTry().hasValue());
94 EXPECT_FALSE(makeSemiFuture<int>(eggs).getTry().hasValue());
97 TEST(SemiFuture, makeSemiFuture) {
98 EXPECT_TYPE(makeSemiFuture(42), SemiFuture<int>);
99 EXPECT_EQ(42, makeSemiFuture(42).value());
101 EXPECT_TYPE(makeSemiFuture<float>(42), SemiFuture<float>);
102 EXPECT_EQ(42, makeSemiFuture<float>(42).value());
104 auto fun = [] { return 42; };
105 EXPECT_TYPE(makeSemiFutureWith(fun), SemiFuture<int>);
106 EXPECT_EQ(42, makeSemiFutureWith(fun).value());
108 auto funf = [] { return makeSemiFuture<int>(43); };
109 EXPECT_TYPE(makeSemiFutureWith(funf), SemiFuture<int>);
110 EXPECT_EQ(43, makeSemiFutureWith(funf).value());
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);
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);
122 EXPECT_TYPE(makeSemiFuture(), SemiFuture<Unit>);
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());
132 TEST(SemiFuture, ImplicitConstructor) {
133 auto f1 = []() -> SemiFuture<int> { return 3; }();
134 EXPECT_EQ(f1.value(), 3);
137 TEST(SemiFuture, InPlaceConstructor) {
138 auto f = SemiFuture<std::pair<int, double>>(in_place, 5, 3.2);
139 EXPECT_EQ(5, f.value().first);
142 TEST(SemiFuture, makeSemiFutureNoThrow) {
143 makeSemiFuture().value();
146 TEST(SemiFuture, ViaThrowOnNull) {
147 EXPECT_THROW(makeSemiFuture().via(nullptr), NoExecutor);
150 TEST(SemiFuture, ConstructSemiFutureFromEmptyFuture) {
151 auto f = SemiFuture<int>{Future<int>::makeEmpty()};
152 EXPECT_THROW(f.isReady(), NoState);
155 TEST(SemiFuture, ConstructSemiFutureFromFutureDefaultCtor) {
156 SemiFuture<Unit>(Future<Unit>{});
159 TEST(SemiFuture, MakeSemiFutureFromFutureWithUnit) {
161 SemiFuture<Unit> fu = SemiFuture<Unit>{makeFutureWith([&] { count++; })};
165 TEST(SemiFuture, MakeSemiFutureFromFutureWithValue) {
167 SemiFuture<std::unique_ptr<int>>{makeFuture(std::make_unique<int>(42))};
168 auto up = std::move(f.value());
172 TEST(SemiFuture, MakeSemiFutureFromReadyFuture) {
174 auto f = SemiFuture<int>{p.getFuture()};
175 EXPECT_FALSE(f.isReady());
177 EXPECT_TRUE(f.isReady());
180 TEST(SemiFuture, MakeSemiFutureFromNotReadyFuture) {
182 auto f = SemiFuture<int>{p.getFuture()};
183 EXPECT_THROW(f.value(), eggs_t);
186 TEST(SemiFuture, MakeFutureFromSemiFuture) {
189 std::atomic<int> result{0};
190 auto f = SemiFuture<int>{p.getFuture()};
191 auto future = std::move(f).via(&e).then([&](int value) {
196 EXPECT_EQ(result, 0);
197 EXPECT_FALSE(future.isReady());
200 EXPECT_TRUE(future.isReady());
201 ASSERT_EQ(future.value(), 42);
202 ASSERT_EQ(result, 42);
205 TEST(SemiFuture, MakeFutureFromSemiFutureLValue) {
208 std::atomic<int> result{0};
209 auto f = SemiFuture<int>{p.getFuture()};
210 auto future = std::move(f).via(&e).then([&](int value) {
215 EXPECT_EQ(result, 0);
216 EXPECT_FALSE(future.isReady());
219 EXPECT_TRUE(future.isReady());
220 ASSERT_EQ(future.value(), 42);
221 ASSERT_EQ(result, 42);
224 TEST(SemiFuture, SimpleDefer) {
225 std::atomic<int> innerResult{0};
226 Promise<folly::Unit> p;
227 auto f = p.getFuture();
228 auto sf = std::move(f).semi().defer([&]() { innerResult = 17; });
230 // Run "F" here inline in the calling thread
232 ASSERT_EQ(innerResult, 17);
235 TEST(SemiFuture, DeferWithVia) {
236 std::atomic<int> innerResult{0};
238 Promise<folly::Unit> p;
239 auto f = p.getFuture();
240 auto sf = std::move(f).semi().defer([&]() { innerResult = 17; });
241 // Run "F" here inline in the calling thread
242 auto tf = std::move(sf).via(&e2);
245 ASSERT_EQ(innerResult, 17);
248 TEST(SemiFuture, ChainingDefertoThen) {
249 std::atomic<int> innerResult{0};
250 std::atomic<int> result{0};
252 Promise<folly::Unit> p;
253 auto f = p.getFuture();
254 auto sf = std::move(f).semi().defer([&]() { innerResult = 17; });
255 // Run "F" here inline in a task running on the eventbase
256 auto tf = std::move(sf).via(&e2).then([&]() { result = 42; });
259 ASSERT_EQ(innerResult, 17);
260 ASSERT_EQ(result, 42);
263 TEST(SemiFuture, SimpleDeferWithValue) {
264 std::atomic<int> innerResult{0};
266 auto f = p.getFuture();
267 auto sf = std::move(f).semi().defer([&](int a) { innerResult = a; });
269 // Run "F" here inline in the calling thread
271 ASSERT_EQ(innerResult, 7);
274 TEST(SemiFuture, ChainingDefertoThenWithValue) {
275 std::atomic<int> innerResult{0};
276 std::atomic<int> result{0};
279 auto f = p.getFuture();
280 auto sf = std::move(f).semi().defer([&](int a) {
284 // Run "F" here inline in a task running on the eventbase
285 auto tf = std::move(sf).via(&e2).then([&](int a) { result = a; });
288 ASSERT_EQ(innerResult, 7);
289 ASSERT_EQ(result, 7);
292 TEST(SemiFuture, MakeSemiFutureFromFutureWithTry) {
294 auto f = p.getFuture();
295 auto sf = std::move(f).semi().defer([&](Try<int> t) {
296 if (auto err = t.tryGetExceptionObject<std::logic_error>()) {
297 return Try<std::string>(err->what());
299 return Try<std::string>(
300 make_exception_wrapper<std::logic_error>("Exception"));
302 p.setException(make_exception_wrapper<std::logic_error>("Try"));
303 auto tryResult = std::move(sf).get();
304 ASSERT_EQ(tryResult.value(), "Try");