1*9356374aSAndroid Build Coastguard Worker // Copyright 2018 The Abseil Authors. 2*9356374aSAndroid Build Coastguard Worker // 3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*9356374aSAndroid Build Coastguard Worker // 7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 8*9356374aSAndroid Build Coastguard Worker // 9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*9356374aSAndroid Build Coastguard Worker // limitations under the License. 14*9356374aSAndroid Build Coastguard Worker // 15*9356374aSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------- 16*9356374aSAndroid Build Coastguard Worker // mocking_bit_gen.h 17*9356374aSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------- 18*9356374aSAndroid Build Coastguard Worker // 19*9356374aSAndroid Build Coastguard Worker // This file includes an `absl::MockingBitGen` class to use as a mock within the 20*9356374aSAndroid Build Coastguard Worker // Googletest testing framework. Such a mock is useful to provide deterministic 21*9356374aSAndroid Build Coastguard Worker // values as return values within (otherwise random) Abseil distribution 22*9356374aSAndroid Build Coastguard Worker // functions. Such determinism within a mock is useful within testing frameworks 23*9356374aSAndroid Build Coastguard Worker // to test otherwise indeterminate APIs. 24*9356374aSAndroid Build Coastguard Worker // 25*9356374aSAndroid Build Coastguard Worker // More information about the Googletest testing framework is available at 26*9356374aSAndroid Build Coastguard Worker // https://github.com/google/googletest 27*9356374aSAndroid Build Coastguard Worker 28*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_RANDOM_MOCKING_BIT_GEN_H_ 29*9356374aSAndroid Build Coastguard Worker #define ABSL_RANDOM_MOCKING_BIT_GEN_H_ 30*9356374aSAndroid Build Coastguard Worker 31*9356374aSAndroid Build Coastguard Worker #include <memory> 32*9356374aSAndroid Build Coastguard Worker #include <tuple> 33*9356374aSAndroid Build Coastguard Worker #include <type_traits> 34*9356374aSAndroid Build Coastguard Worker #include <utility> 35*9356374aSAndroid Build Coastguard Worker 36*9356374aSAndroid Build Coastguard Worker #include "gmock/gmock.h" 37*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h" 38*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h" 39*9356374aSAndroid Build Coastguard Worker #include "absl/base/internal/fast_type_id.h" 40*9356374aSAndroid Build Coastguard Worker #include "absl/container/flat_hash_map.h" 41*9356374aSAndroid Build Coastguard Worker #include "absl/meta/type_traits.h" 42*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/mock_helpers.h" 43*9356374aSAndroid Build Coastguard Worker #include "absl/random/random.h" 44*9356374aSAndroid Build Coastguard Worker #include "absl/utility/utility.h" 45*9356374aSAndroid Build Coastguard Worker 46*9356374aSAndroid Build Coastguard Worker namespace absl { 47*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN 48*9356374aSAndroid Build Coastguard Worker 49*9356374aSAndroid Build Coastguard Worker class BitGenRef; 50*9356374aSAndroid Build Coastguard Worker 51*9356374aSAndroid Build Coastguard Worker namespace random_internal { 52*9356374aSAndroid Build Coastguard Worker template <typename> 53*9356374aSAndroid Build Coastguard Worker struct DistributionCaller; 54*9356374aSAndroid Build Coastguard Worker class MockHelpers; 55*9356374aSAndroid Build Coastguard Worker 56*9356374aSAndroid Build Coastguard Worker // Implements MockingBitGen with an option to turn on extra validation. 57*9356374aSAndroid Build Coastguard Worker template <bool EnableValidation> 58*9356374aSAndroid Build Coastguard Worker class MockingBitGenImpl { 59*9356374aSAndroid Build Coastguard Worker public: 60*9356374aSAndroid Build Coastguard Worker MockingBitGenImpl() = default; 61*9356374aSAndroid Build Coastguard Worker ~MockingBitGenImpl() = default; 62*9356374aSAndroid Build Coastguard Worker 63*9356374aSAndroid Build Coastguard Worker // URBG interface 64*9356374aSAndroid Build Coastguard Worker using result_type = absl::BitGen::result_type; 65*9356374aSAndroid Build Coastguard Worker result_type(min)66*9356374aSAndroid Build Coastguard Worker static constexpr result_type(min)() { return (absl::BitGen::min)(); } result_type(max)67*9356374aSAndroid Build Coastguard Worker static constexpr result_type(max)() { return (absl::BitGen::max)(); } operator()68*9356374aSAndroid Build Coastguard Worker result_type operator()() { return gen_(); } 69*9356374aSAndroid Build Coastguard Worker 70*9356374aSAndroid Build Coastguard Worker private: 71*9356374aSAndroid Build Coastguard Worker // GetMockFnType returns the testing::MockFunction for a result and tuple. 72*9356374aSAndroid Build Coastguard Worker // This method only exists for type deduction and is otherwise unimplemented. 73*9356374aSAndroid Build Coastguard Worker template <typename ResultT, typename... Args> 74*9356374aSAndroid Build Coastguard Worker static auto GetMockFnType(ResultT, std::tuple<Args...>) 75*9356374aSAndroid Build Coastguard Worker -> ::testing::MockFunction<ResultT(Args...)>; 76*9356374aSAndroid Build Coastguard Worker 77*9356374aSAndroid Build Coastguard Worker // MockFnCaller is a helper method for use with absl::apply to 78*9356374aSAndroid Build Coastguard Worker // apply an ArgTupleT to a compatible MockFunction. 79*9356374aSAndroid Build Coastguard Worker // NOTE: MockFnCaller is essentially equivalent to the lambda: 80*9356374aSAndroid Build Coastguard Worker // [fn](auto... args) { return fn->Call(std::move(args)...)} 81*9356374aSAndroid Build Coastguard Worker // however that fails to build on some supported platforms. 82*9356374aSAndroid Build Coastguard Worker template <typename MockFnType, typename ValidatorT, typename ResultT, 83*9356374aSAndroid Build Coastguard Worker typename Tuple> 84*9356374aSAndroid Build Coastguard Worker struct MockFnCaller; 85*9356374aSAndroid Build Coastguard Worker 86*9356374aSAndroid Build Coastguard Worker // specialization for std::tuple. 87*9356374aSAndroid Build Coastguard Worker template <typename MockFnType, typename ValidatorT, typename ResultT, 88*9356374aSAndroid Build Coastguard Worker typename... Args> 89*9356374aSAndroid Build Coastguard Worker struct MockFnCaller<MockFnType, ValidatorT, ResultT, std::tuple<Args...>> { 90*9356374aSAndroid Build Coastguard Worker MockFnType* fn; 91*9356374aSAndroid Build Coastguard Worker inline ResultT operator()(Args... args) { 92*9356374aSAndroid Build Coastguard Worker ResultT result = fn->Call(args...); 93*9356374aSAndroid Build Coastguard Worker ValidatorT::Validate(result, args...); 94*9356374aSAndroid Build Coastguard Worker return result; 95*9356374aSAndroid Build Coastguard Worker } 96*9356374aSAndroid Build Coastguard Worker }; 97*9356374aSAndroid Build Coastguard Worker 98*9356374aSAndroid Build Coastguard Worker // FunctionHolder owns a particular ::testing::MockFunction associated with 99*9356374aSAndroid Build Coastguard Worker // a mocked type signature, and implement the type-erased Apply call, which 100*9356374aSAndroid Build Coastguard Worker // applies type-erased arguments to the mock. 101*9356374aSAndroid Build Coastguard Worker class FunctionHolder { 102*9356374aSAndroid Build Coastguard Worker public: 103*9356374aSAndroid Build Coastguard Worker virtual ~FunctionHolder() = default; 104*9356374aSAndroid Build Coastguard Worker 105*9356374aSAndroid Build Coastguard Worker // Call is a dispatch function which converts the 106*9356374aSAndroid Build Coastguard Worker // generic type-erased parameters into a specific mock invocation call. 107*9356374aSAndroid Build Coastguard Worker virtual void Apply(/*ArgTupleT*/ void* args_tuple, 108*9356374aSAndroid Build Coastguard Worker /*ResultT*/ void* result) = 0; 109*9356374aSAndroid Build Coastguard Worker }; 110*9356374aSAndroid Build Coastguard Worker 111*9356374aSAndroid Build Coastguard Worker template <typename MockFnType, typename ValidatorT, typename ResultT, 112*9356374aSAndroid Build Coastguard Worker typename ArgTupleT> 113*9356374aSAndroid Build Coastguard Worker class FunctionHolderImpl final : public FunctionHolder { 114*9356374aSAndroid Build Coastguard Worker public: 115*9356374aSAndroid Build Coastguard Worker void Apply(void* args_tuple, void* result) final { 116*9356374aSAndroid Build Coastguard Worker // Requires tuple_args to point to a ArgTupleT, which is a 117*9356374aSAndroid Build Coastguard Worker // std::tuple<Args...> used to invoke the mock function. Requires result 118*9356374aSAndroid Build Coastguard Worker // to point to a ResultT, which is the result of the call. 119*9356374aSAndroid Build Coastguard Worker *static_cast<ResultT*>(result) = absl::apply( 120*9356374aSAndroid Build Coastguard Worker MockFnCaller<MockFnType, ValidatorT, ResultT, ArgTupleT>{&mock_fn_}, 121*9356374aSAndroid Build Coastguard Worker *static_cast<ArgTupleT*>(args_tuple)); 122*9356374aSAndroid Build Coastguard Worker } 123*9356374aSAndroid Build Coastguard Worker 124*9356374aSAndroid Build Coastguard Worker MockFnType mock_fn_; 125*9356374aSAndroid Build Coastguard Worker }; 126*9356374aSAndroid Build Coastguard Worker 127*9356374aSAndroid Build Coastguard Worker // MockingBitGen::RegisterMock 128*9356374aSAndroid Build Coastguard Worker // 129*9356374aSAndroid Build Coastguard Worker // RegisterMock<ResultT, ArgTupleT>(FastTypeIdType) is the main extension 130*9356374aSAndroid Build Coastguard Worker // point for extending the MockingBitGen framework. It provides a mechanism to 131*9356374aSAndroid Build Coastguard Worker // install a mock expectation for a function like ResultT(Args...) keyed by 132*9356374aSAndroid Build Coastguard Worker // type_idex onto the MockingBitGen context. The key is that the type_index 133*9356374aSAndroid Build Coastguard Worker // used to register must match the type index used to call the mock. 134*9356374aSAndroid Build Coastguard Worker // 135*9356374aSAndroid Build Coastguard Worker // The returned MockFunction<...> type can be used to setup additional 136*9356374aSAndroid Build Coastguard Worker // distribution parameters of the expectation. 137*9356374aSAndroid Build Coastguard Worker template <typename ResultT, typename ArgTupleT, typename SelfT, 138*9356374aSAndroid Build Coastguard Worker typename ValidatorT> 139*9356374aSAndroid Build Coastguard Worker auto RegisterMock(SelfT&, base_internal::FastTypeIdType type, ValidatorT) 140*9356374aSAndroid Build Coastguard Worker -> decltype(GetMockFnType(std::declval<ResultT>(), 141*9356374aSAndroid Build Coastguard Worker std::declval<ArgTupleT>()))& { 142*9356374aSAndroid Build Coastguard Worker using ActualValidatorT = 143*9356374aSAndroid Build Coastguard Worker std::conditional_t<EnableValidation, ValidatorT, NoOpValidator>; 144*9356374aSAndroid Build Coastguard Worker using MockFnType = decltype(GetMockFnType(std::declval<ResultT>(), 145*9356374aSAndroid Build Coastguard Worker std::declval<ArgTupleT>())); 146*9356374aSAndroid Build Coastguard Worker 147*9356374aSAndroid Build Coastguard Worker using WrappedFnType = absl::conditional_t< 148*9356374aSAndroid Build Coastguard Worker std::is_same<SelfT, ::testing::NiceMock<MockingBitGenImpl>>::value, 149*9356374aSAndroid Build Coastguard Worker ::testing::NiceMock<MockFnType>, 150*9356374aSAndroid Build Coastguard Worker absl::conditional_t< 151*9356374aSAndroid Build Coastguard Worker std::is_same<SelfT, ::testing::NaggyMock<MockingBitGenImpl>>::value, 152*9356374aSAndroid Build Coastguard Worker ::testing::NaggyMock<MockFnType>, 153*9356374aSAndroid Build Coastguard Worker absl::conditional_t< 154*9356374aSAndroid Build Coastguard Worker std::is_same<SelfT, 155*9356374aSAndroid Build Coastguard Worker ::testing::StrictMock<MockingBitGenImpl>>::value, 156*9356374aSAndroid Build Coastguard Worker ::testing::StrictMock<MockFnType>, MockFnType>>>; 157*9356374aSAndroid Build Coastguard Worker 158*9356374aSAndroid Build Coastguard Worker using ImplT = 159*9356374aSAndroid Build Coastguard Worker FunctionHolderImpl<WrappedFnType, ActualValidatorT, ResultT, ArgTupleT>; 160*9356374aSAndroid Build Coastguard Worker auto& mock = mocks_[type]; 161*9356374aSAndroid Build Coastguard Worker if (!mock) { 162*9356374aSAndroid Build Coastguard Worker mock = absl::make_unique<ImplT>(); 163*9356374aSAndroid Build Coastguard Worker } 164*9356374aSAndroid Build Coastguard Worker return static_cast<ImplT*>(mock.get())->mock_fn_; 165*9356374aSAndroid Build Coastguard Worker } 166*9356374aSAndroid Build Coastguard Worker 167*9356374aSAndroid Build Coastguard Worker // MockingBitGen::InvokeMock 168*9356374aSAndroid Build Coastguard Worker // 169*9356374aSAndroid Build Coastguard Worker // InvokeMock(FastTypeIdType, args, result) is the entrypoint for invoking 170*9356374aSAndroid Build Coastguard Worker // mocks registered on MockingBitGen. 171*9356374aSAndroid Build Coastguard Worker // 172*9356374aSAndroid Build Coastguard Worker // When no mocks are registered on the provided FastTypeIdType, returns false. 173*9356374aSAndroid Build Coastguard Worker // Otherwise attempts to invoke the mock function ResultT(Args...) that 174*9356374aSAndroid Build Coastguard Worker // was previously registered via the type_index. 175*9356374aSAndroid Build Coastguard Worker // Requires tuple_args to point to a ArgTupleT, which is a std::tuple<Args...> 176*9356374aSAndroid Build Coastguard Worker // used to invoke the mock function. 177*9356374aSAndroid Build Coastguard Worker // Requires result to point to a ResultT, which is the result of the call. 178*9356374aSAndroid Build Coastguard Worker inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple, 179*9356374aSAndroid Build Coastguard Worker void* result) { 180*9356374aSAndroid Build Coastguard Worker // Trigger a mock, if there exists one that matches `param`. 181*9356374aSAndroid Build Coastguard Worker auto it = mocks_.find(type); 182*9356374aSAndroid Build Coastguard Worker if (it == mocks_.end()) return false; 183*9356374aSAndroid Build Coastguard Worker it->second->Apply(args_tuple, result); 184*9356374aSAndroid Build Coastguard Worker return true; 185*9356374aSAndroid Build Coastguard Worker } 186*9356374aSAndroid Build Coastguard Worker 187*9356374aSAndroid Build Coastguard Worker absl::flat_hash_map<base_internal::FastTypeIdType, 188*9356374aSAndroid Build Coastguard Worker std::unique_ptr<FunctionHolder>> 189*9356374aSAndroid Build Coastguard Worker mocks_; 190*9356374aSAndroid Build Coastguard Worker absl::BitGen gen_; 191*9356374aSAndroid Build Coastguard Worker 192*9356374aSAndroid Build Coastguard Worker template <typename> 193*9356374aSAndroid Build Coastguard Worker friend struct ::absl::random_internal::DistributionCaller; // for InvokeMock 194*9356374aSAndroid Build Coastguard Worker friend class ::absl::BitGenRef; // for InvokeMock 195*9356374aSAndroid Build Coastguard Worker friend class ::absl::random_internal::MockHelpers; // for RegisterMock, 196*9356374aSAndroid Build Coastguard Worker // InvokeMock 197*9356374aSAndroid Build Coastguard Worker }; 198*9356374aSAndroid Build Coastguard Worker 199*9356374aSAndroid Build Coastguard Worker } // namespace random_internal 200*9356374aSAndroid Build Coastguard Worker 201*9356374aSAndroid Build Coastguard Worker // MockingBitGen 202*9356374aSAndroid Build Coastguard Worker // 203*9356374aSAndroid Build Coastguard Worker // `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class 204*9356374aSAndroid Build Coastguard Worker // which can act in place of an `absl::BitGen` URBG within tests using the 205*9356374aSAndroid Build Coastguard Worker // Googletest testing framework. 206*9356374aSAndroid Build Coastguard Worker // 207*9356374aSAndroid Build Coastguard Worker // Usage: 208*9356374aSAndroid Build Coastguard Worker // 209*9356374aSAndroid Build Coastguard Worker // Use an `absl::MockingBitGen` along with a mock distribution object (within 210*9356374aSAndroid Build Coastguard Worker // mock_distributions.h) inside Googletest constructs such as ON_CALL(), 211*9356374aSAndroid Build Coastguard Worker // EXPECT_TRUE(), etc. to produce deterministic results conforming to the 212*9356374aSAndroid Build Coastguard Worker // distribution's API contract. 213*9356374aSAndroid Build Coastguard Worker // 214*9356374aSAndroid Build Coastguard Worker // Example: 215*9356374aSAndroid Build Coastguard Worker // 216*9356374aSAndroid Build Coastguard Worker // // Mock a call to an `absl::Bernoulli` distribution using Googletest 217*9356374aSAndroid Build Coastguard Worker // absl::MockingBitGen bitgen; 218*9356374aSAndroid Build Coastguard Worker // 219*9356374aSAndroid Build Coastguard Worker // ON_CALL(absl::MockBernoulli(), Call(bitgen, 0.5)) 220*9356374aSAndroid Build Coastguard Worker // .WillByDefault(testing::Return(true)); 221*9356374aSAndroid Build Coastguard Worker // EXPECT_TRUE(absl::Bernoulli(bitgen, 0.5)); 222*9356374aSAndroid Build Coastguard Worker // 223*9356374aSAndroid Build Coastguard Worker // // Mock a call to an `absl::Uniform` distribution within Googletest 224*9356374aSAndroid Build Coastguard Worker // absl::MockingBitGen bitgen; 225*9356374aSAndroid Build Coastguard Worker // 226*9356374aSAndroid Build Coastguard Worker // ON_CALL(absl::MockUniform<int>(), Call(bitgen, testing::_, testing::_)) 227*9356374aSAndroid Build Coastguard Worker // .WillByDefault([] (int low, int high) { 228*9356374aSAndroid Build Coastguard Worker // return low + (high - low) / 2; 229*9356374aSAndroid Build Coastguard Worker // }); 230*9356374aSAndroid Build Coastguard Worker // 231*9356374aSAndroid Build Coastguard Worker // EXPECT_EQ(absl::Uniform<int>(gen, 0, 10), 5); 232*9356374aSAndroid Build Coastguard Worker // EXPECT_EQ(absl::Uniform<int>(gen, 30, 40), 35); 233*9356374aSAndroid Build Coastguard Worker // 234*9356374aSAndroid Build Coastguard Worker // At this time, only mock distributions supplied within the Abseil random 235*9356374aSAndroid Build Coastguard Worker // library are officially supported. 236*9356374aSAndroid Build Coastguard Worker // 237*9356374aSAndroid Build Coastguard Worker // EXPECT_CALL and ON_CALL need to be made within the same DLL component as 238*9356374aSAndroid Build Coastguard Worker // the call to absl::Uniform and related methods, otherwise mocking will fail 239*9356374aSAndroid Build Coastguard Worker // since the underlying implementation creates a type-specific pointer which 240*9356374aSAndroid Build Coastguard Worker // will be distinct across different DLL boundaries. 241*9356374aSAndroid Build Coastguard Worker // 242*9356374aSAndroid Build Coastguard Worker using MockingBitGen = random_internal::MockingBitGenImpl<true>; 243*9356374aSAndroid Build Coastguard Worker 244*9356374aSAndroid Build Coastguard Worker // UnvalidatedMockingBitGen 245*9356374aSAndroid Build Coastguard Worker // 246*9356374aSAndroid Build Coastguard Worker // UnvalidatedMockingBitGen is a variant of MockingBitGen which does no extra 247*9356374aSAndroid Build Coastguard Worker // validation. 248*9356374aSAndroid Build Coastguard Worker using UnvalidatedMockingBitGen ABSL_DEPRECATED("Use MockingBitGen instead") = 249*9356374aSAndroid Build Coastguard Worker random_internal::MockingBitGenImpl<false>; 250*9356374aSAndroid Build Coastguard Worker 251*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END 252*9356374aSAndroid Build Coastguard Worker } // namespace absl 253*9356374aSAndroid Build Coastguard Worker 254*9356374aSAndroid Build Coastguard Worker #endif // ABSL_RANDOM_MOCKING_BIT_GEN_H_ 255