• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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