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 | |
22 | using namespace folly; |
23 | using std::string; |
24 | |
25 | using std::unique_ptr; |
26 | typedef FutureException eggs_t; |
27 | static eggs_t eggs("eggs" ); |
28 | |
29 | TEST(Promise, makeEmpty) { |
30 | auto p = Promise<int>::makeEmpty(); |
31 | EXPECT_TRUE(p.isFulfilled()); |
32 | } |
33 | |
34 | TEST(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 | |
41 | TEST(Promise, getSemiFuture) { |
42 | Promise<int> p; |
43 | SemiFuture<int> f = p.getSemiFuture(); |
44 | EXPECT_FALSE(f.isReady()); |
45 | } |
46 | |
47 | TEST(Promise, getFuture) { |
48 | Promise<int> p; |
49 | Future<int> f = p.getFuture(); |
50 | EXPECT_FALSE(f.isReady()); |
51 | } |
52 | |
53 | TEST(Promise, setValueUnit) { |
54 | Promise<Unit> p; |
55 | p.setValue(); |
56 | } |
57 | |
58 | namespace { |
59 | auto makeValid() { |
60 | auto valid = Promise<int>(); |
61 | EXPECT_TRUE(valid.valid()); |
62 | return valid; |
63 | } |
64 | auto makeInvalid() { |
65 | auto invalid = Promise<int>::makeEmpty(); |
66 | EXPECT_FALSE(invalid.valid()); |
67 | return invalid; |
68 | } |
69 | } // namespace |
70 | |
71 | TEST(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 | |
92 | TEST(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 | |
110 | TEST(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 | |
144 | TEST(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 | |
172 | TEST(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 | |
190 | TEST(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 | |
235 | TEST(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 | |
273 | TEST(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 | |
311 | TEST(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 | |
326 | TEST(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 | |
341 | TEST(Promise, isFulfilled) { |
342 | Promise<int> p; |
343 | |
344 | EXPECT_FALSE(p.isFulfilled()); |
345 | p.setValue(42); |
346 | EXPECT_TRUE(p.isFulfilled()); |
347 | } |
348 | |
349 | TEST(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 | |
358 | TEST(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 | |
373 | TEST(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 | |