proxygen
WaitTest.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 <queue>
18 
20 #include <folly/futures/Future.h>
24 
25 using namespace folly;
26 using std::vector;
27 using std::chrono::milliseconds;
28 
29 TEST(Wait, waitImmediate) {
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 }
52 
53 TEST(Wait, wait) {
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 }
80 
81 struct MoveFlag {
82  MoveFlag() = default;
83  MoveFlag& operator=(const MoveFlag&) = delete;
84  MoveFlag(const MoveFlag&) = delete;
86  other.moved = true;
87  }
88  bool moved{false};
89 };
90 
91 TEST(Wait, waitReplacesSelf) {
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 }
129 
130 TEST(Wait, waitWithDuration) {
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 }
273 
274 TEST(Wait, multipleWait) {
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 }
286 
287 TEST(Wait, WaitPlusThen) {
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
Future< Unit > sleep(Duration dur, Timekeeper *tk)
Definition: Future.cpp:42
std::chrono::steady_clock::time_point now()
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
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
requires E e noexcept(noexcept(s.error(std::move(e))))
static once_flag flag
Definition: Random.cpp:75
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
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
bool wait(Waiter *waiter, bool shouldSleep, Waiter *&next)
Future< std::tuple< Try< typename remove_cvref_t< Fs >::value_type >... > > collectAll(Fs &&...fs)
Definition: Future-inl.h:1477
auto start
Definition: Try.h:51
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
MoveFlag(MoveFlag &&other) noexcept
Definition: WaitTest.cpp:85
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST(SequencedExecutor, CPUThreadPoolExecutor)
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310