mimic++ v4
Loading...
Searching...
No Matches
ExpectationBuilder.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_EXPECTATION_BUILDER_HPP
7#define MIMICPP_EXPECTATION_BUILDER_HPP
8
9#pragma once
10
14#include "mimic++/Sequence.hpp"
15
16namespace mimicpp
17{
18 template <
19 bool timesConfigured,
20 typename SequenceConfig,
21 typename Signature,
22 typename FinalizePolicy,
23 expectation_policy_for<Signature>... Policies>
25 {
26 public:
28 using PolicyListT = std::tuple<Policies...>;
30
32
33 template <typename FinalizePolicyArg, typename PolicyListArg>
34 requires std::constructible_from<FinalizePolicy, FinalizePolicyArg>
35 && std::constructible_from<PolicyListT, PolicyListArg>
36 [[nodiscard]]
37 explicit constexpr BasicExpectationBuilder(
38 std::shared_ptr<StorageT> storage,
39 detail::TimesConfig timesConfig,
40 SequenceConfig sequenceConfig,
41 FinalizePolicyArg&& finalizePolicyArg,
42 PolicyListArg&& policyListArg
43 ) noexcept
44 : m_Storage{std::move(storage)},
45 m_TimesConfig{std::move(timesConfig)},
46 m_SequenceConfig{std::move(sequenceConfig)},
47 m_FinalizePolicy{std::forward<FinalizePolicyArg>(finalizePolicyArg)},
48 m_ExpectationPolicies{std::forward<PolicyListArg>(policyListArg)}
49 {
50 assert(m_Storage && "Storage is nullptr.");
51 }
52
55
56 [[nodiscard]]
59
60 template <typename Policy>
61 requires std::same_as<expectation_policies::InitFinalize, FinalizePolicy>
62 && (!std::same_as<expectation_policies::InitFinalize, std::remove_cvref_t<Policy>>)
63 && finalize_policy_for<std::remove_cvref_t<Policy>, Signature>
64 [[nodiscard]]
65 constexpr auto operator &&(Policy&& policy) &&
66 {
67 using ExtendedExpectationBuilderT = BasicExpectationBuilder<
68 timesConfigured,
69 SequenceConfig,
70 Signature,
71 std::remove_cvref_t<Policy>,
72 Policies...>;
73
74 return ExtendedExpectationBuilderT{
75 std::move(m_Storage),
76 std::move(m_TimesConfig),
77 std::move(m_SequenceConfig),
78 std::forward<Policy>(policy),
79 std::move(m_ExpectationPolicies)
80 };
81 }
82
83 template <typename Policy>
85 [[nodiscard]]
86 constexpr auto operator &&(Policy&& policy) && // NOLINT(cppcoreguidelines-missing-std-forward)
87 {
88 using ExtendedExpectationBuilderT = BasicExpectationBuilder<
89 timesConfigured,
90 SequenceConfig,
91 Signature,
92 FinalizePolicy,
93 Policies...,
94 std::remove_cvref_t<Policy>>;
95
96 return ExtendedExpectationBuilderT{
97 std::move(m_Storage),
98 std::move(m_TimesConfig),
99 std::move(m_SequenceConfig),
100 std::move(m_FinalizePolicy),
101 std::apply(
102 [&](auto&... policies) noexcept
103 {
104 return std::forward_as_tuple(
105 std::move(policies)...,
106 std::forward<Policy>(policy));
107 },
108 m_ExpectationPolicies)
109 };
110 }
111
112 [[nodiscard]]
113 constexpr auto operator &&(detail::TimesConfig&& config) &&
114 requires (!timesConfigured)
115 {
116 using NewBuilderT = BasicExpectationBuilder<
117 true,
118 SequenceConfig,
119 Signature,
120 FinalizePolicy,
121 Policies...>;
122
123 return NewBuilderT{
124 std::move(m_Storage),
125 std::move(config),
126 std::move(m_SequenceConfig),
127 std::move(m_FinalizePolicy),
128 std::move(m_ExpectationPolicies)
129 };
130 }
131
132 template <typename... Sequences>
133 [[nodiscard]]
134 constexpr auto operator &&(sequence::detail::Config<Sequences...>&& config) &&
135 {
136 sequence::detail::Config newConfig = m_SequenceConfig.concat(std::move(config));
137
138 using ExtendedExpectationBuilderT = BasicExpectationBuilder<
139 timesConfigured,
140 decltype(newConfig),
141 Signature,
142 FinalizePolicy,
143 Policies...>;
144
145 return ExtendedExpectationBuilderT{
146 std::move(m_Storage),
147 std::move(m_TimesConfig),
148 std::move(newConfig),
149 std::move(m_FinalizePolicy),
150 std::move(m_ExpectationPolicies)
151 };
152 }
153
154 [[nodiscard]]
155 ScopedExpectation finalize(const std::source_location& sourceLocation) &&
156 {
157 static_assert(
159 "For non-void return types, a finalize policy must be set.");
160
161 return ScopedExpectation{
162 std::move(m_Storage),
163 std::apply(
164 [&](auto&... policies)
165 {
166 ControlPolicy controlPolicy{
167 std::move(m_TimesConfig),
168 std::move(m_SequenceConfig)
169 };
170
171 using ExpectationT = BasicExpectation<
172 Signature,
173 decltype(controlPolicy),
174 FinalizePolicy,
175 Policies...>;
176
177 return std::make_unique<ExpectationT>(
178 sourceLocation,
179 std::move(controlPolicy),
180 std::move(m_FinalizePolicy),
181 std::move(policies)...);
182 },
183 m_ExpectationPolicies)
184 };
185 }
186
187 private:
188 std::shared_ptr<StorageT> m_Storage;
189 detail::TimesConfig m_TimesConfig{};
190 SequenceConfig m_SequenceConfig{};
191 FinalizePolicy m_FinalizePolicy{};
192 PolicyListT m_ExpectationPolicies{};
193 };
194}
195
196namespace mimicpp::detail
197{
198 template <typename Param, typename Arg>
199 requires matcher_for<
200 std::remove_cvref_t<Arg>,
201 Param>
202 [[nodiscard]]
203 constexpr auto make_arg_matcher(Arg&& arg, [[maybe_unused]] const priority_tag<2>)
204 {
205 return std::forward<Arg>(arg);
206 }
207
208 template <string Param, string Arg>
209 [[nodiscard]]
210 constexpr auto make_arg_matcher(Arg&& arg, [[maybe_unused]] const priority_tag<1>)
211 {
212 return matches::str::eq(std::forward<Arg>(arg));
213 }
214
215 template <typename Param, std::equality_comparable_with<Param> Arg>
216 [[nodiscard]]
217 constexpr auto make_arg_matcher(Arg&& arg, [[maybe_unused]] const priority_tag<0>)
218 {
219 return matches::eq(std::forward<Arg>(arg));
220 }
221
222 constexpr priority_tag<2> max_make_arg_matcher_tag{};
223
224 template <typename Arg, typename Target>
225 concept requirement_for = requires
226 {
227 {
228 detail::make_arg_matcher<Target, Arg>(
229 std::declval<Arg>(),
230 max_make_arg_matcher_tag)
231 } -> matcher_for<Target>;
232 };
233
234 template <
235 typename Signature,
236 std::size_t index,
237 typename Arg,
238 typename... Canary,
240 requires requirement_for<Arg, Param>
241 constexpr auto make_arg_policy(Arg&& arg)
242 {
243 return expect::arg<index>(
244 detail::make_arg_matcher<Param, Arg>(
245 std::forward<Arg>(arg),
246 max_make_arg_matcher_tag));
247 }
248
249 template <typename Signature, typename Builder, std::size_t... indices, typename... Args>
250 [[nodiscard]]
251 constexpr auto extend_builder_with_arg_policies(
252 Builder&& builder,
253 const std::index_sequence<indices...>,
254 Args&&... args
255 )
256 {
257 return (
258 std::forward<Builder>(builder)
259 && ...
260 && detail::make_arg_policy<Signature, indices>(
261 std::forward<Args>(args)));
262 }
263
264 template <typename Signature, typename... Args>
265 constexpr auto make_expectation_builder(
266 std::shared_ptr<ExpectationCollection<Signature>> expectations,
267 Args&&... args
268 )
269 {
270 using BaseBuilderT = BasicExpectationBuilder<
271 false,
272 sequence::detail::Config<>,
273 Signature,
274 expectation_policies::InitFinalize
275 >;
276
277 return detail::extend_builder_with_arg_policies<Signature>(
278 BaseBuilderT{
279 std::move(expectations),
280 TimesConfig{},
281 sequence::detail::Config<>{},
282 expectation_policies::InitFinalize{},
283 std::tuple{}
284 },
285 std::index_sequence_for<Args...>{},
286 std::forward<Args>(args)...);
287 }
288}
289
290#define MIMICPP_DETAIL_UNIQUE_NAME(prefix, counter) prefix##counter
291#define MIMICPP_DETAIL_SCOPED_EXPECTATION_IMPL(counter) \
292 [[maybe_unused]] \
293 const ::mimicpp::ScopedExpectation MIMICPP_DETAIL_UNIQUE_NAME(_mimicpp_expectation_, counter) =
294
299#define MIMICPP_SCOPED_EXPECTATION MIMICPP_DETAIL_SCOPED_EXPECTATION_IMPL(__COUNTER__)
300
301#ifndef MIMICPP_CONFIG_ONLY_PREFIXED_MACROS
302
307 #define SCOPED_EXP MIMICPP_SCOPED_EXPECTATION
308
309#endif
310
311#endif
Definition ExpectationBuilder.hpp:25
ScopedExpectation finalize(const std::source_location &sourceLocation) &&
Definition ExpectationBuilder.hpp:155
BasicExpectationBuilder(BasicExpectationBuilder &&)=default
std::tuple< Policies... > PolicyListT
Definition ExpectationBuilder.hpp:28
BasicExpectationBuilder & operator=(const BasicExpectationBuilder &)=delete
typename Expectation< Signature >::ReturnT ReturnT
Definition ExpectationBuilder.hpp:29
BasicExpectationBuilder(const BasicExpectationBuilder &)=delete
constexpr BasicExpectationBuilder(std::shared_ptr< StorageT > storage, detail::TimesConfig timesConfig, SequenceConfig sequenceConfig, FinalizePolicyArg &&finalizePolicyArg, PolicyListArg &&policyListArg) noexcept
Definition ExpectationBuilder.hpp:37
constexpr auto operator&&(Policy &&policy) &&
Definition ExpectationBuilder.hpp:65
The actual expectation template.
Definition Expectation.hpp:415
Definition ControlPolicy.hpp:165
Collects all expectations for a specific (decayed) signature.
Definition Fwd.hpp:176
signature_return_type_t< Signature > ReturnT
The return type.
Definition Expectation.hpp:117
Takes the ownership of an expectation and check whether it's satisfied during destruction.
Definition Expectation.hpp:568
Determines, whether the given type satisfies the requirements of an expectation-policy for the given ...
Definition Expectation.hpp:363
Determines, whether the given type satisfies the requirements of a finalize-policy for the given sign...
Definition Expectation.hpp:378
constexpr auto eq(T &&value)
Tests, whether the target compares equal to the expected value.
Definition Matcher.hpp:350
constexpr auto eq(Pattern &&pattern)
Tests, whether the target string compares equal to the expected string.
Definition Matcher.hpp:594
constexpr auto arg(Matcher &&matcher, Projection projection={}) noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< Matcher >, Matcher > &&std::is_nothrow_move_constructible_v< Projection >)
Checks, whether the selected argument matches the given matcher.
Definition ExpectationPolicies.hpp:405
typename signature_param_type< index, Signature >::type signature_param_type_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:100
Definition BoostTest.hpp:20