xref: /aosp_15_r20/external/abseil-cpp/absl/random/internal/mock_overload_set.h (revision 9356374a3709195abf420251b3e825997ff56c0f)
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_OVERLOAD_SET_H_
17 #define ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_
18 
19 #include <tuple>
20 #include <type_traits>
21 
22 #include "gmock/gmock.h"
23 #include "absl/base/config.h"
24 #include "absl/random/internal/mock_helpers.h"
25 #include "absl/random/mocking_bit_gen.h"
26 
27 namespace absl {
28 ABSL_NAMESPACE_BEGIN
29 namespace random_internal {
30 
31 template <typename DistrT, typename ValidatorT, typename Fn>
32 struct MockSingleOverload;
33 
34 // MockSingleOverload
35 //
36 // MockSingleOverload hooks in to gMock's `ON_CALL` and `EXPECT_CALL` macros.
37 // EXPECT_CALL(mock_single_overload, Call(...))` will expand to a call to
38 // `mock_single_overload.gmock_Call(...)`. Because expectations are stored on
39 // the MockingBitGen (an argument passed inside `Call(...)`), this forwards to
40 // arguments to MockingBitGen::Register.
41 //
42 // The underlying KeyT must match the KeyT constructed by DistributionCaller.
43 template <typename DistrT, typename ValidatorT, typename Ret, typename... Args>
44 struct MockSingleOverload<DistrT, ValidatorT, Ret(MockingBitGen&, Args...)> {
45   static_assert(std::is_same<typename DistrT::result_type, Ret>::value,
46                 "Overload signature must have return type matching the "
47                 "distribution result_type.");
48   using KeyT = Ret(DistrT, std::tuple<Args...>);
49 
50   template <typename MockURBG>
51   auto gmock_Call(MockURBG& gen, const ::testing::Matcher<Args>&... matchers)
52       -> decltype(MockHelpers::MockFor<KeyT>(gen, ValidatorT())
53                       .gmock_Call(matchers...)) {
54     static_assert(
55         std::is_base_of<MockingBitGenImpl<true>, MockURBG>::value ||
56             std::is_base_of<MockingBitGenImpl<false>, MockURBG>::value,
57         "Mocking requires an absl::MockingBitGen");
58     return MockHelpers::MockFor<KeyT>(gen, ValidatorT())
59         .gmock_Call(matchers...);
60   }
61 };
62 
63 template <typename DistrT, typename ValidatorT, typename Ret, typename Arg,
64           typename... Args>
65 struct MockSingleOverload<DistrT, ValidatorT,
66                           Ret(Arg, MockingBitGen&, Args...)> {
67   static_assert(std::is_same<typename DistrT::result_type, Ret>::value,
68                 "Overload signature must have return type matching the "
69                 "distribution result_type.");
70   using KeyT = Ret(DistrT, std::tuple<Arg, Args...>);
71 
72   template <typename MockURBG>
73   auto gmock_Call(const ::testing::Matcher<Arg>& matcher, MockURBG& gen,
74                   const ::testing::Matcher<Args>&... matchers)
75       -> decltype(MockHelpers::MockFor<KeyT>(gen, ValidatorT())
76                       .gmock_Call(matcher, matchers...)) {
77     static_assert(
78         std::is_base_of<MockingBitGenImpl<true>, MockURBG>::value ||
79             std::is_base_of<MockingBitGenImpl<false>, MockURBG>::value,
80         "Mocking requires an absl::MockingBitGen");
81     return MockHelpers::MockFor<KeyT>(gen, ValidatorT())
82         .gmock_Call(matcher, matchers...);
83   }
84 };
85 
86 // MockOverloadSetWithValidator
87 //
88 // MockOverloadSetWithValidator is a wrapper around MockOverloadSet which takes
89 // an additional Validator parameter, allowing for customization of the mock
90 // behavior.
91 //
92 // `ValidatorT::Validate(result, args...)` will be called after the mock
93 // distribution returns a value in `result`, allowing for validation against the
94 // args.
95 template <typename DistrT, typename ValidatorT, typename... Fns>
96 struct MockOverloadSetWithValidator;
97 
98 template <typename DistrT, typename ValidatorT, typename Sig>
99 struct MockOverloadSetWithValidator<DistrT, ValidatorT, Sig>
100     : public MockSingleOverload<DistrT, ValidatorT, Sig> {
101   using MockSingleOverload<DistrT, ValidatorT, Sig>::gmock_Call;
102 };
103 
104 template <typename DistrT, typename ValidatorT, typename FirstSig,
105           typename... Rest>
106 struct MockOverloadSetWithValidator<DistrT, ValidatorT, FirstSig, Rest...>
107     : public MockSingleOverload<DistrT, ValidatorT, FirstSig>,
108       public MockOverloadSetWithValidator<DistrT, ValidatorT, Rest...> {
109   using MockSingleOverload<DistrT, ValidatorT, FirstSig>::gmock_Call;
110   using MockOverloadSetWithValidator<DistrT, ValidatorT, Rest...>::gmock_Call;
111 };
112 
113 // MockOverloadSet
114 //
115 // MockOverloadSet takes a distribution and a collection of signatures and
116 // performs overload resolution amongst all the overloads. This makes
117 // `EXPECT_CALL(mock_overload_set, Call(...))` expand and do overload resolution
118 // correctly.
119 template <typename DistrT, typename... Signatures>
120 using MockOverloadSet =
121     MockOverloadSetWithValidator<DistrT, NoOpValidator, Signatures...>;
122 
123 }  // namespace random_internal
124 ABSL_NAMESPACE_END
125 }  // namespace absl
126 #endif  // ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_
127