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