mimic++ v5
Loading...
Searching...
No Matches
Mock.hpp
Go to the documentation of this file.
1// // Copyright Dominic (DNKpp) Koepke 2024 - 2024.
2// // Distributed under the Boost Software License, Version 1.0.
3// // (See accompanying file LICENSE_1_0.txt or copy at
4// // https://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef MIMICPP_MOCK_HPP
7#define MIMICPP_MOCK_HPP
8
9#pragma once
10
15#include "mimic++/Utility.hpp"
16
17namespace mimicpp::detail
18{
19 template <typename Derived, typename Signature>
20 using call_interface_t = typename call_convention_traits<
21 signature_call_convention_t<Signature>>::template call_interface_t<Derived, Signature>;
22
23 template <typename Derived, typename Signature, typename... Params>
24 class DefaultCallInterface<
25 Derived,
26 Signature,
29 type_list<Params...>>
30 {
31 public:
32 constexpr signature_return_type_t<Signature> operator()(
33 Params... params,
34 const std::source_location& from = std::source_location::current()) noexcept(signature_is_noexcept_v<Signature>)
35 {
36 return static_cast<const Derived&>(*this)
37 .handle_call(std::tuple{std::ref(params)...}, from);
38 }
39 };
40
41 template <typename Derived, typename Signature, typename... Params>
42 class DefaultCallInterface<
43 Derived,
44 Signature,
47 type_list<Params...>>
48 {
49 public:
50 constexpr signature_return_type_t<Signature> operator()(
51 Params... params,
52 const std::source_location& from = std::source_location::current()) const noexcept(signature_is_noexcept_v<Signature>)
53 {
54 return static_cast<const Derived&>(*this)
55 .handle_call(std::tuple{std::ref(params)...}, from);
56 }
57 };
58
59 template <typename Derived, typename Signature, typename... Params>
60 class DefaultCallInterface<
61 Derived,
62 Signature,
65 type_list<Params...>>
66 {
67 public:
68 constexpr signature_return_type_t<Signature> operator()(
69 Params... params,
70 const std::source_location& from = std::source_location::current()) & noexcept(signature_is_noexcept_v<Signature>)
71 {
72 return static_cast<const Derived&>(*this)
73 .handle_call(std::tuple{std::ref(params)...}, from);
74 }
75 };
76
77 template <typename Derived, typename Signature, typename... Params>
78 class DefaultCallInterface<
79 Derived,
80 Signature,
83 type_list<Params...>>
84 {
85 public:
86 constexpr signature_return_type_t<Signature> operator()(
87 Params... params,
88 const std::source_location& from = std::source_location::current()) const& noexcept(signature_is_noexcept_v<Signature>)
89 {
90 return static_cast<const Derived&>(*this)
91 .handle_call(std::tuple{std::ref(params)...}, from);
92 }
93 };
94
95 template <typename Derived, typename Signature, typename... Params>
96 class DefaultCallInterface<
97 Derived,
98 Signature,
101 type_list<Params...>>
102 {
103 public:
104 constexpr signature_return_type_t<Signature> operator()(
105 Params... params,
106 const std::source_location& from = std::source_location::current()) && noexcept(signature_is_noexcept_v<Signature>)
107 {
108 return static_cast<const Derived&>(*this)
109 .handle_call(std::tuple{std::ref(params)...}, from);
110 }
111 };
112
113 template <typename Derived, typename Signature, typename... Params>
114 class DefaultCallInterface<
115 Derived,
116 Signature,
119 type_list<Params...>>
120 {
121 public:
122 constexpr signature_return_type_t<Signature> operator()(
123 Params... params,
124 const std::source_location& from = std::source_location::current()) const&& noexcept(signature_is_noexcept_v<Signature>)
125 {
126 return static_cast<const Derived&>(*this)
127 .handle_call(std::tuple{std::ref(params)...}, from);
128 }
129 };
130
131 template <
132 typename Derived,
133 typename Signature,
136 typename ParamList = signature_param_list_t<Signature>>
137 class MockFrontend;
138
139 template <typename Derived, typename Signature, typename... Params>
140 class MockFrontend<
141 Derived,
142 Signature,
145 type_list<Params...>>
146 {
147 public:
148 template <typename... Args>
149 requires(... && requirement_for<Args, Params>)
150 [[nodiscard]]
151 constexpr auto expect_call(Args&&... args)
152 {
153 return static_cast<const Derived&>(*this)
154 .make_expectation_builder(std::forward<Args>(args)...);
155 }
156 };
157
158 template <typename Derived, typename Signature, typename... Params>
159 class MockFrontend<
160 Derived,
161 Signature,
164 type_list<Params...>>
165 {
166 public:
167 template <typename... Args>
168 requires(... && requirement_for<Args, Params>)
169 [[nodiscard]]
170 constexpr auto expect_call(Args&&... args) const
171 {
172 return static_cast<const Derived&>(*this)
173 .make_expectation_builder(std::forward<Args>(args)...);
174 }
175 };
176
177 template <typename Derived, typename Signature, typename... Params>
178 class MockFrontend<
179 Derived,
180 Signature,
183 type_list<Params...>>
184 {
185 public:
186 template <typename... Args>
187 requires(... && requirement_for<Args, Params>)
188 [[nodiscard]]
189 constexpr auto expect_call(Args&&... args) &
190 {
191 return static_cast<const Derived&>(*this)
192 .make_expectation_builder(std::forward<Args>(args)...);
193 }
194 };
195
196 template <typename Derived, typename Signature, typename... Params>
197 class MockFrontend<
198 Derived,
199 Signature,
202 type_list<Params...>>
203 {
204 public:
205 template <typename... Args>
206 requires(... && requirement_for<Args, Params>)
207 [[nodiscard]]
208 constexpr auto expect_call(Args&&... args) const&
209 {
210 return static_cast<const Derived&>(*this)
211 .make_expectation_builder(std::forward<Args>(args)...);
212 }
213 };
214
215 template <typename Derived, typename Signature, typename... Params>
216 class MockFrontend<
217 Derived,
218 Signature,
221 type_list<Params...>>
222 {
223 public:
224 template <typename... Args>
225 requires(... && requirement_for<Args, Params>)
226 [[nodiscard]]
227 constexpr auto expect_call(Args&&... args) &&
228 {
229 return static_cast<const Derived&>(*this)
230 .make_expectation_builder(std::forward<Args>(args)...);
231 }
232 };
233
234 template <typename Derived, typename Signature, typename... Params>
235 class MockFrontend<
236 Derived,
237 Signature,
240 type_list<Params...>>
241 {
242 public:
243 template <typename... Args>
244 requires(... && requirement_for<Args, Params>)
245 [[nodiscard]]
246 constexpr auto expect_call(Args&&... args) const&&
247 {
248 return static_cast<const Derived&>(*this)
249 .make_expectation_builder(std::forward<Args>(args)...);
250 }
251 };
252
253 template <typename Signature>
254 using expectation_collection_ptr_for = std::shared_ptr<ExpectationCollection<signature_decay_t<Signature>>>;
255
256 template <typename Signature, typename ParamList = signature_param_list_t<Signature>>
257 class BasicMock;
258
259 template <typename Signature, typename... Params>
260 class BasicMock<Signature, type_list<Params...>>
261 : public MockFrontend<
262 // MockFrontend doesn't need to know about the call-convention, thus remove it
263 BasicMock<Signature, type_list<Params...>>,
264 signature_remove_call_convention_t<Signature>>,
265 public call_interface_t<
266 BasicMock<Signature, type_list<Params...>>,
267 Signature>
268 {
270
271 friend class MockFrontend<BasicMock, SignatureT>;
272 friend call_interface_t<BasicMock, Signature>;
273
274 static constexpr Constness constQualification = signature_const_qualification_v<SignatureT>;
275 static constexpr ValueCategory refQualification = signature_ref_qualification_v<SignatureT>;
276
277 protected:
278 using ExpectationCollectionPtrT = expectation_collection_ptr_for<SignatureT>;
279
280 [[nodiscard]]
281 explicit BasicMock(ExpectationCollectionPtrT collection) noexcept
282 : m_Expectations{std::move(collection)}
283 {
284 }
285
286 private:
287 ExpectationCollectionPtrT m_Expectations;
288
289 [[nodiscard]]
290 constexpr signature_return_type_t<SignatureT> handle_call(
291 std::tuple<std::reference_wrapper<std::remove_reference_t<Params>>...>&& params,
292 const std::source_location& from) const
293 {
294 return m_Expectations->handle_call(
296 .args = std::move(params),
297 .fromCategory = refQualification,
298 .fromConstness = constQualification,
299 .fromSourceLocation = from});
300 }
301
302 template <typename... Args>
303 [[nodiscard]]
304 constexpr auto make_expectation_builder(Args&&... args) const
305 {
306 return detail::make_expectation_builder(m_Expectations, std::forward<Args>(args)...)
307 && expectation_policies::Category<refQualification>{}
308 && expectation_policies::Constness<constQualification>{};
309 }
310 };
311
312 template <typename List>
313 struct expectation_collection_factory;
314
315 template <typename... UniqueSignatures>
316 struct expectation_collection_factory<type_list<UniqueSignatures...>>
317 {
318 [[nodiscard]]
319 static auto make()
320 {
321 return std::tuple{
322 std::make_shared<ExpectationCollection<UniqueSignatures>>()...};
323 }
324 };
325}
326
327namespace mimicpp
328{
385 template <typename FirstSignature, typename... OtherSignatures>
386 requires is_overload_set_v<FirstSignature, OtherSignatures...>
387 class Mock
388 : public detail::BasicMock<FirstSignature>,
389 public detail::BasicMock<OtherSignatures>...
390 {
391 public:
392 using detail::BasicMock<FirstSignature>::operator();
393 using detail::BasicMock<FirstSignature>::expect_call;
394 using detail::BasicMock<OtherSignatures>::operator()...;
395 using detail::BasicMock<OtherSignatures>::expect_call...;
396
400 ~Mock() = default;
401
405 [[nodiscard]]
407 : Mock{
408 detail::expectation_collection_factory<
409 detail::unique_list_t<
410 signature_decay_t<FirstSignature>,
411 signature_decay_t<OtherSignatures>...>>::make()}
412 {
413 }
414
418 Mock(const Mock&) = delete;
419
423 Mock& operator=(const Mock&) = delete;
424
428 [[nodiscard]]
429 Mock(Mock&&) = default;
430
434 Mock& operator=(Mock&&) = default;
435
436 private:
437 template <typename... Collections>
438 explicit Mock(std::tuple<Collections...> collections) noexcept
439 : detail::BasicMock<FirstSignature>{std::get<detail::expectation_collection_ptr_for<FirstSignature>>(collections)},
440 detail::BasicMock<OtherSignatures>{std::get<detail::expectation_collection_ptr_for<OtherSignatures>>(collections)}...
441 {
442 }
443 };
444
448}
449
450#endif
A Mock type, which fully supports overload sets.
Definition Mock.hpp:390
~Mock()=default
Defaulted destructor.
Mock & operator=(Mock &&)=default
Defaulted move assignment operator.
Mock(Mock &&)=default
Defaulted move constructor.
Mock(const Mock &)=delete
Deleted copy constructor.
Mock & operator=(const Mock &)=delete
Deleted copy assignment operator.
Mock()
Default constructor.
Definition Mock.hpp:406
constexpr bool is_overload_set_v
Convenience constant, exposing the value member of the actual type-trait.
Definition Fwd.hpp:287
typename signature_call_convention< Signature >::type signature_call_convention_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:75
constexpr Constness signature_const_qualification_v
Convenience constant, exposing the value member of the actual type-trait.
Definition Fwd.hpp:187
typename signature_decay< Signature >::type signature_decay_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:155
constexpr bool signature_is_noexcept_v
Convenience constant, exposing the value member of the actual type-trait.
Definition Fwd.hpp:219
typename signature_param_list< Signature >::type signature_param_list_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:251
constexpr ValueCategory signature_ref_qualification_v
Convenience constant, exposing the value member of the actual type-trait.
Definition Fwd.hpp:203
typename signature_remove_call_convention< Signature >::type signature_remove_call_convention_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:91
typename signature_return_type< Signature >::type signature_return_type_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:171
typename info_for_signature< Signature >::type info_for_signature_t
Definition Call.hpp:69
Definition BoostTest.hpp:20
ValueCategory
Definition Fwd.hpp:30
Constness
Definition Fwd.hpp:23