Add SemiFuture class.
[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/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>
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::unique_ptr<int>(new 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
82 TEST(SemiFuture, hasException) {
83   EXPECT_TRUE(makeSemiFuture<int>(eggs).getTry().hasException());
84   EXPECT_FALSE(makeSemiFuture(42).getTry().hasException());
85 }
86
87 TEST(SemiFuture, hasValue) {
88   EXPECT_TRUE(makeSemiFuture(42).getTry().hasValue());
89   EXPECT_FALSE(makeSemiFuture<int>(eggs).getTry().hasValue());
90 }
91
92 TEST(SemiFuture, makeSemiFuture) {
93   EXPECT_TYPE(makeSemiFuture(42), SemiFuture<int>);
94   EXPECT_EQ(42, makeSemiFuture(42).value());
95
96   EXPECT_TYPE(makeSemiFuture<float>(42), SemiFuture<float>);
97   EXPECT_EQ(42, makeSemiFuture<float>(42).value());
98
99   auto fun = [] { return 42; };
100   EXPECT_TYPE(makeSemiFutureWith(fun), SemiFuture<int>);
101   EXPECT_EQ(42, makeSemiFutureWith(fun).value());
102
103   auto funf = [] { return makeSemiFuture<int>(43); };
104   EXPECT_TYPE(makeSemiFutureWith(funf), SemiFuture<int>);
105   EXPECT_EQ(43, makeSemiFutureWith(funf).value());
106
107   auto failfun = []() -> int { throw eggs; };
108   EXPECT_TYPE(makeSemiFutureWith(failfun), SemiFuture<int>);
109   EXPECT_NO_THROW(makeSemiFutureWith(failfun));
110   EXPECT_THROW(makeSemiFutureWith(failfun).value(), eggs_t);
111
112   auto failfunf = []() -> SemiFuture<int> { throw eggs; };
113   EXPECT_TYPE(makeSemiFutureWith(failfunf), SemiFuture<int>);
114   EXPECT_NO_THROW(makeSemiFutureWith(failfunf));
115   EXPECT_THROW(makeSemiFutureWith(failfunf).value(), eggs_t);
116
117   EXPECT_TYPE(makeSemiFuture(), SemiFuture<Unit>);
118 }
119
120 TEST(SemiFuture, Constructor) {
121   auto f1 = []() -> SemiFuture<int> { return SemiFuture<int>(3); }();
122   EXPECT_EQ(f1.value(), 3);
123   auto f2 = []() -> SemiFuture<Unit> { return SemiFuture<Unit>(); }();
124   EXPECT_NO_THROW(f2.value());
125 }
126
127 TEST(SemiFuture, ImplicitConstructor) {
128   auto f1 = []() -> SemiFuture<int> { return 3; }();
129   EXPECT_EQ(f1.value(), 3);
130 }
131
132 TEST(SemiFuture, InPlaceConstructor) {
133   auto f = SemiFuture<std::pair<int, double>>(in_place, 5, 3.2);
134   EXPECT_EQ(5, f.value().first);
135 }
136
137 TEST(SemiFuture, makeSemiFutureNoThrow) {
138   makeSemiFuture().value();
139 }
140
141 TEST(SemiFuture, ConstructSemiFutureFromEmptyFuture) {
142   auto f = SemiFuture<int>{Future<int>::makeEmpty()};
143   EXPECT_THROW(f.isReady(), NoState);
144 }
145
146 TEST(SemiFuture, ConstructSemiFutureFromFutureDefaultCtor) {
147   SemiFuture<Unit>(Future<Unit>{});
148 }
149
150 TEST(SemiFuture, MakeSemiFutureFromFutureWithUnit) {
151   int count = 0;
152   SemiFuture<Unit> fu = SemiFuture<Unit>{makeFutureWith([&] { count++; })};
153   EXPECT_EQ(1, count);
154 }
155
156 TEST(SemiFuture, MakeSemiFutureFromFutureWithValue) {
157   auto f = SemiFuture<std::unique_ptr<int>>{
158       makeFuture(std::unique_ptr<int>(new int(42)))};
159   auto up = std::move(f.value());
160   EXPECT_EQ(42, *up);
161 }
162
163 TEST(SemiFuture, MakeSemiFutureFromReadyFuture) {
164   Promise<int> p;
165   auto f = SemiFuture<int>{p.getFuture()};
166   EXPECT_FALSE(f.isReady());
167   p.setValue(42);
168   EXPECT_TRUE(f.isReady());
169 }
170
171 TEST(SemiFuture, MakeSemiFutureFromNotReadyFuture) {
172   Promise<int> p;
173   auto f = SemiFuture<int>{p.getFuture()};
174   EXPECT_THROW(f.value(), eggs_t);
175 }
176
177 TEST(SemiFuture, MakeFutureFromSemiFuture) {
178   folly::EventBase e;
179   Promise<int> p;
180   std::atomic<int> result{0};
181   auto f = SemiFuture<int>{p.getFuture()};
182   auto future = std::move(f).via(&e).then([&](int value) {
183     result = value;
184     return value;
185   });
186   e.loop();
187   EXPECT_EQ(result, 0);
188   EXPECT_FALSE(future.isReady());
189   p.setValue(42);
190   e.loop();
191   EXPECT_TRUE(future.isReady());
192   ASSERT_EQ(future.value(), 42);
193   ASSERT_EQ(result, 42);
194 }
195
196 TEST(SemiFuture, MakeFutureFromSemiFutureLValue) {
197   folly::EventBase e;
198   Promise<int> p;
199   std::atomic<int> result{0};
200   auto f = SemiFuture<int>{p.getFuture()};
201   auto future = f.via(&e).then([&](int value) {
202     result = value;
203     return value;
204   });
205   e.loop();
206   EXPECT_EQ(result, 0);
207   EXPECT_FALSE(future.isReady());
208   p.setValue(42);
209   e.loop();
210   EXPECT_TRUE(future.isReady());
211   ASSERT_EQ(future.value(), 42);
212   ASSERT_EQ(result, 42);
213 }