1 // Copyright 2021 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/test/test_future.h"
6
7 #include <tuple>
8
9 #include "base/functional/callback.h"
10 #include "base/run_loop.h"
11 #include "base/task/sequenced_task_runner.h"
12 #include "base/task/thread_pool.h"
13 #include "base/test/bind.h"
14 #include "base/test/gtest_util.h"
15 #include "base/test/mock_callback.h"
16 #include "base/test/scoped_run_loop_timeout.h"
17 #include "base/test/task_environment.h"
18 #include "testing/gtest/include/gtest/gtest-spi.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace base::test {
22
23 namespace {
24
25 using AnyType = int;
26 constexpr int kAnyValue = 5;
27 constexpr int kOtherValue = 10;
28
29 struct MoveOnlyValue {
30 public:
31 MoveOnlyValue() = default;
MoveOnlyValuebase::test::__anon0a11accd0111::MoveOnlyValue32 explicit MoveOnlyValue(int data) : data(data) {}
33 MoveOnlyValue(MoveOnlyValue&&) = default;
34 MoveOnlyValue& operator=(MoveOnlyValue&&) = default;
35 ~MoveOnlyValue() = default;
36
37 int data;
38 };
39
40 } // namespace
41
42 class TestFutureTest : public ::testing::Test {
43 public:
44 TestFutureTest() = default;
45 TestFutureTest(const TestFutureTest&) = delete;
46 TestFutureTest& operator=(const TestFutureTest&) = delete;
47 ~TestFutureTest() override = default;
48
49 template <typename Lambda>
RunLater(Lambda lambda,scoped_refptr<SequencedTaskRunner> task_runner=SequencedTaskRunner::GetCurrentDefault ())50 void RunLater(Lambda lambda,
51 scoped_refptr<SequencedTaskRunner> task_runner =
52 SequencedTaskRunner::GetCurrentDefault()) {
53 task_runner->PostTask(FROM_HERE, BindLambdaForTesting(lambda));
54 }
55
RunLater(OnceClosure callable,scoped_refptr<SequencedTaskRunner> task_runner=SequencedTaskRunner::GetCurrentDefault ())56 void RunLater(OnceClosure callable,
57 scoped_refptr<SequencedTaskRunner> task_runner =
58 SequencedTaskRunner::GetCurrentDefault()) {
59 task_runner->PostTask(FROM_HERE, std::move(callable));
60 }
61
RunLater(RepeatingClosure callable,scoped_refptr<SequencedTaskRunner> task_runner=SequencedTaskRunner::GetCurrentDefault ())62 void RunLater(RepeatingClosure callable,
63 scoped_refptr<SequencedTaskRunner> task_runner =
64 SequencedTaskRunner::GetCurrentDefault()) {
65 task_runner->PostTask(FROM_HERE, std::move(callable));
66 }
67
PostDelayedTask(OnceClosure callable,base::TimeDelta delay,scoped_refptr<SequencedTaskRunner> task_runner=SequencedTaskRunner::GetCurrentDefault ())68 void PostDelayedTask(OnceClosure callable,
69 base::TimeDelta delay,
70 scoped_refptr<SequencedTaskRunner> task_runner =
71 SequencedTaskRunner::GetCurrentDefault()) {
72 task_runner->PostDelayedTask(FROM_HERE, std::move(callable), delay);
73 }
74
75 private:
76 TaskEnvironment environment_{TaskEnvironment::TimeSource::MOCK_TIME};
77 };
78
79 using TestFutureDeathTest = TestFutureTest;
80
TEST_F(TestFutureTest,WaitShouldBlockUntilValueArrives)81 TEST_F(TestFutureTest, WaitShouldBlockUntilValueArrives) {
82 const int expected_value = 42;
83 TestFuture<int> future;
84
85 PostDelayedTask(BindOnce(future.GetCallback(), expected_value),
86 Milliseconds(1));
87
88 std::ignore = future.Wait();
89
90 EXPECT_EQ(expected_value, future.Get());
91 }
92
TEST_F(TestFutureTest,WaitShouldBlockUntilValueArrivesOnOtherSequence)93 TEST_F(TestFutureTest, WaitShouldBlockUntilValueArrivesOnOtherSequence) {
94 const int expected_value = 42;
95 TestFuture<int> future;
96
97 PostDelayedTask(BindOnce(future.GetSequenceBoundCallback(), expected_value),
98 Milliseconds(1), ThreadPool::CreateSequencedTaskRunner({}));
99
100 std::ignore = future.Wait();
101
102 EXPECT_EQ(expected_value, future.Get());
103 }
104
TEST_F(TestFutureTest,WaitShouldReturnTrueWhenValueArrives)105 TEST_F(TestFutureTest, WaitShouldReturnTrueWhenValueArrives) {
106 TestFuture<int> future;
107
108 PostDelayedTask(BindOnce(future.GetCallback(), kAnyValue), Milliseconds(1));
109
110 bool success = future.Wait();
111 EXPECT_TRUE(success);
112 }
113
TEST_F(TestFutureTest,WaitShouldReturnTrueWhenValueArrivesOnOtherSequence)114 TEST_F(TestFutureTest, WaitShouldReturnTrueWhenValueArrivesOnOtherSequence) {
115 TestFuture<int> future;
116
117 PostDelayedTask(BindOnce(future.GetSequenceBoundCallback(), kAnyValue),
118 Milliseconds(1), ThreadPool::CreateSequencedTaskRunner({}));
119
120 bool success = future.Wait();
121 EXPECT_TRUE(success);
122 }
123
TEST_F(TestFutureTest,WaitShouldReturnFalseIfTimeoutHappens)124 TEST_F(TestFutureTest, WaitShouldReturnFalseIfTimeoutHappens) {
125 ScopedRunLoopTimeout timeout(FROM_HERE, Milliseconds(1));
126
127 // `ScopedRunLoopTimeout` will automatically fail the test when a timeout
128 // happens, so we use EXPECT_FATAL_FAILURE to handle this failure.
129 // EXPECT_FATAL_FAILURE only works on static objects.
130 static bool success;
131 static TestFuture<AnyType> future;
132
133 EXPECT_NONFATAL_FAILURE({ success = future.Wait(); }, "timed out");
134
135 EXPECT_FALSE(success);
136 }
137
TEST_F(TestFutureTest,GetShouldBlockUntilValueArrives)138 TEST_F(TestFutureTest, GetShouldBlockUntilValueArrives) {
139 const int expected_value = 42;
140 TestFuture<int> future;
141
142 PostDelayedTask(BindOnce(future.GetCallback(), expected_value),
143 Milliseconds(1));
144
145 int actual_value = future.Get();
146
147 EXPECT_EQ(expected_value, actual_value);
148 }
149
TEST_F(TestFutureTest,GetShouldBlockUntilValueArrivesOnOtherSequence)150 TEST_F(TestFutureTest, GetShouldBlockUntilValueArrivesOnOtherSequence) {
151 const int expected_value = 42;
152 TestFuture<int> future;
153
154 PostDelayedTask(BindOnce(future.GetSequenceBoundCallback(), expected_value),
155 Milliseconds(1), ThreadPool::CreateSequencedTaskRunner({}));
156
157 int actual_value = future.Get();
158
159 EXPECT_EQ(expected_value, actual_value);
160 }
161
TEST_F(TestFutureDeathTest,GetShouldCheckIfTimeoutHappens)162 TEST_F(TestFutureDeathTest, GetShouldCheckIfTimeoutHappens) {
163 ScopedRunLoopTimeout timeout(FROM_HERE, Milliseconds(1));
164
165 TestFuture<AnyType> future;
166
167 EXPECT_CHECK_DEATH_WITH(std::ignore = future.Get(), "timed out");
168 }
169
TEST_F(TestFutureTest,TakeShouldWorkWithMoveOnlyValue)170 TEST_F(TestFutureTest, TakeShouldWorkWithMoveOnlyValue) {
171 const int expected_data = 99;
172 TestFuture<MoveOnlyValue> future;
173
174 RunLater(BindOnce(future.GetCallback(), MoveOnlyValue(expected_data)));
175
176 MoveOnlyValue actual_value = future.Take();
177
178 EXPECT_EQ(expected_data, actual_value.data);
179 }
180
TEST_F(TestFutureTest,TakeShouldWorkWithMoveOnlyValueOnOtherSequence)181 TEST_F(TestFutureTest, TakeShouldWorkWithMoveOnlyValueOnOtherSequence) {
182 const int expected_data = 99;
183 TestFuture<MoveOnlyValue> future;
184
185 RunLater(
186 BindOnce(future.GetSequenceBoundCallback(), MoveOnlyValue(expected_data)),
187 ThreadPool::CreateSequencedTaskRunner({}));
188
189 MoveOnlyValue actual_value = future.Take();
190
191 EXPECT_EQ(expected_data, actual_value.data);
192 }
193
TEST_F(TestFutureDeathTest,TakeShouldCheckIfTimeoutHappens)194 TEST_F(TestFutureDeathTest, TakeShouldCheckIfTimeoutHappens) {
195 ScopedRunLoopTimeout timeout(FROM_HERE, Milliseconds(1));
196
197 TestFuture<AnyType> future;
198
199 EXPECT_CHECK_DEATH_WITH(std::ignore = future.Take(), "timed out");
200 }
201
TEST_F(TestFutureTest,IsReadyShouldBeTrueWhenValueIsSet)202 TEST_F(TestFutureTest, IsReadyShouldBeTrueWhenValueIsSet) {
203 TestFuture<AnyType> future;
204
205 EXPECT_FALSE(future.IsReady());
206
207 future.SetValue(kAnyValue);
208
209 EXPECT_TRUE(future.IsReady());
210 }
211
TEST_F(TestFutureTest,ClearShouldRemoveStoredValue)212 TEST_F(TestFutureTest, ClearShouldRemoveStoredValue) {
213 TestFuture<AnyType> future;
214
215 future.SetValue(kAnyValue);
216
217 future.Clear();
218
219 EXPECT_FALSE(future.IsReady());
220 }
221
TEST_F(TestFutureTest,ShouldNotAllowOverwritingStoredValue)222 TEST_F(TestFutureTest, ShouldNotAllowOverwritingStoredValue) {
223 TestFuture<AnyType> future;
224
225 future.SetValue(kAnyValue);
226
227 EXPECT_NONFATAL_FAILURE(future.SetValue(kOtherValue), "Received new value");
228 }
229
TEST_F(TestFutureTest,ShouldAllowReuseIfPreviousValueIsFirstConsumed)230 TEST_F(TestFutureTest, ShouldAllowReuseIfPreviousValueIsFirstConsumed) {
231 TestFuture<std::string> future;
232
233 RunLater([&] { future.SetValue("first value"); });
234 EXPECT_EQ(future.Take(), "first value");
235
236 ASSERT_FALSE(future.IsReady());
237
238 RunLater([&] { future.SetValue("second value"); });
239 EXPECT_EQ(future.Take(), "second value");
240 }
241
TEST_F(TestFutureTest,ShouldAllowReusingCallback)242 TEST_F(TestFutureTest, ShouldAllowReusingCallback) {
243 TestFuture<std::string> future;
244
245 RepeatingCallback<void(std::string)> callback = future.GetRepeatingCallback();
246
247 RunLater(BindOnce(callback, "first value"));
248 EXPECT_EQ(future.Take(), "first value");
249
250 RunLater(BindOnce(callback, "second value"));
251 EXPECT_EQ(future.Take(), "second value");
252
253 RepeatingCallback<void(std::string)> sequence_bound_callback =
254 future.GetSequenceBoundRepeatingCallback();
255 auto other_task_runner = ThreadPool::CreateSequencedTaskRunner({});
256
257 RunLater(BindOnce(sequence_bound_callback, "third value"), other_task_runner);
258 EXPECT_EQ(future.Take(), "third value");
259
260 RunLater(BindOnce(sequence_bound_callback, "fourth value"),
261 other_task_runner);
262 EXPECT_EQ(future.Take(), "fourth value");
263 }
264
TEST_F(TestFutureTest,WaitShouldWorkAfterTake)265 TEST_F(TestFutureTest, WaitShouldWorkAfterTake) {
266 TestFuture<std::string> future;
267
268 future.SetValue("first value");
269 std::ignore = future.Take();
270
271 RunLater([&] { future.SetValue("second value"); });
272
273 EXPECT_TRUE(future.Wait());
274 EXPECT_EQ(future.Get(), "second value");
275 }
276
TEST_F(TestFutureTest,ShouldSignalWhenSetValueIsInvoked)277 TEST_F(TestFutureTest, ShouldSignalWhenSetValueIsInvoked) {
278 const int expected_value = 111;
279 TestFuture<int> future;
280
281 RunLater([&future] { future.SetValue(expected_value); });
282
283 int actual_value = future.Get();
284
285 EXPECT_EQ(expected_value, actual_value);
286 }
287
TEST_F(TestFutureTest,ShouldAllowReferenceArgumentsForCallback)288 TEST_F(TestFutureTest, ShouldAllowReferenceArgumentsForCallback) {
289 const int expected_value = 222;
290 TestFuture<int> future;
291
292 OnceCallback<void(const int&)> callback = future.GetCallback<const int&>();
293 RunLater(BindOnce(std::move(callback), expected_value));
294
295 int actual_value = future.Get();
296
297 EXPECT_EQ(expected_value, actual_value);
298 }
299
TEST_F(TestFutureTest,ShouldAllowReferenceArgumentsForCallbackOnOtherSequence)300 TEST_F(TestFutureTest,
301 ShouldAllowReferenceArgumentsForCallbackOnOtherSequence) {
302 const int expected_value = 222;
303 TestFuture<int> future;
304
305 OnceCallback<void(const int&)> callback =
306 future.GetSequenceBoundCallback<const int&>();
307 RunLater(BindOnce(std::move(callback), expected_value),
308 ThreadPool::CreateSequencedTaskRunner({}));
309
310 int actual_value = future.Get();
311
312 EXPECT_EQ(expected_value, actual_value);
313 }
314
TEST_F(TestFutureTest,ShouldAllowInvokingCallbackAfterFutureIsDestroyed)315 TEST_F(TestFutureTest, ShouldAllowInvokingCallbackAfterFutureIsDestroyed) {
316 OnceCallback<void(int)> callback;
317
318 {
319 TestFuture<int> future;
320 callback = future.GetCallback();
321 }
322
323 std::move(callback).Run(1);
324 }
325
TEST_F(TestFutureTest,ShouldAllowInvokingCallbackOnOtherSequenceAfterFutureIsDestroyed)326 TEST_F(TestFutureTest,
327 ShouldAllowInvokingCallbackOnOtherSequenceAfterFutureIsDestroyed) {
328 OnceCallback<void(int)> callback;
329
330 {
331 TestFuture<int> future;
332 callback = future.GetSequenceBoundCallback();
333 }
334
335 base::RunLoop run_loop;
336 ThreadPool::PostTask(
337 FROM_HERE, BindOnce(std::move(callback), 1).Then(run_loop.QuitClosure()));
338 run_loop.Run();
339 }
340
TEST_F(TestFutureTest,ShouldReturnTupleValue)341 TEST_F(TestFutureTest, ShouldReturnTupleValue) {
342 const int expected_int_value = 5;
343 const std::string expected_string_value = "value";
344
345 TestFuture<int, std::string> future;
346
347 RunLater(BindOnce(future.GetCallback(), expected_int_value,
348 expected_string_value));
349
350 const std::tuple<int, std::string>& actual = future.Get();
351
352 EXPECT_EQ(expected_int_value, std::get<0>(actual));
353 EXPECT_EQ(expected_string_value, std::get<1>(actual));
354 }
355
TEST_F(TestFutureTest,ShouldReturnTupleValueOnOtherSequence)356 TEST_F(TestFutureTest, ShouldReturnTupleValueOnOtherSequence) {
357 const int expected_int_value = 5;
358 const std::string expected_string_value = "value";
359
360 TestFuture<int, std::string> future;
361
362 RunLater(BindOnce(future.GetSequenceBoundCallback(), expected_int_value,
363 expected_string_value),
364 ThreadPool::CreateSequencedTaskRunner({}));
365
366 const std::tuple<int, std::string>& actual = future.Get();
367
368 EXPECT_EQ(expected_int_value, std::get<0>(actual));
369 EXPECT_EQ(expected_string_value, std::get<1>(actual));
370 }
371
TEST_F(TestFutureTest,ShouldAllowAccessingTupleValueUsingGetWithIndex)372 TEST_F(TestFutureTest, ShouldAllowAccessingTupleValueUsingGetWithIndex) {
373 const int expected_int_value = 5;
374 const std::string expected_string_value = "value";
375
376 TestFuture<int, std::string> future;
377
378 RunLater(BindOnce(future.GetCallback(), expected_int_value,
379 expected_string_value));
380
381 std::ignore = future.Get();
382
383 EXPECT_EQ(expected_int_value, future.Get<0>());
384 EXPECT_EQ(expected_string_value, future.Get<1>());
385 }
386
TEST_F(TestFutureTest,ShouldAllowAccessingTupleValueUsingGetWithType)387 TEST_F(TestFutureTest, ShouldAllowAccessingTupleValueUsingGetWithType) {
388 const int expected_int_value = 5;
389 const std::string expected_string_value = "value";
390
391 TestFuture<int, std::string> future;
392
393 RunLater(BindOnce(future.GetCallback(), expected_int_value,
394 expected_string_value));
395
396 std::ignore = future.Get();
397
398 EXPECT_EQ(expected_int_value, future.Get<int>());
399 EXPECT_EQ(expected_string_value, future.Get<std::string>());
400 }
401
TEST_F(TestFutureTest,ShouldAllowReferenceArgumentsForMultiArgumentCallback)402 TEST_F(TestFutureTest, ShouldAllowReferenceArgumentsForMultiArgumentCallback) {
403 const int expected_int_value = 5;
404 const std::string expected_string_value = "value";
405
406 TestFuture<int, std::string> future;
407
408 OnceCallback<void(int, const std::string&)> callback =
409 future.GetCallback<int, const std::string&>();
410 RunLater(
411 BindOnce(std::move(callback), expected_int_value, expected_string_value));
412
413 std::tuple<int, std::string> actual = future.Get();
414
415 EXPECT_EQ(expected_int_value, std::get<0>(actual));
416 EXPECT_EQ(expected_string_value, std::get<1>(actual));
417 }
418
TEST_F(TestFutureTest,ShouldAllowReferenceArgumentsForMultiArgumentCallbackOnOtherSequence)419 TEST_F(TestFutureTest,
420 ShouldAllowReferenceArgumentsForMultiArgumentCallbackOnOtherSequence) {
421 const int expected_int_value = 5;
422 const std::string expected_string_value = "value";
423
424 TestFuture<int, std::string> future;
425
426 OnceCallback<void(int, const std::string&)> callback =
427 future.GetSequenceBoundCallback<int, const std::string&>();
428 RunLater(
429 BindOnce(std::move(callback), expected_int_value, expected_string_value),
430 ThreadPool::CreateSequencedTaskRunner({}));
431
432 std::tuple<int, std::string> actual = future.Get();
433
434 EXPECT_EQ(expected_int_value, std::get<0>(actual));
435 EXPECT_EQ(expected_string_value, std::get<1>(actual));
436 }
437
TEST_F(TestFutureTest,SetValueShouldAllowMultipleArguments)438 TEST_F(TestFutureTest, SetValueShouldAllowMultipleArguments) {
439 const int expected_int_value = 5;
440 const std::string expected_string_value = "value";
441
442 TestFuture<int, std::string> future;
443
444 RunLater([&future, expected_string_value]() {
445 future.SetValue(expected_int_value, expected_string_value);
446 });
447
448 const std::tuple<int, std::string>& actual = future.Get();
449
450 EXPECT_EQ(expected_int_value, std::get<0>(actual));
451 EXPECT_EQ(expected_string_value, std::get<1>(actual));
452 }
453
TEST_F(TestFutureTest,ShouldSupportCvRefType)454 TEST_F(TestFutureTest, ShouldSupportCvRefType) {
455 std::string expected_value = "value";
456 TestFuture<const std::string&> future;
457
458 OnceCallback<void(const std::string&)> callback = future.GetCallback();
459 std::move(callback).Run(expected_value);
460
461 // both get and take should compile, and take should return the decayed value.
462 const std::string& get_result = future.Get();
463 EXPECT_EQ(expected_value, get_result);
464
465 std::string take_result = future.Take();
466 EXPECT_EQ(expected_value, take_result);
467 }
468
TEST_F(TestFutureTest,ShouldSupportMultipleCvRefTypes)469 TEST_F(TestFutureTest, ShouldSupportMultipleCvRefTypes) {
470 const int expected_first_value = 5;
471 std::string expected_second_value = "value";
472 const long expected_third_value = 10;
473 TestFuture<const int, std::string&, const long&> future;
474
475 OnceCallback<void(const int, std::string&, const long&)> callback =
476 future.GetCallback();
477 std::move(callback).Run(expected_first_value, expected_second_value,
478 expected_third_value);
479
480 // both get and take should compile, and return the decayed value.
481 const std::tuple<int, std::string, long>& get_result = future.Get();
482 EXPECT_EQ(expected_first_value, std::get<0>(get_result));
483 EXPECT_EQ(expected_second_value, std::get<1>(get_result));
484 EXPECT_EQ(expected_third_value, std::get<2>(get_result));
485
486 // Get<i> should also work
487 EXPECT_EQ(expected_first_value, future.Get<0>());
488 EXPECT_EQ(expected_second_value, future.Get<1>());
489 EXPECT_EQ(expected_third_value, future.Get<2>());
490
491 std::tuple<int, std::string, long> take_result = future.Take();
492 EXPECT_EQ(expected_first_value, std::get<0>(take_result));
493 EXPECT_EQ(expected_second_value, std::get<1>(take_result));
494 EXPECT_EQ(expected_third_value, std::get<2>(take_result));
495 }
496
TEST_F(TestFutureTest,ShouldAllowReuseIfPreviousTupleValueIsFirstConsumed)497 TEST_F(TestFutureTest, ShouldAllowReuseIfPreviousTupleValueIsFirstConsumed) {
498 TestFuture<std::string, int> future;
499
500 future.SetValue("first value", 1);
501 std::ignore = future.Take();
502
503 ASSERT_FALSE(future.IsReady());
504
505 future.SetValue("second value", 2);
506 EXPECT_EQ(future.Take(), std::make_tuple("second value", 2));
507 }
508
TEST_F(TestFutureTest,ShouldPrintCurrentValueIfItIsOverwritten)509 TEST_F(TestFutureTest, ShouldPrintCurrentValueIfItIsOverwritten) {
510 using UnprintableValue = MoveOnlyValue;
511
512 TestFuture<const char*, int, UnprintableValue> future;
513
514 future.SetValue("first-value", 1111, UnprintableValue());
515
516 EXPECT_NONFATAL_FAILURE(
517 future.SetValue("second-value", 2222, UnprintableValue()),
518 "old value <first-value, 1111, [4-byte object at 0x");
519 }
520
TEST_F(TestFutureTest,ShouldPrintNewValueIfItOverwritesOldValue)521 TEST_F(TestFutureTest, ShouldPrintNewValueIfItOverwritesOldValue) {
522 using UnprintableValue = MoveOnlyValue;
523
524 TestFuture<const char*, int, UnprintableValue> future;
525
526 future.SetValue("first-value", 1111, UnprintableValue());
527
528 EXPECT_NONFATAL_FAILURE(
529 future.SetValue("second-value", 2222, UnprintableValue()),
530 "new value <second-value, 2222, [4-byte object at 0x");
531 }
532
TEST_F(TestFutureTest,InvokeFutureSingleValue)533 TEST_F(TestFutureTest, InvokeFutureSingleValue) {
534 TestFuture<int> future;
535
536 MockCallback<OnceCallback<void(int)>> cb;
537
538 EXPECT_CALL(cb, Run).WillOnce(InvokeFuture(future));
539
540 RunLater(BindOnce(cb.Get(), 7));
541
542 EXPECT_EQ(7, future.Take());
543 }
544
TEST_F(TestFutureTest,InvokeFutureMoveOnlyValue)545 TEST_F(TestFutureTest, InvokeFutureMoveOnlyValue) {
546 TestFuture<MoveOnlyValue> future;
547
548 MockCallback<OnceCallback<void(MoveOnlyValue)>> cb;
549
550 EXPECT_CALL(cb, Run).WillOnce(InvokeFuture(future));
551
552 RunLater(BindOnce(cb.Get(), MoveOnlyValue(10)));
553
554 EXPECT_EQ(10, future.Take().data);
555 }
556
TEST_F(TestFutureTest,InvokeFutureMultipleValues)557 TEST_F(TestFutureTest, InvokeFutureMultipleValues) {
558 TestFuture<int, std::string> future;
559
560 MockCallback<OnceCallback<void(int, std::string)>> cb;
561
562 EXPECT_CALL(cb, Run).WillOnce(InvokeFuture(future));
563
564 RunLater(BindOnce(cb.Get(), 19, "Nineteen"));
565
566 EXPECT_THAT(future.Take(), std::tuple(19, "Nineteen"));
567 }
568
TEST_F(TestFutureTest,InvokeFutureMultipleTimes)569 TEST_F(TestFutureTest, InvokeFutureMultipleTimes) {
570 TestFuture<std::string> future;
571
572 MockCallback<RepeatingCallback<void(std::string)>> cb;
573
574 EXPECT_CALL(cb, Run).WillRepeatedly(InvokeFuture(future));
575
576 cb.Get().Run("first time");
577 EXPECT_EQ("first time", future.Take());
578
579 cb.Get().Run("second time");
580 EXPECT_EQ("second time", future.Take());
581 }
582
TEST_F(TestFutureTest,InvokeFutureDestroyedFuture)583 TEST_F(TestFutureTest, InvokeFutureDestroyedFuture) {
584 std::optional<TestFuture<int>> maybe_future;
585 maybe_future.emplace();
586
587 MockCallback<OnceCallback<void(int)>> cb;
588
589 EXPECT_CALL(cb, Run).WillOnce(InvokeFuture(*maybe_future));
590
591 maybe_future = std::nullopt;
592
593 // If this doesn't crash it worked.
594 cb.Get().Run(42);
595 }
596
TEST_F(TestFutureDeathTest,CallbackShouldDcheckOnOtherSequence)597 TEST_F(TestFutureDeathTest, CallbackShouldDcheckOnOtherSequence) {
598 TestFuture<int> future;
599
600 // Sequence-bound callback may run any time between RunLater() and Wait(),
601 // should succeed.
602 auto other_task_runner = ThreadPool::CreateSequencedTaskRunner({});
603 RunLater(BindOnce(future.GetSequenceBoundCallback(), 1), other_task_runner);
604 EXPECT_TRUE(future.Wait());
605
606 future.Clear();
607
608 // Callback may run any time between RunLater() and Wait(), should DCHECK.
609 EXPECT_DCHECK_DEATH_WITH(
610 {
611 RunLater(BindOnce(future.GetCallback(), 2), other_task_runner);
612 EXPECT_TRUE(future.Wait());
613 },
614 "CalledOnValidSequence");
615 }
616
617 using TestFutureWithoutValuesTest = TestFutureTest;
618
TEST_F(TestFutureWithoutValuesTest,IsReadyShouldBeTrueWhenSetValueIsInvoked)619 TEST_F(TestFutureWithoutValuesTest, IsReadyShouldBeTrueWhenSetValueIsInvoked) {
620 TestFuture<void> future;
621
622 EXPECT_FALSE(future.IsReady());
623
624 future.SetValue();
625
626 EXPECT_TRUE(future.IsReady());
627 }
628
TEST_F(TestFutureWithoutValuesTest,WaitShouldUnblockWhenSetValueIsInvoked)629 TEST_F(TestFutureWithoutValuesTest, WaitShouldUnblockWhenSetValueIsInvoked) {
630 TestFuture<void> future;
631
632 RunLater([&future] { future.SetValue(); });
633
634 ASSERT_FALSE(future.IsReady());
635 std::ignore = future.Wait();
636 EXPECT_TRUE(future.IsReady());
637 }
638
TEST_F(TestFutureWithoutValuesTest,WaitShouldUnblockWhenCallbackIsInvoked)639 TEST_F(TestFutureWithoutValuesTest, WaitShouldUnblockWhenCallbackIsInvoked) {
640 TestFuture<void> future;
641
642 RunLater(future.GetCallback());
643
644 ASSERT_FALSE(future.IsReady());
645 std::ignore = future.Wait();
646 EXPECT_TRUE(future.IsReady());
647 }
648
TEST_F(TestFutureWithoutValuesTest,WaitShouldUnblockWhenCallbackIsInvokedOnOtherSequence)649 TEST_F(TestFutureWithoutValuesTest,
650 WaitShouldUnblockWhenCallbackIsInvokedOnOtherSequence) {
651 TestFuture<void> future;
652
653 RunLater(future.GetSequenceBoundCallback(),
654 ThreadPool::CreateSequencedTaskRunner({}));
655
656 ASSERT_FALSE(future.IsReady());
657 std::ignore = future.Wait();
658 EXPECT_TRUE(future.IsReady());
659 }
660
TEST_F(TestFutureWithoutValuesTest,WaitAndClearShouldAllowFutureReusing)661 TEST_F(TestFutureWithoutValuesTest, WaitAndClearShouldAllowFutureReusing) {
662 TestFuture<void> future;
663
664 RunLater(future.GetCallback());
665 EXPECT_TRUE(future.WaitAndClear());
666
667 ASSERT_FALSE(future.IsReady());
668
669 RunLater(future.GetCallback());
670 EXPECT_TRUE(future.Wait());
671
672 auto other_task_runner = ThreadPool::CreateSequencedTaskRunner({});
673 RunLater(future.GetSequenceBoundCallback(), other_task_runner);
674 EXPECT_TRUE(future.WaitAndClear());
675
676 ASSERT_FALSE(future.IsReady());
677
678 RunLater(future.GetSequenceBoundCallback(), other_task_runner);
679 EXPECT_TRUE(future.Wait());
680 }
681
TEST_F(TestFutureWithoutValuesTest,GetShouldUnblockWhenCallbackIsInvoked)682 TEST_F(TestFutureWithoutValuesTest, GetShouldUnblockWhenCallbackIsInvoked) {
683 TestFuture<void> future;
684
685 RunLater(future.GetCallback());
686
687 ASSERT_FALSE(future.IsReady());
688 future.Get();
689 EXPECT_TRUE(future.IsReady());
690 }
691
TEST_F(TestFutureWithoutValuesTest,GetShouldUnblockWhenCallbackIsInvokedOnOtherSequence)692 TEST_F(TestFutureWithoutValuesTest,
693 GetShouldUnblockWhenCallbackIsInvokedOnOtherSequence) {
694 TestFuture<void> future;
695
696 RunLater(future.GetSequenceBoundCallback(),
697 ThreadPool::CreateSequencedTaskRunner({}));
698
699 ASSERT_FALSE(future.IsReady());
700 future.Get();
701 EXPECT_TRUE(future.IsReady());
702 }
703
TEST(TestFutureWithoutTaskEnvironmentTest,CanCreateTestFutureBeforeTaskEnvironment)704 TEST(TestFutureWithoutTaskEnvironmentTest,
705 CanCreateTestFutureBeforeTaskEnvironment) {
706 TestFuture<AnyType> future;
707
708 // If we come here the test passes, since it means we can create a
709 // `TestFuture` without having a `TaskEnvironment`.
710 }
711
TEST(TestFutureWithoutTaskEnvironmentDeathTest,WaitShouldDcheckWithoutTaskEnvironment)712 TEST(TestFutureWithoutTaskEnvironmentDeathTest,
713 WaitShouldDcheckWithoutTaskEnvironment) {
714 TestFuture<AnyType> future;
715
716 EXPECT_CHECK_DEATH_WITH((void)future.Wait(),
717 "requires a single-threaded context");
718 }
719
TEST_F(TestFutureWithoutValuesTest,InvokeFuture)720 TEST_F(TestFutureWithoutValuesTest, InvokeFuture) {
721 TestFuture<void> future;
722
723 MockCallback<OnceClosure> cb;
724
725 EXPECT_CALL(cb, Run).WillOnce(InvokeFuture(future));
726
727 RunLater(cb.Get());
728
729 EXPECT_TRUE(future.Wait());
730 }
731
732 } // namespace base::test
733