proxygen
PromiseTest.cpp
Go to the documentation of this file.
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>
19 
20 #include <memory>
21 
22 using namespace folly;
23 using std::string;
24 
25 using std::unique_ptr;
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;
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>{});
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());
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 
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 
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 
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 
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();
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 
345  p.setValue(42);
347 }
348 
349 TEST(Promise, isFulfilledWithFuture) {
350  Promise<int> p;
351  auto f = p.getFuture(); // so core_ will become null
352 
354  p.setValue(42); // after here
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 }
void * ptr
auto f
auto v
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
static Promise< T > makeEmpty() noexcept
Definition: Promise-inl.h:40
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void setWith(F &&func)
Definition: Promise-inl.h:137
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
bool isFulfilled() const noexcept
Definition: Promise-inl.h:143
void setException(exception_wrapper ew)
Definition: Promise-inl.h:111
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
const char * name
Definition: http_parser.c:437
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
Definition: Utility.h:72
FutureException eggs_t
Definition: PromiseTest.cpp:26
static eggs_t eggs("eggs")
Future< T > getFuture()
Definition: Promise-inl.h:97
Definition: Try.h:51
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
std::enable_if< std::is_same< Unit, B >::value, void >::type setValue()
Definition: Promise.h:326
SemiFuture< T > getSemiFuture()
Definition: Promise-inl.h:88
const char * string
Definition: Conv.cpp:212
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
#define DOIT(CREATION_EXPR)
TEST(SequencedExecutor, CPUThreadPoolExecutor)