1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
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 <memory>
18 
19 #include <folly/futures/Future.h>
20 #include <folly/portability/GTest.h>
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 
TEST(Promise,makeEmpty)29 TEST(Promise, makeEmpty) {
30   auto p = Promise<int>::makeEmpty();
31   EXPECT_TRUE(p.isFulfilled());
32 }
33 
TEST(Promise,special)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 
TEST(Promise,getSemiFuture)41 TEST(Promise, getSemiFuture) {
42   Promise<int> p;
43   SemiFuture<int> f = p.getSemiFuture();
44   EXPECT_FALSE(f.isReady());
45 }
46 
TEST(Promise,getFuture)47 TEST(Promise, getFuture) {
48   Promise<int> p;
49   Future<int> f = p.getFuture();
50   EXPECT_FALSE(f.isReady());
51 }
52 
TEST(Promise,setValueUnit)53 TEST(Promise, setValueUnit) {
54   Promise<Unit> p;
55   p.setValue();
56 }
57 
58 namespace {
makeValid()59 auto makeValid() {
60   auto valid = Promise<int>();
61   EXPECT_TRUE(valid.valid());
62   return valid;
63 }
makeInvalid()64 auto makeInvalid() {
65   auto invalid = Promise<int>::makeEmpty();
66   EXPECT_FALSE(invalid.valid());
67   return invalid;
68 }
69 } // namespace
70 
TEST(Promise,ctorPostconditionValid)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 
TEST(Promise,ctorPostconditionInvalid)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 
TEST(Promise,lacksPreconditionValid)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 
TEST(Promise,hasPreconditionValid)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 
TEST(Promise,hasPostconditionValid)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 
TEST(Promise,hasPostconditionInvalid)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 
TEST(Promise,setValueSemiFuture)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 
TEST(Promise,setValue)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 
TEST(Promise,setException)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 
TEST(Promise,setWith)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 
TEST(Promise,isFulfilled)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 
TEST(Promise,isFulfilledWithFuture)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 
TEST(Promise,brokenOnDelete)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.result();
369 
370   EXPECT_TRUE(t.hasException<BrokenPromise>());
371 }
372 
TEST(Promise,brokenPromiseHasTypeInfo)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.result().exception().what();
384   auto whatFloat = fFloat.result().exception().what();
385 
386   EXPECT_NE(whatInt, whatFloat);
387 }
388