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/task/single_thread_task_runner.h"
11 #include "base/test/bind.h"
12 #include "base/test/gtest_util.h"
13 #include "base/test/scoped_run_loop_timeout.h"
14 #include "base/test/task_environment.h"
15 #include "testing/gtest/include/gtest/gtest-spi.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace base::test {
19
20 namespace {
21
22 using AnyType = int;
23 constexpr int kAnyValue = 5;
24 constexpr int kOtherValue = 10;
25
26 struct MoveOnlyValue {
27 public:
28 MoveOnlyValue() = default;
MoveOnlyValuebase::test::__anone81dcee50111::MoveOnlyValue29 explicit MoveOnlyValue(int data) : data(data) {}
30 MoveOnlyValue(MoveOnlyValue&&) = default;
31 MoveOnlyValue& operator=(MoveOnlyValue&&) = default;
32 ~MoveOnlyValue() = default;
33
34 int data;
35 };
36
37 } // namespace
38
39 class TestFutureTest : public ::testing::Test {
40 public:
41 TestFutureTest() = default;
42 TestFutureTest(const TestFutureTest&) = delete;
43 TestFutureTest& operator=(const TestFutureTest&) = delete;
44 ~TestFutureTest() override = default;
45
46 template <typename Lambda>
RunLater(Lambda lambda)47 void RunLater(Lambda lambda) {
48 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
49 FROM_HERE, BindLambdaForTesting(lambda));
50 }
51
RunLater(OnceClosure callable)52 void RunLater(OnceClosure callable) {
53 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE,
54 std::move(callable));
55 }
56
RunLater(RepeatingClosure callable)57 void RunLater(RepeatingClosure callable) {
58 SingleThreadTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE,
59 std::move(callable));
60 }
61
PostDelayedTask(OnceClosure callable,base::TimeDelta delay)62 void PostDelayedTask(OnceClosure callable, base::TimeDelta delay) {
63 SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
64 FROM_HERE, std::move(callable), delay);
65 }
66
67 private:
68 SingleThreadTaskEnvironment environment_{
69 TaskEnvironment::TimeSource::MOCK_TIME};
70 };
71
TEST_F(TestFutureTest,WaitShouldBlockUntilValueArrives)72 TEST_F(TestFutureTest, WaitShouldBlockUntilValueArrives) {
73 const int expected_value = 42;
74 TestFuture<int> future;
75
76 PostDelayedTask(BindOnce(future.GetCallback(), expected_value),
77 Milliseconds(1));
78
79 std::ignore = future.Wait();
80
81 EXPECT_EQ(expected_value, future.Get());
82 }
83
TEST_F(TestFutureTest,WaitShouldReturnTrueWhenValueArrives)84 TEST_F(TestFutureTest, WaitShouldReturnTrueWhenValueArrives) {
85 TestFuture<int> future;
86
87 PostDelayedTask(BindOnce(future.GetCallback(), kAnyValue), Milliseconds(1));
88
89 bool success = future.Wait();
90 EXPECT_TRUE(success);
91 }
92
TEST_F(TestFutureTest,WaitShouldReturnFalseIfTimeoutHappens)93 TEST_F(TestFutureTest, WaitShouldReturnFalseIfTimeoutHappens) {
94 ScopedRunLoopTimeout timeout(FROM_HERE, Milliseconds(1));
95
96 // `ScopedRunLoopTimeout` will automatically fail the test when a timeout
97 // happens, so we use EXPECT_FATAL_FAILURE to handle this failure.
98 // EXPECT_FATAL_FAILURE only works on static objects.
99 static bool success;
100 static TestFuture<AnyType> future;
101
102 EXPECT_NONFATAL_FAILURE({ success = future.Wait(); }, "timed out");
103
104 EXPECT_FALSE(success);
105 }
106
TEST_F(TestFutureTest,GetShouldBlockUntilValueArrives)107 TEST_F(TestFutureTest, GetShouldBlockUntilValueArrives) {
108 const int expected_value = 42;
109 TestFuture<int> future;
110
111 PostDelayedTask(BindOnce(future.GetCallback(), expected_value),
112 Milliseconds(1));
113
114 int actual_value = future.Get();
115
116 EXPECT_EQ(expected_value, actual_value);
117 }
118
TEST_F(TestFutureTest,GetShouldCheckIfTimeoutHappens)119 TEST_F(TestFutureTest, GetShouldCheckIfTimeoutHappens) {
120 ScopedRunLoopTimeout timeout(FROM_HERE, Milliseconds(1));
121
122 TestFuture<AnyType> future;
123
124 EXPECT_CHECK_DEATH_WITH(std::ignore = future.Get(), "timed out");
125 }
126
TEST_F(TestFutureTest,TakeShouldWorkWithMoveOnlyValue)127 TEST_F(TestFutureTest, TakeShouldWorkWithMoveOnlyValue) {
128 const int expected_data = 99;
129 TestFuture<MoveOnlyValue> future;
130
131 RunLater(BindOnce(future.GetCallback(), MoveOnlyValue(expected_data)));
132
133 MoveOnlyValue actual_value = future.Take();
134
135 EXPECT_EQ(expected_data, actual_value.data);
136 }
137
TEST_F(TestFutureTest,TakeShouldCheckIfTimeoutHappens)138 TEST_F(TestFutureTest, TakeShouldCheckIfTimeoutHappens) {
139 ScopedRunLoopTimeout timeout(FROM_HERE, Milliseconds(1));
140
141 TestFuture<AnyType> future;
142
143 EXPECT_CHECK_DEATH_WITH(std::ignore = future.Take(), "timed out");
144 }
145
TEST_F(TestFutureTest,IsReadyShouldBeTrueWhenValueIsSet)146 TEST_F(TestFutureTest, IsReadyShouldBeTrueWhenValueIsSet) {
147 TestFuture<AnyType> future;
148
149 EXPECT_FALSE(future.IsReady());
150
151 future.SetValue(kAnyValue);
152
153 EXPECT_TRUE(future.IsReady());
154 }
155
TEST_F(TestFutureTest,ClearShouldRemoveStoredValue)156 TEST_F(TestFutureTest, ClearShouldRemoveStoredValue) {
157 TestFuture<AnyType> future;
158
159 future.SetValue(kAnyValue);
160
161 future.Clear();
162
163 EXPECT_FALSE(future.IsReady());
164 }
165
TEST_F(TestFutureTest,ShouldNotAllowOverwritingStoredValue)166 TEST_F(TestFutureTest, ShouldNotAllowOverwritingStoredValue) {
167 TestFuture<AnyType> future;
168
169 future.SetValue(kAnyValue);
170
171 EXPECT_NONFATAL_FAILURE(future.SetValue(kOtherValue), "Received new value");
172 }
173
TEST_F(TestFutureTest,ShouldAllowReuseIfPreviousValueIsFirstConsumed)174 TEST_F(TestFutureTest, ShouldAllowReuseIfPreviousValueIsFirstConsumed) {
175 TestFuture<std::string> future;
176
177 RunLater([&]() { future.SetValue("first value"); });
178 EXPECT_EQ(future.Take(), "first value");
179
180 ASSERT_FALSE(future.IsReady());
181
182 RunLater([&]() { future.SetValue("second value"); });
183 EXPECT_EQ(future.Take(), "second value");
184 }
185
TEST_F(TestFutureTest,ShouldAllowReusingCallback)186 TEST_F(TestFutureTest, ShouldAllowReusingCallback) {
187 TestFuture<std::string> future;
188
189 RepeatingCallback<void(std::string)> callback = future.GetRepeatingCallback();
190
191 RunLater(BindOnce(callback, "first value"));
192 EXPECT_EQ(future.Take(), "first value");
193
194 RunLater(BindOnce(callback, "second value"));
195 EXPECT_EQ(future.Take(), "second value");
196 }
197
TEST_F(TestFutureTest,WaitShouldWorkAfterTake)198 TEST_F(TestFutureTest, WaitShouldWorkAfterTake) {
199 TestFuture<std::string> future;
200
201 future.SetValue("first value");
202 std::ignore = future.Take();
203
204 RunLater([&]() { future.SetValue("second value"); });
205
206 EXPECT_TRUE(future.Wait());
207 EXPECT_EQ(future.Get(), "second value");
208 }
209
TEST_F(TestFutureTest,ShouldSignalWhenSetValueIsInvoked)210 TEST_F(TestFutureTest, ShouldSignalWhenSetValueIsInvoked) {
211 const int expected_value = 111;
212 TestFuture<int> future;
213
214 RunLater([&future]() { future.SetValue(expected_value); });
215
216 int actual_value = future.Get();
217
218 EXPECT_EQ(expected_value, actual_value);
219 }
220
TEST_F(TestFutureTest,ShouldAllowReferenceArgumentsForCallback)221 TEST_F(TestFutureTest, ShouldAllowReferenceArgumentsForCallback) {
222 const int expected_value = 222;
223 TestFuture<int> future;
224
225 OnceCallback<void(const int&)> callback = future.GetCallback<const int&>();
226 RunLater(BindOnce(std::move(callback), expected_value));
227
228 int actual_value = future.Get();
229
230 EXPECT_EQ(expected_value, actual_value);
231 }
232
TEST_F(TestFutureTest,ShouldAllowInvokingCallbackAfterFutureIsDestroyed)233 TEST_F(TestFutureTest, ShouldAllowInvokingCallbackAfterFutureIsDestroyed) {
234 OnceCallback<void(int)> callback;
235
236 {
237 TestFuture<int> future;
238 callback = future.GetCallback();
239 }
240
241 std::move(callback).Run(1);
242 }
243
TEST_F(TestFutureTest,ShouldReturnTupleValue)244 TEST_F(TestFutureTest, ShouldReturnTupleValue) {
245 const int expected_int_value = 5;
246 const std::string expected_string_value = "value";
247
248 TestFuture<int, std::string> future;
249
250 RunLater(BindOnce(future.GetCallback(), expected_int_value,
251 expected_string_value));
252
253 const std::tuple<int, std::string>& actual = future.Get();
254
255 EXPECT_EQ(expected_int_value, std::get<0>(actual));
256 EXPECT_EQ(expected_string_value, std::get<1>(actual));
257 }
258
TEST_F(TestFutureTest,ShouldAllowAccessingTupleValueUsingGetWithIndex)259 TEST_F(TestFutureTest, ShouldAllowAccessingTupleValueUsingGetWithIndex) {
260 const int expected_int_value = 5;
261 const std::string expected_string_value = "value";
262
263 TestFuture<int, std::string> future;
264
265 RunLater(BindOnce(future.GetCallback(), expected_int_value,
266 expected_string_value));
267
268 std::ignore = future.Get();
269
270 EXPECT_EQ(expected_int_value, future.Get<0>());
271 EXPECT_EQ(expected_string_value, future.Get<1>());
272 }
273
TEST_F(TestFutureTest,ShouldAllowAccessingTupleValueUsingGetWithType)274 TEST_F(TestFutureTest, ShouldAllowAccessingTupleValueUsingGetWithType) {
275 const int expected_int_value = 5;
276 const std::string expected_string_value = "value";
277
278 TestFuture<int, std::string> future;
279
280 RunLater(BindOnce(future.GetCallback(), expected_int_value,
281 expected_string_value));
282
283 std::ignore = future.Get();
284
285 EXPECT_EQ(expected_int_value, future.Get<int>());
286 EXPECT_EQ(expected_string_value, future.Get<std::string>());
287 }
288
TEST_F(TestFutureTest,ShouldAllowReferenceArgumentsForMultiArgumentCallback)289 TEST_F(TestFutureTest, ShouldAllowReferenceArgumentsForMultiArgumentCallback) {
290 const int expected_int_value = 5;
291 const std::string expected_string_value = "value";
292
293 TestFuture<int, std::string> future;
294
295 OnceCallback<void(int, const std::string&)> callback =
296 future.GetCallback<int, const std::string&>();
297 RunLater(
298 BindOnce(std::move(callback), expected_int_value, expected_string_value));
299
300 std::tuple<int, std::string> actual = future.Get();
301
302 EXPECT_EQ(expected_int_value, std::get<0>(actual));
303 EXPECT_EQ(expected_string_value, std::get<1>(actual));
304 }
305
TEST_F(TestFutureTest,SetValueShouldAllowMultipleArguments)306 TEST_F(TestFutureTest, SetValueShouldAllowMultipleArguments) {
307 const int expected_int_value = 5;
308 const std::string expected_string_value = "value";
309
310 TestFuture<int, std::string> future;
311
312 RunLater([&future, expected_string_value]() {
313 future.SetValue(expected_int_value, expected_string_value);
314 });
315
316 const std::tuple<int, std::string>& actual = future.Get();
317
318 EXPECT_EQ(expected_int_value, std::get<0>(actual));
319 EXPECT_EQ(expected_string_value, std::get<1>(actual));
320 }
321
TEST_F(TestFutureTest,ShouldSupportCvRefType)322 TEST_F(TestFutureTest, ShouldSupportCvRefType) {
323 std::string expected_value = "value";
324 TestFuture<const std::string&> future;
325
326 OnceCallback<void(const std::string&)> callback = future.GetCallback();
327 std::move(callback).Run(expected_value);
328
329 // both get and take should compile, and take should return the decayed value.
330 const std::string& get_result = future.Get();
331 EXPECT_EQ(expected_value, get_result);
332
333 std::string take_result = future.Take();
334 EXPECT_EQ(expected_value, take_result);
335 }
336
TEST_F(TestFutureTest,ShouldSupportMultipleCvRefTypes)337 TEST_F(TestFutureTest, ShouldSupportMultipleCvRefTypes) {
338 const int expected_first_value = 5;
339 std::string expected_second_value = "value";
340 const long expected_third_value = 10;
341 TestFuture<const int, std::string&, const long&> future;
342
343 OnceCallback<void(const int, std::string&, const long&)> callback =
344 future.GetCallback();
345 std::move(callback).Run(expected_first_value, expected_second_value,
346 expected_third_value);
347
348 // both get and take should compile, and return the decayed value.
349 const std::tuple<int, std::string, long>& get_result = future.Get();
350 EXPECT_EQ(expected_first_value, std::get<0>(get_result));
351 EXPECT_EQ(expected_second_value, std::get<1>(get_result));
352 EXPECT_EQ(expected_third_value, std::get<2>(get_result));
353
354 // Get<i> should also work
355 EXPECT_EQ(expected_first_value, future.Get<0>());
356 EXPECT_EQ(expected_second_value, future.Get<1>());
357 EXPECT_EQ(expected_third_value, future.Get<2>());
358
359 std::tuple<int, std::string, long> take_result = future.Take();
360 EXPECT_EQ(expected_first_value, std::get<0>(take_result));
361 EXPECT_EQ(expected_second_value, std::get<1>(take_result));
362 EXPECT_EQ(expected_third_value, std::get<2>(take_result));
363 }
364
TEST_F(TestFutureTest,ShouldAllowReuseIfPreviousTupleValueIsFirstConsumed)365 TEST_F(TestFutureTest, ShouldAllowReuseIfPreviousTupleValueIsFirstConsumed) {
366 TestFuture<std::string, int> future;
367
368 future.SetValue("first value", 1);
369 std::ignore = future.Take();
370
371 ASSERT_FALSE(future.IsReady());
372
373 future.SetValue("second value", 2);
374 EXPECT_EQ(future.Take(), std::make_tuple("second value", 2));
375 }
376
TEST_F(TestFutureTest,ShouldPrintCurrentValueIfItIsOverwritten)377 TEST_F(TestFutureTest, ShouldPrintCurrentValueIfItIsOverwritten) {
378 using UnprintableValue = MoveOnlyValue;
379
380 TestFuture<const char*, int, UnprintableValue> future;
381
382 future.SetValue("first-value", 1111, UnprintableValue());
383
384 EXPECT_NONFATAL_FAILURE(
385 future.SetValue("second-value", 2222, UnprintableValue()),
386 "old value <first-value, 1111, [4-byte object at 0x");
387 }
388
TEST_F(TestFutureTest,ShouldPrintNewValueIfItOverwritesOldValue)389 TEST_F(TestFutureTest, ShouldPrintNewValueIfItOverwritesOldValue) {
390 using UnprintableValue = MoveOnlyValue;
391
392 TestFuture<const char*, int, UnprintableValue> future;
393
394 future.SetValue("first-value", 1111, UnprintableValue());
395
396 EXPECT_NONFATAL_FAILURE(
397 future.SetValue("second-value", 2222, UnprintableValue()),
398 "new value <second-value, 2222, [4-byte object at 0x");
399 }
400
401 using TestFutureWithoutValuesTest = TestFutureTest;
402
TEST_F(TestFutureWithoutValuesTest,IsReadyShouldBeTrueWhenSetValueIsInvoked)403 TEST_F(TestFutureWithoutValuesTest, IsReadyShouldBeTrueWhenSetValueIsInvoked) {
404 TestFuture<void> future;
405
406 EXPECT_FALSE(future.IsReady());
407
408 future.SetValue();
409
410 EXPECT_TRUE(future.IsReady());
411 }
412
TEST_F(TestFutureWithoutValuesTest,WaitShouldUnblockWhenSetValueIsInvoked)413 TEST_F(TestFutureWithoutValuesTest, WaitShouldUnblockWhenSetValueIsInvoked) {
414 TestFuture<void> future;
415
416 RunLater([&future]() { future.SetValue(); });
417
418 ASSERT_FALSE(future.IsReady());
419 std::ignore = future.Wait();
420 EXPECT_TRUE(future.IsReady());
421 }
422
TEST_F(TestFutureWithoutValuesTest,WaitShouldUnblockWhenCallbackIsInvoked)423 TEST_F(TestFutureWithoutValuesTest, WaitShouldUnblockWhenCallbackIsInvoked) {
424 TestFuture<void> future;
425
426 RunLater(future.GetCallback());
427
428 ASSERT_FALSE(future.IsReady());
429 std::ignore = future.Wait();
430 EXPECT_TRUE(future.IsReady());
431 }
432
TEST_F(TestFutureWithoutValuesTest,GetShouldUnblockWhenCallbackIsInvoked)433 TEST_F(TestFutureWithoutValuesTest, GetShouldUnblockWhenCallbackIsInvoked) {
434 TestFuture<void> future;
435
436 RunLater(future.GetCallback());
437
438 ASSERT_FALSE(future.IsReady());
439 future.Get();
440 EXPECT_TRUE(future.IsReady());
441 }
442
TEST(TestFutureWithoutSingleThreadTaskEnvironment,CanCreateTestFutureBeforeTaskEnvironment)443 TEST(TestFutureWithoutSingleThreadTaskEnvironment,
444 CanCreateTestFutureBeforeTaskEnvironment) {
445 TestFuture<AnyType> future;
446
447 // If we come here the test passes, since it means we can create a
448 // `TestFuture` without having a `TaskEnvironment`.
449 }
450
TEST(TestFutureWithoutSingleThreadTaskEnvironment,WaitShouldDcheckWithoutTaskEnvironment)451 TEST(TestFutureWithoutSingleThreadTaskEnvironment,
452 WaitShouldDcheckWithoutTaskEnvironment) {
453 TestFuture<AnyType> future;
454
455 EXPECT_CHECK_DEATH_WITH((void)future.Wait(),
456 "requires a single-threaded context");
457 }
458
459 } // namespace base::test
460