1/*
2 * Copyright 2015-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
17#include <folly/futures/Future.h>
18#include <folly/portability/GTest.h>
19
20#include <memory>
21
22using namespace folly;
23using std::string;
24
25using std::unique_ptr;
26typedef FutureException eggs_t;
27static eggs_t eggs("eggs");
28
29TEST(Promise, makeEmpty) {
30 auto p = Promise<int>::makeEmpty();
31 EXPECT_TRUE(p.isFulfilled());
32}
33
34TEST(Promise, special) {
35 EXPECT_FALSE(std::is_copy_constructible<Promise<int>>::value);
36 EXPECT_FALSE(std::is_copy_assignable<Promise<int>>::value);
37 EXPECT_TRUE(std::is_move_constructible<Promise<int>>::value);
38 EXPECT_TRUE(std::is_move_assignable<Promise<int>>::value);
39}
40
41TEST(Promise, getSemiFuture) {
42 Promise<int> p;
43 SemiFuture<int> f = p.getSemiFuture();
44 EXPECT_FALSE(f.isReady());
45}
46
47TEST(Promise, getFuture) {
48 Promise<int> p;
49 Future<int> f = p.getFuture();
50 EXPECT_FALSE(f.isReady());
51}
52
53TEST(Promise, setValueUnit) {
54 Promise<Unit> p;
55 p.setValue();
56}
57
58namespace {
59auto makeValid() {
60 auto valid = Promise<int>();
61 EXPECT_TRUE(valid.valid());
62 return valid;
63}
64auto makeInvalid() {
65 auto invalid = Promise<int>::makeEmpty();
66 EXPECT_FALSE(invalid.valid());
67 return invalid;
68}
69} // namespace
70
71TEST(Promise, ctorPostconditionValid) {
72 // Ctors/factories that promise valid -- postcondition: valid()
73
74#define DOIT(CREATION_EXPR) \
75 do { \
76 auto p1 = (CREATION_EXPR); \
77 EXPECT_TRUE(p1.valid()); \
78 auto p2 = std::move(p1); \
79 EXPECT_FALSE(p1.valid()); \
80 EXPECT_TRUE(p2.valid()); \
81 } while (false)
82
83 DOIT(makeValid());
84 DOIT(Promise<int>());
85 DOIT(Promise<int>{});
86 DOIT(Promise<Unit>());
87 DOIT(Promise<Unit>{});
88
89#undef DOIT
90}
91
92TEST(Promise, ctorPostconditionInvalid) {
93 // Ctors/factories that promise invalid -- postcondition: !valid()
94
95#define DOIT(CREATION_EXPR) \
96 do { \
97 auto p1 = (CREATION_EXPR); \
98 EXPECT_FALSE(p1.valid()); \
99 auto p2 = std::move(p1); \
100 EXPECT_FALSE(p1.valid()); \
101 EXPECT_FALSE(p2.valid()); \
102 } while (false)
103
104 DOIT(makeInvalid());
105 DOIT(Promise<int>::makeEmpty());
106
107#undef DOIT
108}
109
110TEST(Promise, lacksPreconditionValid) {
111 // Ops that don't throw PromiseInvalid if !valid() --
112 // without precondition: valid()
113
114#define DOIT(STMT) \
115 do { \
116 auto p = makeValid(); \
117 { STMT; } \
118 copy(std::move(p)); \
119 EXPECT_NO_THROW(STMT); \
120 } while (false)
121
122 // misc methods that don't require isValid()
123 DOIT(p.valid());
124 DOIT(p.isFulfilled());
125
126 // move-ctor - move-copy to local, copy(), pass-by-move-value
127 DOIT(auto other = std::move(p));
128 DOIT(copy(std::move(p)));
129 DOIT(([](auto) {})(std::move(p)));
130
131 // move-assignment into either {valid | invalid}
132 DOIT({
133 auto other = makeValid();
134 other = std::move(p);
135 });
136 DOIT({
137 auto other = makeInvalid();
138 other = std::move(p);
139 });
140
141#undef DOIT
142}
143
144TEST(Promise, hasPreconditionValid) {
145 // Ops that require validity; precondition: valid();
146 // throw PromiseInvalid if !valid()
147
148#define DOIT(STMT) \
149 do { \
150 auto p = makeValid(); \
151 EXPECT_NO_THROW(STMT); \
152 copy(std::move(p)); \
153 EXPECT_THROW(STMT, PromiseInvalid); \
154 } while (false)
155
156 auto const except = std::logic_error("foo");
157 auto const ewrap = folly::exception_wrapper(except);
158
159 DOIT(p.getSemiFuture());
160 DOIT(p.getFuture());
161 DOIT(p.setException(except));
162 DOIT(p.setException(ewrap));
163 DOIT(p.setInterruptHandler([](auto&) {}));
164 DOIT(p.setValue(42));
165 DOIT(p.setTry(Try<int>(42)));
166 DOIT(p.setTry(Try<int>(ewrap)));
167 DOIT(p.setWith([] { return 42; }));
168
169#undef DOIT
170}
171
172TEST(Promise, hasPostconditionValid) {
173 // Ops that preserve validity -- postcondition: valid()
174
175#define DOIT(STMT) \
176 do { \
177 auto p = makeValid(); \
178 EXPECT_NO_THROW(STMT); \
179 EXPECT_TRUE(p.valid()); \
180 } while (false)
181
182 auto const swallow = [](auto) {};
183
184 DOIT(swallow(p.valid())); // p.valid() itself preserves validity
185 DOIT(swallow(p.isFulfilled()));
186
187#undef DOIT
188}
189
190TEST(Promise, hasPostconditionInvalid) {
191 // Ops that consume *this -- postcondition: !valid()
192
193#define DOIT(CTOR, STMT) \
194 do { \
195 auto p = (CTOR); \
196 EXPECT_NO_THROW(STMT); \
197 EXPECT_FALSE(p.valid()); \
198 } while (false)
199
200 // move-ctor of {valid|invalid}
201 DOIT(makeValid(), { auto other{std::move(p)}; });
202 DOIT(makeInvalid(), { auto other{std::move(p)}; });
203
204 // move-assignment of {valid|invalid} into {valid|invalid}
205 DOIT(makeValid(), {
206 auto other = makeValid();
207 other = std::move(p);
208 });
209 DOIT(makeValid(), {
210 auto other = makeInvalid();
211 other = std::move(p);
212 });
213 DOIT(makeInvalid(), {
214 auto other = makeValid();
215 other = std::move(p);
216 });
217 DOIT(makeInvalid(), {
218 auto other = makeInvalid();
219 other = std::move(p);
220 });
221
222 // pass-by-value of {valid|invalid}
223 DOIT(makeValid(), {
224 auto const byval = [](auto) {};
225 byval(std::move(p));
226 });
227 DOIT(makeInvalid(), {
228 auto const byval = [](auto) {};
229 byval(std::move(p));
230 });
231
232#undef DOIT
233}
234
235TEST(Promise, setValueSemiFuture) {
236 Promise<int> fund;
237 auto ffund = fund.getSemiFuture();
238 fund.setValue(42);
239 EXPECT_EQ(42, ffund.value());
240
241 struct Foo {
242 string name;
243 int value;
244 };
245
246 Promise<Foo> pod;
247 auto fpod = pod.getSemiFuture();
248 Foo f = {"the answer", 42};
249 pod.setValue(f);
250 Foo f2 = fpod.value();
251 EXPECT_EQ(f.name, f2.name);
252 EXPECT_EQ(f.value, f2.value);
253
254 pod = Promise<Foo>();
255 fpod = pod.getSemiFuture();
256 pod.setValue(std::move(f2));
257 Foo f3 = fpod.value();
258 EXPECT_EQ(f.name, f3.name);
259 EXPECT_EQ(f.value, f3.value);
260
261 Promise<unique_ptr<int>> mov;
262 auto fmov = mov.getSemiFuture();
263 mov.setValue(std::make_unique<int>(42));
264 unique_ptr<int> ptr = std::move(fmov.value());
265 EXPECT_EQ(42, *ptr);
266
267 Promise<Unit> v;
268 auto fv = v.getSemiFuture();
269 v.setValue();
270 EXPECT_TRUE(fv.isReady());
271}
272
273TEST(Promise, setValue) {
274 Promise<int> fund;
275 auto ffund = fund.getFuture();
276 fund.setValue(42);
277 EXPECT_EQ(42, ffund.value());
278
279 struct Foo {
280 string name;
281 int value;
282 };
283
284 Promise<Foo> pod;
285 auto fpod = pod.getFuture();
286 Foo f = {"the answer", 42};
287 pod.setValue(f);
288 Foo f2 = fpod.value();
289 EXPECT_EQ(f.name, f2.name);
290 EXPECT_EQ(f.value, f2.value);
291
292 pod = Promise<Foo>();
293 fpod = pod.getFuture();
294 pod.setValue(std::move(f2));
295 Foo f3 = fpod.value();
296 EXPECT_EQ(f.name, f3.name);
297 EXPECT_EQ(f.value, f3.value);
298
299 Promise<unique_ptr<int>> mov;
300 auto fmov = mov.getFuture();
301 mov.setValue(std::make_unique<int>(42));
302 unique_ptr<int> ptr = std::move(fmov.value());
303 EXPECT_EQ(42, *ptr);
304
305 Promise<Unit> v;
306 auto fv = v.getFuture();
307 v.setValue();
308 EXPECT_TRUE(fv.isReady());
309}
310
311TEST(Promise, setException) {
312 {
313 Promise<Unit> p;
314 auto f = p.getFuture();
315 p.setException(eggs);
316 EXPECT_THROW(f.value(), eggs_t);
317 }
318 {
319 Promise<Unit> p;
320 auto f = p.getFuture();
321 p.setException(exception_wrapper(eggs));
322 EXPECT_THROW(f.value(), eggs_t);
323 }
324}
325
326TEST(Promise, setWith) {
327 {
328 Promise<int> p;
329 auto f = p.getFuture();
330 p.setWith([] { return 42; });
331 EXPECT_EQ(42, f.value());
332 }
333 {
334 Promise<int> p;
335 auto f = p.getFuture();
336 p.setWith([]() -> int { throw eggs; });
337 EXPECT_THROW(f.value(), eggs_t);
338 }
339}
340
341TEST(Promise, isFulfilled) {
342 Promise<int> p;
343
344 EXPECT_FALSE(p.isFulfilled());
345 p.setValue(42);
346 EXPECT_TRUE(p.isFulfilled());
347}
348
349TEST(Promise, isFulfilledWithFuture) {
350 Promise<int> p;
351 auto f = p.getFuture(); // so core_ will become null
352
353 EXPECT_FALSE(p.isFulfilled());
354 p.setValue(42); // after here
355 EXPECT_TRUE(p.isFulfilled());
356}
357
358TEST(Promise, brokenOnDelete) {
359 auto p = std::make_unique<Promise<int>>();
360 auto f = p->getFuture();
361
362 EXPECT_FALSE(f.isReady());
363
364 p.reset();
365
366 EXPECT_TRUE(f.isReady());
367
368 auto t = f.getTry();
369
370 EXPECT_TRUE(t.hasException<BrokenPromise>());
371}
372
373TEST(Promise, brokenPromiseHasTypeInfo) {
374 auto pInt = std::make_unique<Promise<int>>();
375 auto fInt = pInt->getFuture();
376
377 auto pFloat = std::make_unique<Promise<float>>();
378 auto fFloat = pFloat->getFuture();
379
380 pInt.reset();
381 pFloat.reset();
382
383 auto whatInt = fInt.getTry().exception().what();
384 auto whatFloat = fFloat.getTry().exception().what();
385
386 EXPECT_NE(whatInt, whatFloat);
387}
388