gmock_callback_support.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright (c) 2012 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_GMOCK_CALLBACK_SUPPORT_H_
  5. #define BASE_TEST_GMOCK_CALLBACK_SUPPORT_H_
  6. #include <functional>
  7. #include <tuple>
  8. #include <type_traits>
  9. #include <utility>
  10. #include "base/callback.h"
  11. #include "base/memory/ref_counted.h"
  12. #include "base/memory/scoped_refptr.h"
  13. #include "testing/gmock/include/gmock/gmock.h"
  14. namespace base {
  15. namespace internal {
  16. // Small helper to get the `I`th argument.
  17. template <size_t I, typename... Args>
  18. decltype(auto) get(Args&&... args) {
  19. return std::get<I>(std::forward_as_tuple(std::forward<Args>(args)...));
  20. }
  21. // Invokes `cb` with the arguments stored in `tuple`. Both `cb` and `tuple` are
  22. // perfectly forwarded, allowing callers to specify whether they should be
  23. // passed by move or copy.
  24. template <typename Callback, typename Tuple, size_t... Is>
  25. decltype(auto) RunImpl(Callback&& cb,
  26. Tuple&& tuple,
  27. std::index_sequence<Is...>) {
  28. return std::forward<Callback>(cb).Run(
  29. std::get<Is>(std::forward<Tuple>(tuple))...);
  30. }
  31. // Invokes `cb` with the arguments stored in `tuple`. Both `cb` and `tuple` are
  32. // perfectly forwarded, allowing callers to specify whether they should be
  33. // passed by move or copy. Needs to dispatch to the three arguments version to
  34. // be able to construct a `std::index_sequence` of the corresponding size.
  35. template <typename Callback, typename Tuple>
  36. decltype(auto) RunImpl(Callback&& cb, Tuple&& tuple) {
  37. return RunImpl(std::forward<Callback>(cb), std::forward<Tuple>(tuple),
  38. std::make_index_sequence<
  39. std::tuple_size<std::remove_reference_t<Tuple>>::value>());
  40. }
  41. // Invoked when the arguments to a OnceCallback are copy constructible. In this
  42. // case the returned lambda will pass the arguments to the provided callback by
  43. // copy, allowing it to be used multiple times.
  44. template <size_t I,
  45. typename Tuple,
  46. std::enable_if_t<std::is_copy_constructible<Tuple>::value, int> = 0>
  47. auto RunOnceCallbackImpl(Tuple&& tuple) {
  48. return [tuple = std::move(tuple)](auto&&... args) -> decltype(auto) {
  49. return RunImpl(std::move(internal::get<I>(args...)), tuple);
  50. };
  51. }
  52. // Invoked when the arguments to a OnceCallback are not copy constructible. In
  53. // this case the returned lambda will pass the arguments to the provided
  54. // callback by move, allowing it to be only used once.
  55. template <size_t I,
  56. typename Tuple,
  57. std::enable_if_t<!std::is_copy_constructible<Tuple>::value, int> = 0>
  58. auto RunOnceCallbackImpl(Tuple&& tuple) {
  59. // Mock actions need to be copyable, but `tuple` is not. Wrap it in in a
  60. // `scoped_refptr` to allow it to be copied.
  61. auto tuple_ptr =
  62. base::MakeRefCounted<base::RefCountedData<Tuple>>(std::move(tuple));
  63. return [tuple_ptr =
  64. std::move(tuple_ptr)](auto&&... args) mutable -> decltype(auto) {
  65. // Since running the action will move out of the arguments, `tuple_ptr` is
  66. // nulled out, so that attempting to run it twice will result in a run-time
  67. // crash.
  68. return RunImpl(std::move(internal::get<I>(args...)),
  69. std::move(std::exchange(tuple_ptr, nullptr)->data));
  70. };
  71. }
  72. // Invoked for RepeatingCallbacks. In this case the returned lambda will pass
  73. // the arguments to the provided callback by copy, allowing it to be used
  74. // multiple times. Move-only arguments are not supported.
  75. template <size_t I, typename Tuple>
  76. auto RunRepeatingCallbackImpl(Tuple&& tuple) {
  77. return [tuple = std::move(tuple)](auto&&... args) -> decltype(auto) {
  78. return RunImpl(internal::get<I>(args...), tuple);
  79. };
  80. }
  81. } // namespace internal
  82. namespace test {
  83. // Matchers for base::{Once,Repeating}Callback and
  84. // base::{Once,Repeating}Closure.
  85. MATCHER(IsNullCallback, "a null callback") {
  86. return (arg.is_null());
  87. }
  88. MATCHER(IsNotNullCallback, "a non-null callback") {
  89. return (!arg.is_null());
  90. }
  91. // The Run[Once]Closure() action invokes the Run() method on the closure
  92. // provided when the action is constructed. Function arguments passed when the
  93. // action is run will be ignored.
  94. ACTION_P(RunClosure, closure) {
  95. closure.Run();
  96. }
  97. // This action can be invoked at most once. Any further invocation will trigger
  98. // a CHECK failure.
  99. inline auto RunOnceClosure(base::OnceClosure cb) {
  100. // Mock actions need to be copyable, but OnceClosure is not. Wrap the closure
  101. // in a base::RefCountedData<> to allow it to be copied. An alternative would
  102. // be to use AdaptCallbackForRepeating(), but that allows the closure to be
  103. // run more than once and silently ignores any invocation after the first.
  104. // Since this is for use by tests, it's better to crash or CHECK-fail and
  105. // surface the incorrect usage, rather than have a silent unexpected success.
  106. using RefCountedOnceClosure = base::RefCountedData<base::OnceClosure>;
  107. scoped_refptr<RefCountedOnceClosure> copyable_cb =
  108. base::MakeRefCounted<RefCountedOnceClosure>(std::move(cb));
  109. return [copyable_cb](auto&&...) {
  110. CHECK(copyable_cb->data);
  111. std::move(copyable_cb->data).Run();
  112. };
  113. }
  114. // The Run[Once]Closure<N>() action invokes the Run() method on the N-th
  115. // (0-based) argument of the mock function.
  116. template <size_t I>
  117. auto RunClosure() {
  118. return [](auto&&... args) -> decltype(auto) {
  119. return internal::get<I>(args...).Run();
  120. };
  121. }
  122. template <size_t I>
  123. auto RunOnceClosure() {
  124. return [](auto&&... args) -> decltype(auto) {
  125. return std::move(internal::get<I>(args...)).Run();
  126. };
  127. }
  128. // The Run[Once]Callback<N>(p1, p2, ..., p_k) action invokes the Run() method on
  129. // the N-th (0-based) argument of the mock function, with arguments p1, p2, ...,
  130. // p_k.
  131. //
  132. // Notes:
  133. //
  134. // 1. The arguments are passed by value by default. If you need to
  135. // pass an argument by reference, wrap it inside ByRef(). For example,
  136. //
  137. // RunCallback<1>(5, string("Hello"), ByRef(foo))
  138. //
  139. // passes 5 and string("Hello") by value, and passes foo by reference.
  140. //
  141. // 2. If the callback takes an argument by reference but ByRef() is
  142. // not used, it will receive the reference to a copy of the value,
  143. // instead of the original value. For example, when the 0-th
  144. // argument of the callback takes a const string&, the action
  145. //
  146. // RunCallback<0>(string("Hello"))
  147. //
  148. // makes a copy of the temporary string("Hello") object and passes a
  149. // reference of the copy, instead of the original temporary object,
  150. // to the callback. This makes it easy for a user to define an
  151. // RunCallback action from temporary values and have it performed later.
  152. //
  153. // 3. In order to facilitate re-use of the `RunOnceCallback()` action,
  154. // the arguments are copied during each run if possible. If this can't
  155. // be done (e.g. one of the arguments is move-only), the arguments will
  156. // be passed by move. However, since moving potentially invalidates the
  157. // arguments, the resulting action is only allowed to run once in this
  158. // case. Attempting to run it twice will result in a runtime crash.
  159. // Using move-only arguments with `RunCallback()` is not supported.
  160. template <size_t I, typename... RunArgs>
  161. auto RunOnceCallback(RunArgs&&... run_args) {
  162. return internal::RunOnceCallbackImpl<I>(
  163. std::make_tuple(std::forward<RunArgs>(run_args)...));
  164. }
  165. template <size_t I, typename... RunArgs>
  166. auto RunCallback(RunArgs&&... run_args) {
  167. return internal::RunRepeatingCallbackImpl<I>(
  168. std::make_tuple(std::forward<RunArgs>(run_args)...));
  169. }
  170. } // namespace test
  171. } // namespace base
  172. #endif // BASE_TEST_GMOCK_CALLBACK_SUPPORT_H_