mock_helpers.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. //
  2. // Copyright 2019 The Abseil Authors.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // https://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #ifndef ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
  16. #define ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
  17. #include <tuple>
  18. #include <type_traits>
  19. #include "absl/base/internal/fast_type_id.h"
  20. #include "absl/types/optional.h"
  21. namespace absl {
  22. ABSL_NAMESPACE_BEGIN
  23. namespace random_internal {
  24. // MockHelpers works in conjunction with MockOverloadSet, MockingBitGen, and
  25. // BitGenRef to enable the mocking capability for absl distribution functions.
  26. //
  27. // MockingBitGen registers mocks based on the typeid of a mock signature, KeyT,
  28. // which is used to generate a unique id.
  29. //
  30. // KeyT is a signature of the form:
  31. // result_type(discriminator_type, std::tuple<args...>)
  32. // The mocked function signature will be composed from KeyT as:
  33. // result_type(args...)
  34. //
  35. class MockHelpers {
  36. using IdType = ::absl::base_internal::FastTypeIdType;
  37. // Given a key signature type used to index the mock, extract the components.
  38. // KeyT is expected to have the form:
  39. // result_type(discriminator_type, arg_tuple_type)
  40. template <typename KeyT>
  41. struct KeySignature;
  42. template <typename ResultT, typename DiscriminatorT, typename ArgTupleT>
  43. struct KeySignature<ResultT(DiscriminatorT, ArgTupleT)> {
  44. using result_type = ResultT;
  45. using discriminator_type = DiscriminatorT;
  46. using arg_tuple_type = ArgTupleT;
  47. };
  48. // Detector for InvokeMock.
  49. template <class T>
  50. using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
  51. std::declval<IdType>(), std::declval<void*>(), std::declval<void*>()));
  52. // Empty implementation of InvokeMock.
  53. template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
  54. typename... Args>
  55. static absl::optional<ReturnT> InvokeMockImpl(char, URBG*, Args&&...) {
  56. return absl::nullopt;
  57. }
  58. // Non-empty implementation of InvokeMock.
  59. template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
  60. typename = invoke_mock_t<URBG>, typename... Args>
  61. static absl::optional<ReturnT> InvokeMockImpl(int, URBG* urbg,
  62. Args&&... args) {
  63. ArgTupleT arg_tuple(std::forward<Args>(args)...);
  64. ReturnT result;
  65. if (urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
  66. &result)) {
  67. return result;
  68. }
  69. return absl::nullopt;
  70. }
  71. public:
  72. // InvokeMock is private; this provides access for some specialized use cases.
  73. template <typename URBG>
  74. static inline bool PrivateInvokeMock(URBG* urbg, IdType type,
  75. void* args_tuple, void* result) {
  76. return urbg->InvokeMock(type, args_tuple, result);
  77. }
  78. // Invoke a mock for the KeyT (may or may not be a signature).
  79. //
  80. // KeyT is used to generate a typeid-based lookup key for the mock.
  81. // KeyT is a signature of the form:
  82. // result_type(discriminator_type, std::tuple<args...>)
  83. // The mocked function signature will be composed from KeyT as:
  84. // result_type(args...)
  85. //
  86. // An instance of arg_tuple_type must be constructable from Args..., since
  87. // the underlying mechanism requires a pointer to an argument tuple.
  88. template <typename KeyT, typename URBG, typename... Args>
  89. static auto MaybeInvokeMock(URBG* urbg, Args&&... args)
  90. -> absl::optional<typename KeySignature<KeyT>::result_type> {
  91. // Use function overloading to dispatch to the implemenation since
  92. // more modern patterns (e.g. require + constexpr) are not supported in all
  93. // compiler configurations.
  94. return InvokeMockImpl<KeyT, typename KeySignature<KeyT>::result_type,
  95. typename KeySignature<KeyT>::arg_tuple_type, URBG>(
  96. 0, urbg, std::forward<Args>(args)...);
  97. }
  98. // Acquire a mock for the KeyT (may or may not be a signature).
  99. //
  100. // KeyT is used to generate a typeid-based lookup for the mock.
  101. // KeyT is a signature of the form:
  102. // result_type(discriminator_type, std::tuple<args...>)
  103. // The mocked function signature will be composed from KeyT as:
  104. // result_type(args...)
  105. template <typename KeyT, typename MockURBG>
  106. static auto MockFor(MockURBG& m)
  107. -> decltype(m.template RegisterMock<
  108. typename KeySignature<KeyT>::result_type,
  109. typename KeySignature<KeyT>::arg_tuple_type>(
  110. m, std::declval<IdType>())) {
  111. return m.template RegisterMock<typename KeySignature<KeyT>::result_type,
  112. typename KeySignature<KeyT>::arg_tuple_type>(
  113. m, ::absl::base_internal::FastTypeId<KeyT>());
  114. }
  115. };
  116. } // namespace random_internal
  117. ABSL_NAMESPACE_END
  118. } // namespace absl
  119. #endif // ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_