• 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 #ifndef BASE_TEST_TEST_FUTURE_H_
6 #define BASE_TEST_TEST_FUTURE_H_
7 
8 #include <memory>
9 #include <optional>
10 #include <tuple>
11 
12 #include "base/auto_reset.h"
13 #include "base/check.h"
14 #include "base/functional/bind.h"
15 #include "base/functional/callback_forward.h"
16 #include "base/functional/callback_helpers.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/run_loop.h"
19 #include "base/sequence_checker.h"
20 #include "base/strings/to_string.h"
21 #include "base/task/bind_post_task.h"
22 #include "base/task/sequenced_task_runner.h"
23 #include "base/test/test_future_internal.h"
24 #include "base/thread_annotations.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 
27 namespace base::test {
28 
29 // Helper class to test code that returns its result(s) asynchronously through a
30 // callback:
31 //
32 //    - Pass the callback provided by `GetCallback()` to the code under test.
33 //    - Wait for the callback to be invoked by calling `Wait(),` or `Get()` to
34 //      access the value(s) passed to the callback.
35 //
36 //   Example usage:
37 //
38 //     TEST_F(MyTestFixture, MyTest) {
39 //       TestFuture<ResultType> future;
40 //
41 //       object_under_test.DoSomethingAsync(future.GetCallback());
42 //
43 //       const ResultType& actual_result = future.Get();
44 //
45 //       // When you come here, DoSomethingAsync has finished and
46 //       // `actual_result` contains the result passed to the callback.
47 //     }
48 //
49 //   Example using `Wait()`:
50 //
51 //     TEST_F(MyTestFixture, MyWaitTest) {
52 //       TestFuture<ResultType> future;
53 //
54 //       object_under_test.DoSomethingAsync(future.GetCallback());
55 //
56 //       // Optional. The Get() call below will also wait until the value
57 //       // arrives, but this explicit call to Wait() can be useful if you want
58 //       // to add extra information.
59 //       ASSERT_TRUE(future.Wait()) << "Detailed error message";
60 //
61 //       const ResultType& actual_result = future.Get();
62 //     }
63 //
64 // `TestFuture` supports both single- and multiple-argument callbacks.
65 // `TestFuture` provides both index and type based accessors for multi-argument
66 // callbacks. `Get()` and `Take()` return tuples for multi-argument callbacks.
67 //
68 //   TestFuture<int, std::string> future;
69 //   future.Get<0>();   // Reads the first argument
70 //   future.Get<int>(); // Also reads the first argument
71 //   future.Get();      // Returns a `const std::tuple<int, std::string>&`
72 //
73 //   Example for a multi-argument callback:
74 //
75 //     TEST_F(MyTestFixture, MyTest) {
76 //       TestFuture<int, std::string> future;
77 //
78 //       object_under_test.DoSomethingAsync(future.GetCallback());
79 //
80 //       // You can use type based accessors:
81 //       int first_argument = future.Get<int>();
82 //       const std::string& second_argument = future.Get<std::string>();
83 //
84 //       // or index based accessors:
85 //       int first_argument = future.Get<0>();
86 //       const std::string& second_argument = future.Get<1>();
87 //     }
88 //
89 // You can also satisfy a `TestFuture` by calling `SetValue()` from the sequence
90 // on which the `TestFuture` was created. This is mostly useful when
91 // implementing an observer:
92 //
93 //     class MyTestObserver: public MyObserver {
94 //       public:
95 //         // `MyObserver` implementation:
96 //         void ObserveAnInt(int value) override {
97 //           future_.SetValue(value);
98 //         }
99 //
100 //         int Wait() { return future_.Take(); }
101 //
102 //      private:
103 //        TestFuture<int> future_;
104 //     };
105 //
106 //     TEST_F(MyTestFixture, MyTest) {
107 //       MyTestObserver observer;
108 //
109 //       object_under_test.DoSomethingAsync(observer);
110 //
111 //       int value_passed_to_observer = observer.Wait();
112 //     };
113 //
114 // `GetRepeatingCallback()` allows you to use a single `TestFuture` in code
115 // that invokes the callback multiple times.
116 // Your test must take care to consume each value before the next value
117 // arrives. You can consume the value by calling either `Take()` or `Clear()`.
118 //
119 //   Example for reusing a `TestFuture`:
120 //
121 //     TEST_F(MyTestFixture, MyReuseTest) {
122 //       TestFuture<std::string> future;
123 //
124 //       object_under_test.InstallCallback(future.GetRepeatingCallback());
125 //
126 //       object_under_test.DoSomething();
127 //       EXPECT_EQ(future.Take(), "expected-first-value");
128 //       // Because we used `Take()` the test future is ready for reuse.
129 //
130 //       object_under_test.DoSomethingElse();
131 //       EXPECT_EQ(future.Take(), "expected-second-value");
132 //     }
133 //
134 //   Example for reusing  a `TestFuture` using `Get()` + `Clear()`:
135 //
136 //     TEST_F(MyTestFixture, MyReuseTest) {
137 //       TestFuture<std::string, int> future;
138 //
139 //       object_under_test.InstallCallback(future.GetRepeatingCallback());
140 //
141 //       object_under_test.DoSomething();
142 //
143 //       EXPECT_EQ(future.Get<std::string>(), "expected-first-value");
144 //       EXPECT_EQ(future.Get<int>(), 5);
145 //       // Because we used `Get()`, the test future is not ready for reuse,
146 //       //so we need an explicit `Clear()` call.
147 //       future.Clear();
148 //
149 //       object_under_test.DoSomethingElse();
150 //       EXPECT_EQ(future.Get<std::string>(), "expected-second-value");
151 //       EXPECT_EQ(future.Get<int>(), 2);
152 //     }
153 //
154 // Finally, `TestFuture` also supports no-args callbacks:
155 //
156 //   Example for no-args callbacks:
157 //
158 //     TEST_F(MyTestFixture, MyTest) {
159 //       TestFuture<void> signal;
160 //
161 //       object_under_test.DoSomethingAsync(signal.GetCallback());
162 //
163 //       EXPECT_TRUE(signal.Wait());
164 //       // When you come here you know the callback was invoked and the async
165 //       // code is ready.
166 //     }
167 //
168 // All access to this class and its callbacks must be made from the sequence on
169 // which the `TestFuture` was constructed.
170 //
171 template <typename... Types>
172 class TestFuture {
173  public:
174   using TupleType = std::tuple<std::decay_t<Types>...>;
175 
176   static_assert(std::tuple_size_v<TupleType> > 0,
177                 "Don't use TestFuture<> but use TestFuture<void> instead");
178 
179   TestFuture() = default;
180   TestFuture(const TestFuture&) = delete;
181   TestFuture& operator=(const TestFuture&) = delete;
182   ~TestFuture() = default;
183 
184   // Waits for the value to arrive.
185   //
186   // Returns true if the value arrived, or false if a timeout happens.
187   //
188   // Directly calling Wait() is not required as Get()/Take() will also wait for
189   // the value to arrive, however you can use a direct call to Wait() to
190   // improve the error reported:
191   //
192   //   ASSERT_TRUE(queue.Wait()) << "Detailed error message";
193   //
Wait()194   [[nodiscard]] bool Wait() {
195     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
196 
197     if (values_) {
198       return true;
199     }
200 
201     // Wait for the value to arrive.
202     RunLoop loop;
203     AutoReset<RepeatingClosure> quit_loop(&ready_signal_, loop.QuitClosure());
204     loop.Run();
205 
206     return IsReady();
207   }
208 
209   // Returns true if the value has arrived.
IsReady()210   bool IsReady() const {
211     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
212     return values_.has_value();
213   }
214 
215   // Waits for the value to arrive, and returns the I-th value.
216   //
217   // Will CHECK if a timeout happens.
218   //
219   // Example usage:
220   //
221   //   TestFuture<int, std::string> future;
222   //   int first = future.Get<0>();
223   //   std::string second = future.Get<1>();
224   //
225   template <std::size_t I, typename T = TupleType>
requires(internal::IsNonEmptyTuple<T>)226     requires(internal::IsNonEmptyTuple<T>)
227   const auto& Get() {
228     return std::get<I>(GetTuple());
229   }
230 
231   // Waits for the value to arrive, and returns the value with the given type.
232   //
233   // Will CHECK if a timeout happens.
234   //
235   // Example usage:
236   //
237   //   TestFuture<int, std::string> future;
238   //   int first = future.Get<int>();
239   //   std::string second = future.Get<std::string>();
240   //
241   template <typename Type>
Get()242   const auto& Get() {
243     return std::get<Type>(GetTuple());
244   }
245 
246   // Returns a callback that when invoked will store all the argument values,
247   // and unblock any waiters. The callback must be invoked on the sequence the
248   // TestFuture was created on.
249   //
250   // Templated so you can specify how you need the arguments to be passed -
251   // const, reference, .... Defaults to simply `Types...`.
252   //
253   // Example usage:
254   //
255   //   TestFuture<int, std::string> future;
256   //
257   //   // Without specifying the callback argument types, this returns
258   //   // base::OnceCallback<void(int, std::string)>.
259   //   future.GetCallback();
260   //
261   //   // By explicitly specifying the callback argument types, this returns
262   //   // base::OnceCallback<void(int, const std::string&)>.
263   //   future.GetCallback<int, const std::string&>();
264   //
265   template <typename... CallbackArgumentsTypes>
GetCallback()266   OnceCallback<void(CallbackArgumentsTypes...)> GetCallback() {
267     return GetRepeatingCallback<CallbackArgumentsTypes...>();
268   }
269 
GetCallback()270   OnceCallback<void(Types...)> GetCallback() { return GetCallback<Types...>(); }
271 
272   // Returns a repeating callback that when invoked will store all the argument
273   // values, and unblock any waiters. The callback must be invoked on the
274   // sequence the TestFuture was created on.
275   //
276   // You must take care that the stored value is consumed before the callback
277   // is invoked a second time. You can consume the value by calling either
278   // `Take()` or `Clear()`.
279   //
280   // Example usage:
281   //
282   //   TestFuture<std::string> future;
283   //
284   //   object_under_test.InstallCallback(future.GetRepeatingCallback());
285   //
286   //   object_under_test.DoSomething();
287   //   EXPECT_EQ(future.Take(), "expected-first-value");
288   //   // Because we used `Take()` the test future is ready for reuse.
289   //
290   //   object_under_test.DoSomethingElse();
291   //   // We can also use `Get()` + `Clear()` to reuse the callback.
292   //   EXPECT_EQ(future.Get(), "expected-second-value");
293   //   future.Clear();
294   //
295   //   object_under_test.DoSomethingElse();
296   //   EXPECT_EQ(future.Take(), "expected-third-value");
297   //
298   template <typename... CallbackArgumentsTypes>
GetRepeatingCallback()299   RepeatingCallback<void(CallbackArgumentsTypes...)> GetRepeatingCallback() {
300     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
301     return BindRepeating(
302         [](WeakPtr<TestFuture<Types...>> future,
303            CallbackArgumentsTypes... values) {
304           if (future) {
305             future->SetValue(std::forward<CallbackArgumentsTypes>(values)...);
306           }
307         },
308         weak_ptr_factory_.GetWeakPtr());
309   }
310 
GetRepeatingCallback()311   RepeatingCallback<void(Types...)> GetRepeatingCallback() {
312     return GetRepeatingCallback<Types...>();
313   }
314 
315   // Returns a callback that can be invoked on any sequence. When invoked it
316   // will post a task to the sequence the TestFuture was created on, to store
317   // all the argument values, and unblock any waiters.
318   //
319   // Templated so you can specify how you need the arguments to be passed -
320   // const, reference, .... Defaults to simply `Types...`.
321   //
322   // Example usage:
323   //
324   //   TestFuture<int, std::string> future;
325   //
326   //   // Without specifying the callback argument types, this returns
327   //   // base::OnceCallback<void(int, std::string)>.
328   //   auto callback = future.GetSequenceBoundCallback();
329   //
330   //   // By explicitly specifying the callback argument types, this returns
331   //   // base::OnceCallback<void(int, const std::string&)>.
332   //   auto callback =
333   //       future.GetSequenceBoundCallback<int, const std::string&>();
334   //
335   //   // AsyncOperation invokes `callback` with a result.
336   //   other_task_runner->PostTask(FROM_HERE, base::BindOnce(&AsyncOperation,
337   //                                              std::move(callback));
338   //
339   //   future.Wait();
340   //
341   template <typename... CallbackArgumentsTypes>
GetSequenceBoundCallback()342   OnceCallback<void(CallbackArgumentsTypes...)> GetSequenceBoundCallback() {
343     return GetSequenceBoundRepeatingCallback<CallbackArgumentsTypes...>();
344   }
345 
GetSequenceBoundCallback()346   OnceCallback<void(Types...)> GetSequenceBoundCallback() {
347     return GetSequenceBoundCallback<Types...>();
348   }
349 
350   // Returns a repeating callback that can be invoked on any sequence. When
351   // invoked it will post a task to the sequence the TestFuture was created on,
352   // to store all the argument values, and unblock any waiters.
353   //
354   // You must take care that the stored value is consumed before the callback
355   // is invoked a second time. You can consume the value by calling either
356   // `Take()` or `Clear()`.
357   //
358   // Example usage:
359   //
360   //   base::SequenceBound<Object> object_under_test(other_task_runner);
361   //   TestFuture<std::string> future;
362   //
363   //   object_under_test.AsyncCall(&Object::InstallCallback,
364   //                               future.GetSequenceBoundRepeatingCallback());
365   //
366   //   object_under_test.AsyncCall(&DoSomething);
367   //   EXPECT_EQ(future.Take(), "expected-first-value");
368   //   // Because we used `Take()` the test future is ready for reuse.
369   //
370   //   object_under_test.AsyncCall(&DoSomethingElse);
371   //   // We can also use `Get()` + `Clear()` to reuse the callback.
372   //   EXPECT_EQ(future.Get(), "expected-second-value");
373   //   future.Clear();
374   //
375   //   object_under_test.AsyncCall(&DoSomethingElse);
376   //   EXPECT_EQ(future.Take(), "expected-third-value");
377   //
378   template <typename... CallbackArgumentsTypes>
379   RepeatingCallback<void(CallbackArgumentsTypes...)>
GetSequenceBoundRepeatingCallback()380   GetSequenceBoundRepeatingCallback() {
381     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
382     return BindPostTask(base::SequencedTaskRunner::GetCurrentDefault(),
383                         GetRepeatingCallback<CallbackArgumentsTypes...>());
384   }
385 
GetSequenceBoundRepeatingCallback()386   RepeatingCallback<void(Types...)> GetSequenceBoundRepeatingCallback() {
387     return GetSequenceBoundRepeatingCallback<Types...>();
388   }
389 
390   // Sets the value of the future.
391   // This will unblock any pending Wait() or Get() call.
SetValue(Types...values)392   void SetValue(Types... values) {
393     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
394 
395     auto new_values = std::make_tuple(std::forward<Types>(values)...);
396 
397     EXPECT_FALSE(values_.has_value())
398         << "Received new value " << ToString(new_values)  //
399         << " before old value " << ToString(GetTuple())
400         << " was consumed through Take() or Clear().";
401 
402     values_ = std::move(new_values);
403 
404     ready_signal_.Run();
405   }
406 
407   // Clears the future, allowing it to be reused and accept a new value.
408   //
409   // All outstanding callbacks issued through `GetCallback()` remain valid.
Clear()410   void Clear() {
411     if (IsReady()) {
412       std::ignore = Take();
413     }
414   }
415 
416   //////////////////////////////////////////////////////////////////////////////
417   //  Accessor methods only available if the future holds a single value.
418   //////////////////////////////////////////////////////////////////////////////
419 
420   // Waits for the value to arrive, and returns a reference to it.
421   //
422   // Will CHECK if a timeout happens.
423   template <typename T = TupleType>
requires(internal::IsSingleValuedTuple<T>)424     requires(internal::IsSingleValuedTuple<T>)
425   [[nodiscard]] const auto& Get() {
426     return std::get<0>(GetTuple());
427   }
428 
429   // Waits for the value to arrive, and returns it.
430   //
431   // Will CHECK if a timeout happens.
432   template <typename T = TupleType>
requires(internal::IsSingleValuedTuple<T>)433     requires(internal::IsSingleValuedTuple<T>)
434   [[nodiscard]] auto Take() {
435     return std::get<0>(TakeTuple());
436   }
437 
438   //////////////////////////////////////////////////////////////////////////////
439   //  Accessor methods only available if the future holds multiple values.
440   //////////////////////////////////////////////////////////////////////////////
441 
442   // Waits for the values to arrive, and returns a tuple with the values.
443   //
444   // Will CHECK if a timeout happens.
445   template <typename T = TupleType>
requires(internal::IsMultiValuedTuple<T>)446     requires(internal::IsMultiValuedTuple<T>)
447   [[nodiscard]] const TupleType& Get() {
448     return GetTuple();
449   }
450 
451   // Waits for the values to arrive, and moves a tuple with the values out.
452   //
453   // Will CHECK if a timeout happens.
454   template <typename T = TupleType>
requires(internal::IsMultiValuedTuple<T>)455     requires(internal::IsMultiValuedTuple<T>)
456   [[nodiscard]] TupleType Take() {
457     return TakeTuple();
458   }
459 
460  private:
GetTuple()461   [[nodiscard]] const TupleType& GetTuple() {
462     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
463     bool success = Wait();
464     CHECK(success) << "Waiting for value timed out.";
465     return values_.value();
466   }
467 
TakeTuple()468   [[nodiscard]] TupleType TakeTuple() {
469     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
470     bool success = Wait();
471     CHECK(success) << "Waiting for value timed out.";
472 
473     return std::exchange(values_, {}).value();
474   }
475 
476   SEQUENCE_CHECKER(sequence_checker_);
477 
478   base::RepeatingClosure ready_signal_ GUARDED_BY_CONTEXT(sequence_checker_) =
479       base::DoNothing();
480 
481   std::optional<TupleType> values_ GUARDED_BY_CONTEXT(sequence_checker_);
482 
483   WeakPtrFactory<TestFuture<Types...>> weak_ptr_factory_{this};
484 };
485 
486 // Specialization so you can use `TestFuture` to wait for a no-args callback.
487 //
488 // This specialization offers a subset of the methods provided on the base
489 // `TestFuture`, as there is no value to be returned.
490 template <>
491 class TestFuture<void> {
492  public:
493   // Waits until the callback or `SetValue()` is invoked.
494   //
495   // Fails your test if a timeout happens, but you can check the return value
496   // to improve the error reported:
497   //
498   //   ASSERT_TRUE(future.Wait()) << "Detailed error message";
Wait()499   [[nodiscard]] bool Wait() { return implementation_.Wait(); }
500 
501   // Same as above, then clears the future, allowing it to be reused and accept
502   // a new value.
WaitAndClear()503   [[nodiscard]] bool WaitAndClear() {
504     auto result = Wait();
505     Clear();
506     return result;
507   }
508 
509   // Waits until the callback or `SetValue()` is invoked.
Get()510   void Get() { std::ignore = implementation_.Get(); }
511 
512   // Returns true if the callback or `SetValue()` was invoked.
IsReady()513   bool IsReady() const { return implementation_.IsReady(); }
514 
515   // Returns a callback that when invoked will unblock any waiters.
GetCallback()516   OnceClosure GetCallback() {
517     return BindOnce(implementation_.GetCallback(), true);
518   }
519 
520   // Returns a callback that when invoked will unblock any waiters.
GetRepeatingCallback()521   RepeatingClosure GetRepeatingCallback() {
522     return BindRepeating(implementation_.GetRepeatingCallback(), true);
523   }
524 
525   // Returns a callback that when invoked on any sequence will unblock any
526   // waiters.
GetSequenceBoundCallback()527   OnceClosure GetSequenceBoundCallback() {
528     return BindOnce(implementation_.GetSequenceBoundCallback(), true);
529   }
530 
531   // Returns a callback that when invoked on any sequence will unblock any
532   // waiters.
GetSequenceBoundRepeatingCallback()533   RepeatingClosure GetSequenceBoundRepeatingCallback() {
534     return BindRepeating(implementation_.GetSequenceBoundRepeatingCallback(),
535                          true);
536   }
537 
538   // Indicates this `TestFuture` is ready, and unblocks any waiters.
SetValue()539   void SetValue() { implementation_.SetValue(true); }
540 
541   // Clears the future, allowing it to be reused and accept a new value.
542   //
543   // All outstanding callbacks issued through `GetCallback()` remain valid.
Clear()544   void Clear() { implementation_.Clear(); }
545 
546  private:
547   TestFuture<bool> implementation_;
548 };
549 
550 // A gmock action that when invoked will store the argument values and
551 // unblock any waiters. The action must be invoked on the sequence the
552 // TestFuture was created on.
553 //
554 // Usually the action will be used with `WillOnce()` and only invoked once,
555 // but if you consume the value with `Take()` or `Clear()` it is safe to
556 // invoke it again.
557 //
558 // Example usage:
559 //   TestFuture<int> future;
560 //
561 //   EXPECT_CALL(delegate, OnReadComplete)
562 //     .WillOnce(InvokeFuture(future));
563 //
564 //   object_under_test.Read(buffer, 16);
565 //
566 //   EXPECT_EQ(future.Take(), 16);
567 //
568 //
569 //
570 // Implementation note: this is not implemented using the MATCHER_P macro as the
571 // C++03-compatible way it implements varargs would make this too verbose.
572 // Instead, it takes advantage of the ability to pass a functor to .WillOnce()
573 // and .WillRepeatedly().
574 template <typename... Types>
575 class InvokeFuture {
576  public:
577   // The TestFuture must be an lvalue. Passing an rvalue would make no sense as
578   // you wouldn't be able to call Take() on it afterwards.
InvokeFuture(TestFuture<Types...> & future)579   explicit InvokeFuture(TestFuture<Types...>& future)
580       : callback_(future.GetRepeatingCallback()) {}
581 
582   // GMock actions must be copyable.
583   InvokeFuture(const InvokeFuture&) = default;
584   InvokeFuture& operator=(const InvokeFuture&) = default;
585 
586   // WillOnce() can take advantage of move constructors.
587   InvokeFuture(InvokeFuture&&) = default;
588   InvokeFuture& operator=(InvokeFuture&&) = default;
589 
operator()590   void operator()(Types... values) {
591     callback_.Run(std::forward<Types>(values)...);
592   }
593 
594  private:
595   RepeatingCallback<void(Types...)> callback_;
596 };
597 
598 // Specialization for TestFuture<void>.
599 template <>
600 class InvokeFuture<void> {
601  public:
InvokeFuture(TestFuture<void> & future)602   explicit InvokeFuture(TestFuture<void>& future)
603       : closure_(future.GetRepeatingCallback()) {}
604 
605   InvokeFuture(const InvokeFuture&) = default;
606   InvokeFuture& operator=(const InvokeFuture&) = default;
607   InvokeFuture(InvokeFuture&&) = default;
608   InvokeFuture& operator=(InvokeFuture&&) = default;
609 
operator()610   void operator()() { closure_.Run(); }
611 
612  private:
613   RepeatingClosure closure_;
614 };
615 
616 // Deduction guide so the compiler can choose the correct specialisation of
617 // InvokeFuture.
618 template <typename... Types>
619 InvokeFuture(TestFuture<Types...>&) -> InvokeFuture<Types...>;
620 
621 }  // namespace base::test
622 
623 #endif  // BASE_TEST_TEST_FUTURE_H_
624