|
|
|||
File indexing completed on 2025-12-16 09:40:57
0001 // Copyright 2018 The Abseil Authors. 0002 // 0003 // Licensed under the Apache License, Version 2.0 (the "License"); 0004 // you may not use this file except in compliance with the License. 0005 // You may obtain a copy of the License at 0006 // 0007 // https://www.apache.org/licenses/LICENSE-2.0 0008 // 0009 // Unless required by applicable law or agreed to in writing, software 0010 // distributed under the License is distributed on an "AS IS" BASIS, 0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0012 // See the License for the specific language governing permissions and 0013 // limitations under the License. 0014 // 0015 // ----------------------------------------------------------------------------- 0016 // mocking_bit_gen.h 0017 // ----------------------------------------------------------------------------- 0018 // 0019 // This file includes an `absl::MockingBitGen` class to use as a mock within the 0020 // Googletest testing framework. Such a mock is useful to provide deterministic 0021 // values as return values within (otherwise random) Abseil distribution 0022 // functions. Such determinism within a mock is useful within testing frameworks 0023 // to test otherwise indeterminate APIs. 0024 // 0025 // More information about the Googletest testing framework is available at 0026 // https://github.com/google/googletest 0027 0028 #ifndef ABSL_RANDOM_MOCKING_BIT_GEN_H_ 0029 #define ABSL_RANDOM_MOCKING_BIT_GEN_H_ 0030 0031 #include <memory> 0032 #include <tuple> 0033 #include <type_traits> 0034 #include <utility> 0035 0036 #include "gmock/gmock.h" 0037 #include "absl/base/attributes.h" 0038 #include "absl/base/config.h" 0039 #include "absl/base/internal/fast_type_id.h" 0040 #include "absl/container/flat_hash_map.h" 0041 #include "absl/meta/type_traits.h" 0042 #include "absl/random/internal/mock_helpers.h" 0043 #include "absl/random/random.h" 0044 #include "absl/utility/utility.h" 0045 0046 namespace absl { 0047 ABSL_NAMESPACE_BEGIN 0048 0049 class BitGenRef; 0050 0051 namespace random_internal { 0052 template <typename> 0053 struct DistributionCaller; 0054 class MockHelpers; 0055 0056 // Implements MockingBitGen with an option to turn on extra validation. 0057 template <bool EnableValidation> 0058 class MockingBitGenImpl { 0059 public: 0060 MockingBitGenImpl() = default; 0061 ~MockingBitGenImpl() = default; 0062 0063 // URBG interface 0064 using result_type = absl::BitGen::result_type; 0065 0066 static constexpr result_type(min)() { return (absl::BitGen::min)(); } 0067 static constexpr result_type(max)() { return (absl::BitGen::max)(); } 0068 result_type operator()() { return gen_(); } 0069 0070 private: 0071 // GetMockFnType returns the testing::MockFunction for a result and tuple. 0072 // This method only exists for type deduction and is otherwise unimplemented. 0073 template <typename ResultT, typename... Args> 0074 static auto GetMockFnType(ResultT, std::tuple<Args...>) 0075 -> ::testing::MockFunction<ResultT(Args...)>; 0076 0077 // MockFnCaller is a helper method for use with absl::apply to 0078 // apply an ArgTupleT to a compatible MockFunction. 0079 // NOTE: MockFnCaller is essentially equivalent to the lambda: 0080 // [fn](auto... args) { return fn->Call(std::move(args)...)} 0081 // however that fails to build on some supported platforms. 0082 template <typename MockFnType, typename ValidatorT, typename ResultT, 0083 typename Tuple> 0084 struct MockFnCaller; 0085 0086 // specialization for std::tuple. 0087 template <typename MockFnType, typename ValidatorT, typename ResultT, 0088 typename... Args> 0089 struct MockFnCaller<MockFnType, ValidatorT, ResultT, std::tuple<Args...>> { 0090 MockFnType* fn; 0091 inline ResultT operator()(Args... args) { 0092 ResultT result = fn->Call(args...); 0093 ValidatorT::Validate(result, args...); 0094 return result; 0095 } 0096 }; 0097 0098 // FunctionHolder owns a particular ::testing::MockFunction associated with 0099 // a mocked type signature, and implement the type-erased Apply call, which 0100 // applies type-erased arguments to the mock. 0101 class FunctionHolder { 0102 public: 0103 virtual ~FunctionHolder() = default; 0104 0105 // Call is a dispatch function which converts the 0106 // generic type-erased parameters into a specific mock invocation call. 0107 virtual void Apply(/*ArgTupleT*/ void* args_tuple, 0108 /*ResultT*/ void* result) = 0; 0109 }; 0110 0111 template <typename MockFnType, typename ValidatorT, typename ResultT, 0112 typename ArgTupleT> 0113 class FunctionHolderImpl final : public FunctionHolder { 0114 public: 0115 void Apply(void* args_tuple, void* result) final { 0116 // Requires tuple_args to point to a ArgTupleT, which is a 0117 // std::tuple<Args...> used to invoke the mock function. Requires result 0118 // to point to a ResultT, which is the result of the call. 0119 *static_cast<ResultT*>(result) = absl::apply( 0120 MockFnCaller<MockFnType, ValidatorT, ResultT, ArgTupleT>{&mock_fn_}, 0121 *static_cast<ArgTupleT*>(args_tuple)); 0122 } 0123 0124 MockFnType mock_fn_; 0125 }; 0126 0127 // MockingBitGen::RegisterMock 0128 // 0129 // RegisterMock<ResultT, ArgTupleT>(FastTypeIdType) is the main extension 0130 // point for extending the MockingBitGen framework. It provides a mechanism to 0131 // install a mock expectation for a function like ResultT(Args...) keyed by 0132 // type_idex onto the MockingBitGen context. The key is that the type_index 0133 // used to register must match the type index used to call the mock. 0134 // 0135 // The returned MockFunction<...> type can be used to setup additional 0136 // distribution parameters of the expectation. 0137 template <typename ResultT, typename ArgTupleT, typename SelfT, 0138 typename ValidatorT> 0139 auto RegisterMock(SelfT&, base_internal::FastTypeIdType type, ValidatorT) 0140 -> decltype(GetMockFnType(std::declval<ResultT>(), 0141 std::declval<ArgTupleT>()))& { 0142 using ActualValidatorT = 0143 std::conditional_t<EnableValidation, ValidatorT, NoOpValidator>; 0144 using MockFnType = decltype(GetMockFnType(std::declval<ResultT>(), 0145 std::declval<ArgTupleT>())); 0146 0147 using WrappedFnType = absl::conditional_t< 0148 std::is_same<SelfT, ::testing::NiceMock<MockingBitGenImpl>>::value, 0149 ::testing::NiceMock<MockFnType>, 0150 absl::conditional_t< 0151 std::is_same<SelfT, ::testing::NaggyMock<MockingBitGenImpl>>::value, 0152 ::testing::NaggyMock<MockFnType>, 0153 absl::conditional_t< 0154 std::is_same<SelfT, 0155 ::testing::StrictMock<MockingBitGenImpl>>::value, 0156 ::testing::StrictMock<MockFnType>, MockFnType>>>; 0157 0158 using ImplT = 0159 FunctionHolderImpl<WrappedFnType, ActualValidatorT, ResultT, ArgTupleT>; 0160 auto& mock = mocks_[type]; 0161 if (!mock) { 0162 mock = absl::make_unique<ImplT>(); 0163 } 0164 return static_cast<ImplT*>(mock.get())->mock_fn_; 0165 } 0166 0167 // MockingBitGen::InvokeMock 0168 // 0169 // InvokeMock(FastTypeIdType, args, result) is the entrypoint for invoking 0170 // mocks registered on MockingBitGen. 0171 // 0172 // When no mocks are registered on the provided FastTypeIdType, returns false. 0173 // Otherwise attempts to invoke the mock function ResultT(Args...) that 0174 // was previously registered via the type_index. 0175 // Requires tuple_args to point to a ArgTupleT, which is a std::tuple<Args...> 0176 // used to invoke the mock function. 0177 // Requires result to point to a ResultT, which is the result of the call. 0178 inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple, 0179 void* result) { 0180 // Trigger a mock, if there exists one that matches `param`. 0181 auto it = mocks_.find(type); 0182 if (it == mocks_.end()) return false; 0183 it->second->Apply(args_tuple, result); 0184 return true; 0185 } 0186 0187 absl::flat_hash_map<base_internal::FastTypeIdType, 0188 std::unique_ptr<FunctionHolder>> 0189 mocks_; 0190 absl::BitGen gen_; 0191 0192 template <typename> 0193 friend struct ::absl::random_internal::DistributionCaller; // for InvokeMock 0194 friend class ::absl::BitGenRef; // for InvokeMock 0195 friend class ::absl::random_internal::MockHelpers; // for RegisterMock, 0196 // InvokeMock 0197 }; 0198 0199 } // namespace random_internal 0200 0201 // MockingBitGen 0202 // 0203 // `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class 0204 // which can act in place of an `absl::BitGen` URBG within tests using the 0205 // Googletest testing framework. 0206 // 0207 // Usage: 0208 // 0209 // Use an `absl::MockingBitGen` along with a mock distribution object (within 0210 // mock_distributions.h) inside Googletest constructs such as ON_CALL(), 0211 // EXPECT_TRUE(), etc. to produce deterministic results conforming to the 0212 // distribution's API contract. 0213 // 0214 // Example: 0215 // 0216 // // Mock a call to an `absl::Bernoulli` distribution using Googletest 0217 // absl::MockingBitGen bitgen; 0218 // 0219 // ON_CALL(absl::MockBernoulli(), Call(bitgen, 0.5)) 0220 // .WillByDefault(testing::Return(true)); 0221 // EXPECT_TRUE(absl::Bernoulli(bitgen, 0.5)); 0222 // 0223 // // Mock a call to an `absl::Uniform` distribution within Googletest 0224 // absl::MockingBitGen bitgen; 0225 // 0226 // ON_CALL(absl::MockUniform<int>(), Call(bitgen, testing::_, testing::_)) 0227 // .WillByDefault([] (int low, int high) { 0228 // return low + (high - low) / 2; 0229 // }); 0230 // 0231 // EXPECT_EQ(absl::Uniform<int>(gen, 0, 10), 5); 0232 // EXPECT_EQ(absl::Uniform<int>(gen, 30, 40), 35); 0233 // 0234 // At this time, only mock distributions supplied within the Abseil random 0235 // library are officially supported. 0236 // 0237 // EXPECT_CALL and ON_CALL need to be made within the same DLL component as 0238 // the call to absl::Uniform and related methods, otherwise mocking will fail 0239 // since the underlying implementation creates a type-specific pointer which 0240 // will be distinct across different DLL boundaries. 0241 // 0242 using MockingBitGen = random_internal::MockingBitGenImpl<true>; 0243 0244 // UnvalidatedMockingBitGen 0245 // 0246 // UnvalidatedMockingBitGen is a variant of MockingBitGen which does no extra 0247 // validation. 0248 using UnvalidatedMockingBitGen ABSL_DEPRECATED("Use MockingBitGen instead") = 0249 random_internal::MockingBitGenImpl<false>; 0250 0251 ABSL_NAMESPACE_END 0252 } // namespace absl 0253 0254 #endif // ABSL_RANDOM_MOCKING_BIT_GEN_H_
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|