mimic++ v6
Loading...
Searching...
No Matches
Mock.hpp
Go to the documentation of this file.
1// Copyright Dominic (DNKpp) Koepke 2024 - 2025.
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
13#include "mimic++/Fwd.hpp"
16#include "mimic++/Utility.hpp"
18
19namespace mimicpp::detail
20{
21 template <typename Derived, typename Signature>
22 using call_interface_t = typename call_convention_traits<
23 signature_call_convention_t<Signature>>::template call_interface_t<Derived, Signature>;
24
25 template <typename Derived, typename Signature, typename... Params>
26 class DefaultCallInterface<
27 Derived,
28 Signature,
31 type_list<Params...>>
32 {
33 public:
34 constexpr signature_return_type_t<Signature> operator()(
35 Params... params,
36 const std::source_location& from = std::source_location::current()) noexcept(signature_is_noexcept_v<Signature>)
37 {
38 return static_cast<const Derived&>(*this)
39 .handle_call(std::tuple{std::ref(params)...}, from);
40 }
41 };
42
43 template <typename Derived, typename Signature, typename... Params>
44 class DefaultCallInterface<
45 Derived,
46 Signature,
49 type_list<Params...>>
50 {
51 public:
52 constexpr signature_return_type_t<Signature> operator()(
53 Params... params,
54 const std::source_location& from = std::source_location::current()) const noexcept(signature_is_noexcept_v<Signature>)
55 {
56 return static_cast<const Derived&>(*this)
57 .handle_call(std::tuple{std::ref(params)...}, from);
58 }
59 };
60
61 template <typename Derived, typename Signature, typename... Params>
62 class DefaultCallInterface<
63 Derived,
64 Signature,
67 type_list<Params...>>
68 {
69 public:
70 constexpr signature_return_type_t<Signature> operator()(
71 Params... params,
72 const std::source_location& from = std::source_location::current()) & noexcept(signature_is_noexcept_v<Signature>)
73 {
74 return static_cast<const Derived&>(*this)
75 .handle_call(std::tuple{std::ref(params)...}, from);
76 }
77 };
78
79 template <typename Derived, typename Signature, typename... Params>
80 class DefaultCallInterface<
81 Derived,
82 Signature,
85 type_list<Params...>>
86 {
87 public:
88 constexpr signature_return_type_t<Signature> operator()(
89 Params... params,
90 const std::source_location& from = std::source_location::current()) const& noexcept(signature_is_noexcept_v<Signature>)
91 {
92 return static_cast<const Derived&>(*this)
93 .handle_call(std::tuple{std::ref(params)...}, from);
94 }
95 };
96
97 template <typename Derived, typename Signature, typename... Params>
98 class DefaultCallInterface<
99 Derived,
100 Signature,
103 type_list<Params...>>
104 {
105 public:
106 constexpr signature_return_type_t<Signature> operator()(
107 Params... params,
108 const std::source_location& from = std::source_location::current()) && noexcept(signature_is_noexcept_v<Signature>)
109 {
110 return static_cast<const Derived&>(*this)
111 .handle_call(std::tuple{std::ref(params)...}, from);
112 }
113 };
114
115 template <typename Derived, typename Signature, typename... Params>
116 class DefaultCallInterface<
117 Derived,
118 Signature,
121 type_list<Params...>>
122 {
123 public:
124 constexpr signature_return_type_t<Signature> operator()(
125 Params... params,
126 const std::source_location& from = std::source_location::current()) const&& noexcept(signature_is_noexcept_v<Signature>)
127 {
128 return static_cast<const Derived&>(*this)
129 .handle_call(std::tuple{std::ref(params)...}, from);
130 }
131 };
132
133 template <
134 typename Derived,
135 typename Signature,
138 typename ParamList = signature_param_list_t<Signature>>
139 class MockFrontend;
140
141 template <typename Derived, typename Signature, typename... Params>
142 class MockFrontend<
143 Derived,
144 Signature,
147 type_list<Params...>>
148 {
149 public:
150 template <typename... Args>
151 requires(... && requirement_for<Args, Params>)
152 [[nodiscard]]
153 constexpr auto expect_call(Args&&... args)
154 {
155 return static_cast<const Derived&>(*this)
156 .make_expectation_builder(std::forward<Args>(args)...);
157 }
158 };
159
160 template <typename Derived, typename Signature, typename... Params>
161 class MockFrontend<
162 Derived,
163 Signature,
166 type_list<Params...>>
167 {
168 public:
169 template <typename... Args>
170 requires(... && requirement_for<Args, Params>)
171 [[nodiscard]]
172 constexpr auto expect_call(Args&&... args) const
173 {
174 return static_cast<const Derived&>(*this)
175 .make_expectation_builder(std::forward<Args>(args)...);
176 }
177 };
178
179 template <typename Derived, typename Signature, typename... Params>
180 class MockFrontend<
181 Derived,
182 Signature,
185 type_list<Params...>>
186 {
187 public:
188 template <typename... Args>
189 requires(... && requirement_for<Args, Params>)
190 [[nodiscard]]
191 constexpr auto expect_call(Args&&... args) &
192 {
193 return static_cast<const Derived&>(*this)
194 .make_expectation_builder(std::forward<Args>(args)...);
195 }
196 };
197
198 template <typename Derived, typename Signature, typename... Params>
199 class MockFrontend<
200 Derived,
201 Signature,
204 type_list<Params...>>
205 {
206 public:
207 template <typename... Args>
208 requires(... && requirement_for<Args, Params>)
209 [[nodiscard]]
210 constexpr auto expect_call(Args&&... args) const&
211 {
212 return static_cast<const Derived&>(*this)
213 .make_expectation_builder(std::forward<Args>(args)...);
214 }
215 };
216
217 template <typename Derived, typename Signature, typename... Params>
218 class MockFrontend<
219 Derived,
220 Signature,
223 type_list<Params...>>
224 {
225 public:
226 template <typename... Args>
227 requires(... && requirement_for<Args, Params>)
228 [[nodiscard]]
229 constexpr auto expect_call(Args&&... args) &&
230 {
231 return static_cast<const Derived&>(*this)
232 .make_expectation_builder(std::forward<Args>(args)...);
233 }
234 };
235
236 template <typename Derived, typename Signature, typename... Params>
237 class MockFrontend<
238 Derived,
239 Signature,
242 type_list<Params...>>
243 {
244 public:
245 template <typename... Args>
246 requires(... && requirement_for<Args, Params>)
247 [[nodiscard]]
248 constexpr auto expect_call(Args&&... args) const&&
249 {
250 return static_cast<const Derived&>(*this)
251 .make_expectation_builder(std::forward<Args>(args)...);
252 }
253 };
254
255 template <typename Signature>
256 using expectation_collection_ptr_for = std::shared_ptr<ExpectationCollection<signature_decay_t<Signature>>>;
257
258 template <typename Signature, typename ParamList = signature_param_list_t<Signature>>
259 class BasicMock;
260
261 template <typename Signature, typename... Params>
262 class BasicMock<Signature, type_list<Params...>>
263 : public MockFrontend<
264 // MockFrontend doesn't need to know about the call-convention, thus remove it
265 BasicMock<Signature, type_list<Params...>>,
266 signature_remove_call_convention_t<Signature>>,
267 public call_interface_t<
268 BasicMock<Signature, type_list<Params...>>,
269 Signature>
270 {
272
273 friend class MockFrontend<BasicMock, SignatureT>;
274 friend call_interface_t<BasicMock, Signature>;
275
276 static constexpr Constness constQualification = signature_const_qualification_v<SignatureT>;
277 static constexpr ValueCategory refQualification = signature_ref_qualification_v<SignatureT>;
278
279 protected:
280 using ExpectationCollectionPtrT = expectation_collection_ptr_for<SignatureT>;
281
282 [[nodiscard]]
283 explicit BasicMock(
284 ExpectationCollectionPtrT collection,
285 const std::size_t stacktraceSkip) noexcept
286 : m_Expectations{std::move(collection)},
287 m_StacktraceSkip{stacktraceSkip + 2u} // skips the operator() and the handle_call from the stacktrace
288 {
289 }
290
291 private:
292 ExpectationCollectionPtrT m_Expectations;
293 std::size_t m_StacktraceSkip;
294
295 [[nodiscard]]
296 constexpr signature_return_type_t<SignatureT> handle_call(
297 std::tuple<std::reference_wrapper<std::remove_reference_t<Params>>...>&& params,
298 const std::source_location& from) const
299 {
300 return m_Expectations->handle_call(
302 .args = std::move(params),
303 .fromCategory = refQualification,
304 .fromConstness = constQualification,
305 .fromSourceLocation = from,
306 .stacktrace = stacktrace::current(m_StacktraceSkip)});
307 }
308
309 template <typename... Args>
310 [[nodiscard]]
311 constexpr auto make_expectation_builder(Args&&... args) const
312 {
313 return detail::make_expectation_builder(m_Expectations, std::forward<Args>(args)...)
314 && expectation_policies::Category<refQualification>{}
315 && expectation_policies::Constness<constQualification>{};
316 }
317 };
318
319 template <typename List>
320 struct expectation_collection_factory;
321
322 template <typename... UniqueSignatures>
323 struct expectation_collection_factory<type_list<UniqueSignatures...>>
324 {
325 [[nodiscard]]
326 static auto make()
327 {
328 return std::tuple{
329 std::make_shared<ExpectationCollection<UniqueSignatures>>()...};
330 }
331 };
332}
333
334namespace mimicpp
335{
386
392 template <typename FirstSignature, typename... OtherSignatures>
393 requires is_overload_set_v<FirstSignature, OtherSignatures...>
394 class Mock
395 : public detail::BasicMock<FirstSignature>,
396 public detail::BasicMock<OtherSignatures>...
397 {
398 public:
399 using detail::BasicMock<FirstSignature>::operator();
400 using detail::BasicMock<FirstSignature>::expect_call;
401 using detail::BasicMock<OtherSignatures>::operator()...;
402 using detail::BasicMock<OtherSignatures>::expect_call...;
403
407 ~Mock() = default;
408
412 [[nodiscard]]
414 : Mock{0u}
415 {
416 }
417
425 [[nodiscard]]
426 explicit Mock(const std::size_t baseStacktraceSkip)
427 : Mock{
428 detail::expectation_collection_factory<
429 detail::unique_list_t<
430 signature_decay_t<FirstSignature>,
431 signature_decay_t<OtherSignatures>...>>::make(),
432 baseStacktraceSkip}
433 {
434 }
435
439 Mock(const Mock&) = delete;
440
444 Mock& operator=(const Mock&) = delete;
445
449 [[nodiscard]]
450 Mock(Mock&&) = default;
451
455 Mock& operator=(Mock&&) = default;
456
457 private:
458 template <typename... Collections>
459 [[nodiscard]]
460 explicit Mock(
461 std::tuple<Collections...> collections,
462 const std::size_t stacktraceSkip) noexcept
463 : detail::BasicMock<FirstSignature>{
464 std::get<detail::expectation_collection_ptr_for<FirstSignature>>(collections),
465 stacktraceSkip},
466 // clang-format off
467 detail::BasicMock<OtherSignatures>{
468 std::get<detail::expectation_collection_ptr_for<OtherSignatures>>(collections),
469 stacktraceSkip}...
470 // clang-format on
471 {
472 }
473 };
474
478}
479
480#endif
~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(const std::size_t baseStacktraceSkip)
Constructor, initializing the base-stacktrace-skip.
Definition Mock.hpp:426
Mock & operator=(const Mock &)=delete
Deleted copy assignment operator.
Mock()
Default constructor.
Definition Mock.hpp:413
constexpr detail::current_hook::current_fn current
Function object, which generates the current-stacktrace.
Definition Stacktrace.hpp:374
constexpr bool is_overload_set_v
Convenience constant, exposing the value member of the actual type-trait.
Definition Fwd.hpp:289
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:77
constexpr Constness signature_const_qualification_v
Convenience constant, exposing the value member of the actual type-trait.
Definition Fwd.hpp:189
typename signature_decay< Signature >::type signature_decay_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:157
constexpr bool signature_is_noexcept_v
Convenience constant, exposing the value member of the actual type-trait.
Definition Fwd.hpp:221
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:253
constexpr ValueCategory signature_ref_qualification_v
Convenience constant, exposing the value member of the actual type-trait.
Definition Fwd.hpp:205
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:93
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:173
typename info_for_signature< Signature >::type info_for_signature_t
Definition Call.hpp:43
Definition BoostTest.hpp:20
ValueCategory
Definition Fwd.hpp:32
@ any
Definition Fwd.hpp:35
@ lvalue
Definition Fwd.hpp:33
@ rvalue
Definition Fwd.hpp:34
Constness
Definition Fwd.hpp:25
@ as_const
Definition Fwd.hpp:27
@ non_const
Definition Fwd.hpp:26