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
19#include <folly/executors/InlineExecutor.h>
20#include <folly/futures/Future.h>
21#include <folly/io/async/EventBase.h>
22#include <folly/portability/GTest.h>
23#include <folly/synchronization/Baton.h>
24
25using namespace folly;
26using std::vector;
27using std::chrono::milliseconds;
28
29TEST(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
53TEST(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
81struct MoveFlag {
82 MoveFlag() = default;
83 MoveFlag& operator=(const MoveFlag&) = delete;
84 MoveFlag(const MoveFlag&) = delete;
85 MoveFlag(MoveFlag&& other) noexcept {
86 other.moved = true;
87 }
88 bool moved{false};
89};
90
91TEST(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
130TEST(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;
176 auto start = std::chrono::steady_clock::now();
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;
189 folly::Baton<> b;
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
208 folly::Baton<> b;
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
233 folly::Baton<> b;
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
260 folly::Baton<> b;
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
274TEST(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
287TEST(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;
304 EXPECT_NO_THROW(
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
315 folly::Baton<> b;
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;
327 EXPECT_NO_THROW(
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;
343 EXPECT_NO_THROW(
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
354 folly::Baton<> b;
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;
366 EXPECT_NO_THROW(
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;
379 EXPECT_NO_THROW(
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);
396 EXPECT_NO_THROW(
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
407 folly::Baton<> b;
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);
421 EXPECT_NO_THROW(
422 std::move(f2).thenValue([&](auto&& v) { continuation = v; }));
423 EXPECT_EQ(continuation, 42);
424 t.join();
425 }
426}
427