tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

mock_helpers.h (6439B)


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