Back to home page

EIC code displayed by LXR

 
 

    


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_