test_future.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_TEST_TEST_FUTURE_H_
  5. #define BASE_TEST_TEST_FUTURE_H_
  6. #include <memory>
  7. #include <string>
  8. #include "base/callback_forward.h"
  9. #include "base/check.h"
  10. #include "base/memory/weak_ptr.h"
  11. #include "base/run_loop.h"
  12. #include "base/sequence_checker.h"
  13. #include "base/test/bind.h"
  14. #include "base/test/test_future_internal.h"
  15. #include "base/thread_annotations.h"
  16. #include "third_party/abseil-cpp/absl/types/optional.h"
  17. namespace base::test {
  18. // Helper class to test code that returns its result(s) asynchronously through a
  19. // callback:
  20. //
  21. // - Pass the callback provided by TestFuture::GetCallback() to the code
  22. // under test.
  23. // - Wait for the callback to be invoked by calling TestFuture::Wait(), or
  24. // TestFuture::Get() to access the value(s) passed to the callback.
  25. //
  26. // If the callback takes multiple arguments, use TestFuture::Get<0>() to access
  27. // the value of the first argument, TestFuture::Get<1>() to access the value of
  28. // the second argument, and so on.
  29. //
  30. // If for any reason you can't use TestFuture::GetCallback(), you can use
  31. // TestFuture::SetValue() to directly set the value. This method must be called
  32. // from the main sequence.
  33. //
  34. // Finally, TestFuture::Take() is similar to TestFuture::Get() but it will
  35. // move the result out, which can be helpful when testing a move-only class.
  36. //
  37. // Example usage:
  38. //
  39. // TEST_F(MyTestFixture, MyTest) {
  40. // TestFuture<ResultType> future;
  41. //
  42. // object_under_test.DoSomethingAsync(future.GetCallback());
  43. //
  44. // const ResultType& actual_result = future.Get();
  45. //
  46. // // When you come here, DoSomethingAsync has finished and |actual_result|
  47. // // contains the result passed to the callback.
  48. // }
  49. //
  50. // Example if the callback has 2 arguments:
  51. //
  52. // TEST_F(MyTestFixture, MyTest) {
  53. // TestFuture<int, std::string> future;
  54. //
  55. // object_under_test.DoSomethingAsync(future.GetCallback());
  56. //
  57. // int first_argument = future.Get<0>();
  58. // const std::string & second_argument = future.Get<1>();
  59. // }
  60. //
  61. // Or an example using TestFuture::Wait():
  62. //
  63. // TEST_F(MyTestFixture, MyWaitTest) {
  64. // TestFuture<ResultType> future;
  65. //
  66. // object_under_test.DoSomethingAsync(future.GetCallback());
  67. //
  68. // // Optional. The Get() call below will also wait until the value
  69. // // arrives, but this explicit call to Wait() can be useful if you want to
  70. // // add extra information.
  71. // ASSERT_TRUE(future.Wait()) << "Detailed error message";
  72. //
  73. // const ResultType& actual_result = future.Get();
  74. // }
  75. //
  76. // All access to this class must be made from the same sequence.
  77. template <typename... Types>
  78. class TestFuture {
  79. public:
  80. using TupleType = std::tuple<std::decay_t<Types>...>;
  81. using FirstType = typename std::tuple_element<0, TupleType>::type;
  82. TestFuture() = default;
  83. TestFuture(const TestFuture&) = delete;
  84. TestFuture& operator=(const TestFuture&) = delete;
  85. ~TestFuture() = default;
  86. // Wait for the value to arrive.
  87. //
  88. // Returns true if the value arrived, or false if a timeout happens.
  89. //
  90. // Directly calling Wait() is not required as Get()/Take() will also wait for
  91. // the value to arrive, however you can use a direct call to Wait() to
  92. // improve the error reported:
  93. //
  94. // ASSERT_TRUE(queue.Wait()) << "Detailed error message";
  95. //
  96. [[nodiscard]] bool Wait() {
  97. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  98. if (values_)
  99. return true;
  100. run_loop_.Run();
  101. return IsReady();
  102. }
  103. // Returns true if the value has arrived.
  104. bool IsReady() const {
  105. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  106. return values_.has_value();
  107. }
  108. // Wait for the value to arrive, and return the I-th value.
  109. //
  110. // Will DCHECK if a timeout happens.
  111. //
  112. // Example usage:
  113. //
  114. // TestFuture<int, std::string> future;
  115. // int first = future.Get<0>();
  116. // std::string second = future.Get<1>();
  117. //
  118. template <std::size_t I>
  119. const typename std::tuple_element<I, TupleType>::type& Get() {
  120. return std::get<I>(GetTuple());
  121. }
  122. // Returns a callback that when invoked will store all the argument values,
  123. // and unblock any waiters.
  124. // Templated so you can specify how you need the arguments to be passed -
  125. // const, reference, .... Defaults to simply |Types...|.
  126. //
  127. // Example usage:
  128. //
  129. // TestFuture<int, std::string> future;
  130. //
  131. // // returns base::OnceCallback<void(int, std::string)>
  132. // future.GetCallback();
  133. //
  134. // // returns base::OnceCallback<void(int, const std::string&)>
  135. // future.GetCallback<int, const std::string&>();
  136. //
  137. template <typename... CallbackArgumentsTypes>
  138. base::OnceCallback<void(CallbackArgumentsTypes...)> GetCallback() {
  139. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  140. return base::BindOnce(
  141. [](WeakPtr<TestFuture<Types...>> future,
  142. CallbackArgumentsTypes... values) {
  143. if (future)
  144. future->SetValue(std::forward<CallbackArgumentsTypes>(values)...);
  145. },
  146. weak_ptr_factory_.GetWeakPtr());
  147. }
  148. base::OnceCallback<void(Types...)> GetCallback() {
  149. return GetCallback<Types...>();
  150. }
  151. // Set the value of the future.
  152. // This will unblock any pending Wait() or Get() call.
  153. // This can only be called once.
  154. void SetValue(Types... values) {
  155. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  156. DCHECK(!values_.has_value())
  157. << "The value of a TestFuture can only be set once. If you need to "
  158. "handle an ordered stream of result values, use "
  159. "|base::test::RepeatingTestFuture|.";
  160. values_ = std::make_tuple(std::forward<Types>(values)...);
  161. run_loop_.Quit();
  162. }
  163. //////////////////////////////////////////////////////////////////////////////
  164. // Accessor methods only available if the future holds a single value.
  165. //////////////////////////////////////////////////////////////////////////////
  166. // Wait for the value to arrive, and returns its value.
  167. //
  168. // Will DCHECK if a timeout happens.
  169. template <typename T = TupleType, internal::EnableIfSingleValue<T> = true>
  170. [[nodiscard]] const FirstType& Get() {
  171. return std::get<0>(GetTuple());
  172. }
  173. // Wait for the value to arrive, and move it out.
  174. //
  175. // Will DCHECK if a timeout happens.
  176. template <typename T = TupleType, internal::EnableIfSingleValue<T> = true>
  177. [[nodiscard]] FirstType Take() {
  178. return std::get<0>(TakeTuple());
  179. }
  180. //////////////////////////////////////////////////////////////////////////////
  181. // Accessor methods only available if the future holds multiple values.
  182. //////////////////////////////////////////////////////////////////////////////
  183. // Wait for the values to arrive, and returns a tuple with the values.
  184. //
  185. // Will DCHECK if a timeout happens.
  186. template <typename T = TupleType, internal::EnableIfMultiValue<T> = true>
  187. [[nodiscard]] const TupleType& Get() {
  188. return GetTuple();
  189. }
  190. // Wait for the values to arrive, and move a tuple with the values out.
  191. //
  192. // Will DCHECK if a timeout happens.
  193. template <typename T = TupleType, internal::EnableIfMultiValue<T> = true>
  194. [[nodiscard]] TupleType Take() {
  195. return TakeTuple();
  196. }
  197. private:
  198. [[nodiscard]] const TupleType& GetTuple() {
  199. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  200. bool success = Wait();
  201. DCHECK(success) << "Waiting for value timed out.";
  202. return values_.value();
  203. }
  204. [[nodiscard]] TupleType TakeTuple() {
  205. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  206. bool success = Wait();
  207. DCHECK(success) << "Waiting for value timed out.";
  208. return std::move(values_.value());
  209. }
  210. SEQUENCE_CHECKER(sequence_checker_);
  211. base::RunLoop run_loop_ GUARDED_BY_CONTEXT(sequence_checker_);
  212. absl::optional<TupleType> values_ GUARDED_BY_CONTEXT(sequence_checker_);
  213. base::WeakPtrFactory<TestFuture<Types...>> weak_ptr_factory_{this};
  214. };
  215. } // namespace base::test
  216. #endif // BASE_TEST_TEST_FUTURE_H_