proxygen
WaitTest.cpp File Reference

Go to the source code of this file.

Classes

struct  MoveFlag
 

Functions

 TEST (Wait, waitImmediate)
 
 TEST (Wait, wait)
 
 TEST (Wait, waitReplacesSelf)
 
 TEST (Wait, waitWithDuration)
 
 TEST (Wait, multipleWait)
 
 TEST (Wait, WaitPlusThen)
 

Function Documentation

TEST ( Wait  ,
waitImmediate   
)

Definition at line 29 of file WaitTest.cpp.

References folly::collectAll(), folly::collectAllSemiFuture(), EXPECT_EQ, folly::makeFuture(), and folly::gen::move.

29  {
30  makeFuture().wait();
31  auto done = makeFuture(42).wait().value();
32  EXPECT_EQ(42, done);
33 
34  vector<int> v{1, 2, 3};
35  auto done_v = makeFuture(v).wait().value();
36  EXPECT_EQ(v.size(), done_v.size());
37  EXPECT_EQ(v, done_v);
38 
39  vector<Future<Unit>> v_f;
40  v_f.push_back(makeFuture());
41  v_f.push_back(makeFuture());
42  auto done_v_f = collectAllSemiFuture(v_f).toUnsafeFuture().wait().value();
43  EXPECT_EQ(2, done_v_f.size());
44 
45  vector<Future<bool>> v_fb;
46  v_fb.push_back(makeFuture(true));
47  v_fb.push_back(makeFuture(false));
48  auto fut = collectAll(v_fb);
49  auto done_v_fb = std::move(fut.wait().value());
50  EXPECT_EQ(2, done_v_fb.size());
51 }
std::vector< typename std::enable_if< !std::is_same< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type >, void >::value, invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > >::type > collectAll(InputIterator first, InputIterator last)
Definition: WhenN-inl.h:147
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
SemiFuture< std::tuple< Try< typename remove_cvref_t< Fs >::value_type >... > > collectAllSemiFuture(Fs &&...fs)
Definition: Future-inl.h:1441
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
TEST ( Wait  ,
wait   
)

Definition at line 53 of file WaitTest.cpp.

References EXPECT_EQ, f, flag, folly::Promise< T >::getFuture(), folly::gen::move, folly::Promise< T >::setValue(), and folly::pushmi::detail::t.

53  {
54  Promise<int> p;
55  Future<int> f = p.getFuture();
56  std::atomic<bool> flag{false};
57  std::atomic<int> result{1};
58  std::atomic<std::thread::id> id;
59 
60  std::thread th(
61  [&](Future<int>&& tf) {
62  auto n = std::move(tf).thenTry([&](Try<int>&& t) {
63  id = std::this_thread::get_id();
64  return t.value();
65  });
66  flag = true;
67  result.store(n.wait().value());
68  },
69  std::move(f));
70  while (!flag) {
71  }
72  EXPECT_EQ(result.load(), 1);
73  p.setValue(42);
74  th.join();
75  // validate that the callback ended up executing in this thread, which
76  // is more to ensure that this test actually tests what it should
77  EXPECT_EQ(id, std::this_thread::get_id());
78  EXPECT_EQ(result.load(), 42);
79 }
auto f
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
static once_flag flag
Definition: Random.cpp:75
Future< T > getFuture()
Definition: Promise-inl.h:97
Definition: Try.h:51
std::enable_if< std::is_same< Unit, B >::value, void >::type setValue()
Definition: Promise.h:326
TEST ( Wait  ,
waitReplacesSelf   
)

Definition at line 91 of file WaitTest.cpp.

References EXPECT_FALSE, and folly::makeFuture().

91  {
92  // wait
93  {
94  // lvalue
95  auto f1 = makeFuture(MoveFlag());
96  f1.wait();
97  EXPECT_FALSE(f1.value().moved);
98 
99  // rvalue
100  auto f2 = makeFuture(MoveFlag()).wait();
101  EXPECT_FALSE(f2.value().moved);
102  }
103 
104  // wait(Duration)
105  {
106  // lvalue
107  auto f1 = makeFuture(MoveFlag());
108  f1.wait(milliseconds(1));
109  EXPECT_FALSE(f1.value().moved);
110 
111  // rvalue
112  auto f2 = makeFuture(MoveFlag()).wait(milliseconds(1));
113  EXPECT_FALSE(f2.value().moved);
114  }
115 
116  // waitVia
117  {
118  folly::EventBase eb;
119  // lvalue
120  auto f1 = makeFuture(MoveFlag());
121  f1.waitVia(&eb);
122  EXPECT_FALSE(f1.value().moved);
123 
124  // rvalue
125  auto f2 = makeFuture(MoveFlag()).waitVia(&eb);
126  EXPECT_FALSE(f2.value().moved);
127  }
128 }
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
TEST ( Wait  ,
waitWithDuration   
)

Definition at line 130 of file WaitTest.cpp.

References b, folly::collectAll(), EXPECT_EQ, EXPECT_FALSE, EXPECT_GE, EXPECT_TRUE, f, folly::Promise< T >::getFuture(), folly::Promise< T >::getSemiFuture(), folly::futures::detail::FutureBase< T >::isReady(), folly::makeFuture(), folly::gen::move, now(), folly::Baton< MayBlock, Atom >::post(), folly::Promise< T >::setValue(), start, folly::pushmi::detail::t, folly::Baton< MayBlock, Atom >::wait(), and folly::Future< T >::wait().

130  {
131  {
132  Promise<int> p;
133  Future<int> f = p.getFuture();
134  f.wait(milliseconds(1));
135  EXPECT_FALSE(f.isReady());
136  p.setValue(1);
137  EXPECT_TRUE(f.isReady());
138  }
139  {
140  Promise<int> p;
141  Future<int> f = p.getFuture();
142  p.setValue(1);
143  f.wait(milliseconds(1));
144  EXPECT_TRUE(f.isReady());
145  }
146  {
147  vector<Future<bool>> v_fb;
148  v_fb.push_back(makeFuture(true));
149  v_fb.push_back(makeFuture(false));
150  auto f = collectAll(v_fb);
151  f.wait(milliseconds(1));
152  EXPECT_TRUE(f.isReady());
153  EXPECT_EQ(2, f.value().size());
154  }
155  {
156  vector<Future<bool>> v_fb;
157  Promise<bool> p1;
158  Promise<bool> p2;
159  v_fb.push_back(p1.getFuture());
160  v_fb.push_back(p2.getFuture());
161  auto f = collectAll(v_fb);
162  f.wait(milliseconds(1));
163  EXPECT_FALSE(f.isReady());
164  p1.setValue(true);
165  EXPECT_FALSE(f.isReady());
166  p2.setValue(true);
167  EXPECT_TRUE(f.isReady());
168  }
169  {
170  auto f = makeFuture().wait(milliseconds(1));
171  EXPECT_TRUE(f.isReady());
172  }
173 
174  {
175  Promise<Unit> p;
177  auto f = p.getFuture().wait(milliseconds(100));
178  auto elapsed = std::chrono::steady_clock::now() - start;
179  EXPECT_GE(elapsed, milliseconds(100));
180  EXPECT_FALSE(f.isReady());
181  p.setValue();
182  EXPECT_TRUE(f.isReady());
183  }
184 
185  {
186  // Try to trigger the race where the resultant Future is not yet complete
187  // even if we didn't hit the timeout, and make sure we deal with it properly
188  Promise<Unit> p;
190  auto t = std::thread([&] {
191  b.post();
192  /* sleep override */ std::this_thread::sleep_for(milliseconds(100));
193  p.setValue();
194  });
195  b.wait();
196  auto f = p.getFuture().wait(std::chrono::seconds(3600));
197  EXPECT_TRUE(f.isReady());
198  t.join();
199  }
200 
201  {
202  // `Future::wait(Duration) &` when promise is fulfilled during the wait
203  Promise<int> p;
204 
205  auto f = p.getFuture();
206  EXPECT_FALSE(f.isReady());
207 
209  auto t = std::thread([&] {
210  b.post();
211  /* sleep override */ std::this_thread::sleep_for(milliseconds(100));
212  p.setValue(42);
213  });
214  b.wait();
215 
216  f.wait(std::chrono::seconds(10));
217  EXPECT_TRUE(f.valid());
218  EXPECT_TRUE(f.isReady());
219  EXPECT_EQ(f.value(), 42);
220 
221  t.join();
222  EXPECT_TRUE(f.isReady());
223  EXPECT_EQ(f.value(), 42);
224  }
225 
226  {
227  // `Future::wait(Duration) &&` when promise is fulfilled during the wait
228  Promise<int> p;
229 
230  auto f1 = p.getFuture();
231  EXPECT_FALSE(f1.isReady());
232 
234  auto t = std::thread([&] {
235  b.post();
236  /* sleep override */ std::this_thread::sleep_for(milliseconds(100));
237  p.setValue(42);
238  });
239  b.wait();
240 
241  auto f2 = std::move(f1).wait(std::chrono::seconds(10));
242  EXPECT_FALSE(f1.valid());
243  EXPECT_TRUE(f2.valid());
244  EXPECT_TRUE(f2.isReady());
245  EXPECT_EQ(f2.value(), 42);
246 
247  t.join();
248  EXPECT_TRUE(f2.valid());
249  EXPECT_TRUE(f2.isReady());
250  EXPECT_EQ(f2.value(), 42);
251  }
252 
253  {
254  // `SemiFuture::get(Duration) &&` when promise is fulfilled during the get
255  Promise<int> p;
256 
257  auto f = p.getSemiFuture();
258  EXPECT_FALSE(f.isReady());
259 
261  auto t = std::thread([&] {
262  b.post();
263  /* sleep override */ std::this_thread::sleep_for(milliseconds(100));
264  p.setValue(42);
265  });
266  b.wait();
267 
268  EXPECT_EQ(std::move(f).get(std::chrono::seconds(10)), 42);
269 
270  t.join();
271  }
272 }
std::vector< typename std::enable_if< !std::is_same< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type >, void >::value, invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > >::type > collectAll(InputIterator first, InputIterator last)
Definition: WhenN-inl.h:147
auto f
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::chrono::steady_clock::time_point now()
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
bool valid() const noexcept
Definition: Future.h:162
Future< T > & wait()&
Definition: Future-inl.h:2197
FOLLY_ALWAYS_INLINE void wait(const WaitOptions &opt=wait_options()) noexcept
Definition: Baton.h:170
Future< T > getFuture()
Definition: Promise-inl.h:97
auto start
void post() noexcept
Definition: Baton.h:123
#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
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
TEST ( Wait  ,
multipleWait   
)

Definition at line 274 of file WaitTest.cpp.

References EXPECT_FALSE, EXPECT_TRUE, f, i, and folly::futures::sleep().

274  {
275  auto f = futures::sleep(milliseconds(100));
276  for (size_t i = 0; i < 5; ++i) {
277  EXPECT_FALSE(f.isReady());
278  f.wait(milliseconds(3));
279  }
280  EXPECT_FALSE(f.isReady());
281  f.wait();
282  EXPECT_TRUE(f.isReady());
283  f.wait();
284  EXPECT_TRUE(f.isReady());
285 }
auto f
Future< Unit > sleep(Duration dur, Timekeeper *tk)
Definition: Future.cpp:42
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( Wait  ,
WaitPlusThen   
)

Definition at line 287 of file WaitTest.cpp.

References b, EXPECT_EQ, EXPECT_FALSE, EXPECT_NO_THROW, EXPECT_TRUE, f, folly::Promise< T >::getFuture(), folly::Promise< T >::getSemiFuture(), folly::gen::move, folly::Baton< MayBlock, Atom >::post(), folly::Promise< T >::setValue(), folly::pushmi::detail::t, v, and folly::Baton< MayBlock, Atom >::wait().

287  {
288  // Validate expected behavior of `f.wait(...).then([](auto&){...})`.
289  // There are 10 sub-cases:
290  // - Future fulfilled {prior to, during} call to wait().
291  // - Future fulfilled {prior to, during, after} call to wait(dur).
292  // - then repeat those 5 cases for SemiFuture
293 
294  {
295  // Sub-case: Future fulfilled before `wait()` is called.
296  // Expect call to `.then()` to succeed & continuation to run immediately.
297  Promise<int> p;
298  auto f = p.getFuture();
299  p.setValue(42);
300  EXPECT_TRUE(f.isReady());
301  EXPECT_EQ(f.value(), 42);
302  f.wait();
303  auto continuation = 0;
305  std::move(f).thenValue([&](auto&& v) { continuation = v; }));
306  EXPECT_EQ(continuation, 42);
307  }
308 
309  {
310  // Sub-case: Future fulfilled after `wait()` actually has to wait.
311  // Expect call to `.then()` to fail (throw std::logic_error).
312  Promise<int> p;
313  auto f = p.getFuture();
314 
316  auto t = std::thread([&] {
317  b.post();
318  /* sleep override */ std::this_thread::sleep_for(milliseconds(100));
319  p.setValue(42);
320  });
321  b.wait();
322 
323  EXPECT_FALSE(f.isReady()); // deterministically passes in practice
324  f.wait();
325  EXPECT_TRUE(f.isReady());
326  auto continuation = 0;
328  std::move(f).thenValue([&](auto&& v) { continuation = v; }));
329  EXPECT_EQ(continuation, 42);
330  t.join();
331  }
332 
333  {
334  // Sub-case: Future fulfilled before `wait(dur)` is called.
335  // Expect call to `.then()` to succeed & continuation to run immediately.
336  Promise<int> p;
337  auto f = p.getFuture();
338  p.setValue(42);
339  EXPECT_TRUE(f.isReady());
340  EXPECT_EQ(f.value(), 42);
341  f.wait(std::chrono::seconds(10));
342  auto continuation = 0;
344  std::move(f).thenValue([&](auto&& v) { continuation = v; }));
345  EXPECT_EQ(continuation, 42);
346  }
347 
348  {
349  // Sub-case: Future fulfilled after `wait(dur)` actually starts waiting.
350  // Expect call to `.then()` to succeed & continuation to when result ready.
351  Promise<int> p;
352  auto f = p.getFuture();
353 
355  auto t = std::thread([&] {
356  b.post();
357  /* sleep override */ std::this_thread::sleep_for(milliseconds(100));
358  p.setValue(42);
359  });
360  b.wait();
361 
362  EXPECT_FALSE(f.isReady()); // deterministically passes in practice
363  f.wait(std::chrono::seconds(10));
364  EXPECT_TRUE(f.isReady()); // deterministically passes in practice
365  auto continuation = 0;
367  std::move(f).thenValue([&](auto&& v) { continuation = v; }));
368  EXPECT_EQ(continuation, 42);
369  t.join();
370  }
371 
372  {
373  // Sub-case: Future not fulfilled - `wait(dur)` times out.
374  // Expect call to `.then()` to succeed; continuation to not run.
375  Promise<int> p;
376  auto f = p.getFuture();
377  f.wait(milliseconds(1));
378  auto continuation = 0;
380  std::move(f).thenValue([&](auto&& v) { continuation = v; }));
381  EXPECT_EQ(continuation, 0);
382  }
383 
384  {
385  // Sub-case: SemiFuture fulfilled before `wait()` is called.
386  // Expect call to `.then()` to succeed & continuation to run immediately.
387  Promise<int> p;
388  auto f = p.getSemiFuture();
389  p.setValue(42);
390  EXPECT_TRUE(f.isReady());
391  EXPECT_EQ(f.value(), 42);
392  f.wait();
393  auto continuation = 0;
394  InlineExecutor e;
395  auto f2 = std::move(f).via(&e);
397  std::move(f2).thenValue([&](auto&& v) { continuation = v; }));
398  EXPECT_EQ(continuation, 42);
399  }
400 
401  {
402  // Sub-case: SemiFuture fulfilled after `wait()` actually has to wait.
403  // Expect call to `.then()` to fail (throw std::logic_error).
404  Promise<int> p;
405  auto f = p.getSemiFuture();
406 
408  auto t = std::thread([&] {
409  b.post();
410  /* sleep override */ std::this_thread::sleep_for(milliseconds(100));
411  p.setValue(42);
412  });
413  b.wait();
414 
415  EXPECT_FALSE(f.isReady()); // deterministically passes in practice
416  f.wait();
417  EXPECT_TRUE(f.isReady());
418  auto continuation = 0;
419  InlineExecutor e;
420  auto f2 = std::move(f).via(&e);
422  std::move(f2).thenValue([&](auto&& v) { continuation = v; }));
423  EXPECT_EQ(continuation, 42);
424  t.join();
425  }
426 }
auto f
auto v
#define EXPECT_NO_THROW(statement)
Definition: gtest.h:1845
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
FOLLY_ALWAYS_INLINE void wait(const WaitOptions &opt=wait_options()) noexcept
Definition: Baton.h:170
Future< T > getFuture()
Definition: Promise-inl.h:97
void post() noexcept
Definition: Baton.h:123
#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
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862