mimic++ v9.2.1
Loading...
Searching...
No Matches
ExpectationBuilder.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_EXPECTATION_BUILDER_HPP
7#define MIMICPP_EXPECTATION_BUILDER_HPP
8
9#pragma once
10
12#include "mimic++/Fwd.hpp"
13#include "mimic++/Sequence.hpp"
26
27#ifndef MIMICPP_DETAIL_IS_MODULE
28 #include <concepts>
29 #include <memory>
30 #include <tuple>
31 #include <utility>
32#endif
33
35{
36 template <
37 bool timesConfigured,
38 typename SequenceConfig,
39 typename Signature,
40 typename FinalizePolicy,
43 {
44 public:
46 using PolicyListT = std::tuple<Policies...>;
48
50
51 template <typename FinalizePolicyArg, typename PolicyListArg>
52 requires std::constructible_from<FinalizePolicy, FinalizePolicyArg>
53 && std::constructible_from<PolicyListT, PolicyListArg>
54 [[nodiscard]]
55 explicit constexpr BasicExpectationBuilder(
56 std::shared_ptr<StorageT> storage,
58 detail::TimesConfig timesConfig,
59 SequenceConfig sequenceConfig,
60 FinalizePolicyArg&& finalizePolicyArg,
61 PolicyListArg&& policyListArg) noexcept
62 : m_Storage{std::move(storage)},
63 m_TargetReport{std::move(target)},
64 m_TimesConfig{std::move(timesConfig)},
65 m_SequenceConfig{std::move(sequenceConfig)},
66 m_FinalizePolicy{std::forward<FinalizePolicyArg>(finalizePolicyArg)},
67 m_ExpectationPolicies{std::forward<PolicyListArg>(policyListArg)}
68 {
69 MIMICPP_ASSERT(m_Storage, "Storage is nullptr.");
70 }
71
74
75 [[nodiscard]]
78
79 template <typename Policy>
81 [[nodiscard]]
82 friend constexpr auto operator&&(BasicExpectationBuilder&& builder, Policy&& policy)
83 {
84 static_assert(
85 !std::same_as<expectation_policies::InitFinalize, std::remove_cvref_t<Policy>>,
86 "Explicitly specifying the `expectation_policies::InitFinalize` is disallowed.");
87
88 static_assert(
89 std::same_as<expectation_policies::InitFinalize, FinalizePolicy>,
90 "Only one finalize-policy may be specified per expectation. "
91 "See: https://dnkpp.github.io/mimicpp/db/d7a/group___e_x_p_e_c_t_a_t_i_o_n___f_i_n_a_l_i_z_e_r.html#details");
92
93 using Builder = BasicExpectationBuilder<
94 timesConfigured,
95 SequenceConfig,
96 Signature,
97 std::remove_cvref_t<Policy>,
98 Policies...>;
99
100 return Builder{
101 std::move(builder.m_Storage),
102 std::move(builder.m_TargetReport),
103 std::move(builder.m_TimesConfig),
104 std::move(builder.m_SequenceConfig),
105 std::forward<Policy>(policy),
106 std::move(builder.m_ExpectationPolicies)};
107 }
108
109 template <typename Policy>
111 [[nodiscard]]
112 friend constexpr auto operator&&(BasicExpectationBuilder&& builder, Policy&& policy)
113 {
114 using ExtendedExpectationBuilderT = BasicExpectationBuilder<
115 timesConfigured,
116 SequenceConfig,
117 Signature,
118 FinalizePolicy,
119 Policies...,
120 std::remove_cvref_t<Policy>>;
121
122 return ExtendedExpectationBuilderT{
123 std::move(builder.m_Storage),
124 std::move(builder.m_TargetReport),
125 std::move(builder.m_TimesConfig),
126 std::move(builder.m_SequenceConfig),
127 std::move(builder.m_FinalizePolicy),
128 std::tuple_cat(
129 std::move(builder.m_ExpectationPolicies),
130 std::forward_as_tuple(std::forward<Policy>(policy)))};
131 }
132
133 [[nodiscard]]
134 friend constexpr auto operator&&(BasicExpectationBuilder&& builder, detail::TimesConfig&& config)
135 {
136 static_assert(
137 !timesConfigured,
138 "Only one times-policy may be specified per expectation. "
139 "See: https://dnkpp.github.io/mimicpp/d7/d32/group___e_x_p_e_c_t_a_t_i_o_n___t_i_m_e_s.html#details");
140
141 using Builder = BasicExpectationBuilder<
142 true,
143 SequenceConfig,
144 Signature,
145 FinalizePolicy,
146 Policies...>;
147
148 return Builder{
149 std::move(builder.m_Storage),
150 std::move(builder.m_TargetReport),
151 std::move(config),
152 std::move(builder.m_SequenceConfig),
153 std::move(builder.m_FinalizePolicy),
154 std::move(builder.m_ExpectationPolicies)};
155 }
156
157 template <typename... Sequences>
158 [[nodiscard]]
159 friend constexpr auto operator&&(BasicExpectationBuilder&& builder, sequence::detail::Config<Sequences...>&& config)
160 {
161 sequence::detail::Config newConfig = builder.m_SequenceConfig.concat(std::move(config));
162
163 using ExtendedExpectationBuilderT = BasicExpectationBuilder<
164 timesConfigured,
165 decltype(newConfig),
166 Signature,
167 FinalizePolicy,
168 Policies...>;
169
170 return ExtendedExpectationBuilderT{
171 std::move(builder.m_Storage),
172 std::move(builder.m_TargetReport),
173 std::move(builder.m_TimesConfig),
174 std::move(newConfig),
175 std::move(builder.m_FinalizePolicy),
176 std::move(builder.m_ExpectationPolicies)};
177 }
178
179 [[nodiscard]]
181 {
182 static_assert(
184 "For non-void return types, a finalize-policy must be specified. "
185 "See: https://dnkpp.github.io/mimicpp/db/d7a/group___e_x_p_e_c_t_a_t_i_o_n___f_i_n_a_l_i_z_e_r.html#details");
186
187 return ScopedExpectation{
188 std::move(m_Storage),
189 std::apply(
190 [&](auto&... policies) {
191 ControlPolicy controlPolicy{
192 sourceLocation,
193 std::move(m_TimesConfig),
194 std::move(m_SequenceConfig)};
195
197 Signature,
198 decltype(controlPolicy),
199 FinalizePolicy,
200 Policies...>;
201
202 return std::make_unique<Expectation>(
203 std::move(sourceLocation),
204 std::move(m_TargetReport),
205 std::move(controlPolicy),
206 std::move(m_FinalizePolicy),
207 std::move(policies)...);
208 },
209 m_ExpectationPolicies)};
210 }
211
212 private:
213 std::shared_ptr<StorageT> m_Storage;
214 reporting::TargetReport m_TargetReport;
215 detail::TimesConfig m_TimesConfig{};
216 SequenceConfig m_SequenceConfig{};
217 FinalizePolicy m_FinalizePolicy{};
218 PolicyListT m_ExpectationPolicies{};
219 };
220}
221
222namespace mimicpp::detail
223{
224 template <typename Param, typename... Canary, matcher_for<Param> Arg>
225 [[nodiscard]]
226 constexpr auto make_arg_matcher([[maybe_unused]] util::priority_tag<2> const, Arg arg)
227 {
228 return arg;
229 }
230
231 // if the param is a character-pointer, there is no evidence, whether it denotes a null-terminated string or just an
232 // actual pointer to a value.
233 // But, the Mock user shall know it, thus if `Arg` is not a character-pointer, we enable this matcher.
234 template <string Param, typename... Canary, string Arg>
235 requires(!std::is_pointer_v<std::remove_reference_t<Param>>)
236 || (!std::is_pointer_v<std::remove_reference_t<Arg>>)
237 [[nodiscard]] //
238 constexpr auto make_arg_matcher([[maybe_unused]] util::priority_tag<1> const, Arg&& arg)
239 {
240 return matches::str::eq(std::forward<Arg>(arg));
241 }
242
243 template <typename Param, typename... Canary, util::weakly_equality_comparable_with<Param> Arg>
244 [[nodiscard]]
245 constexpr auto make_arg_matcher([[maybe_unused]] util::priority_tag<0> const, Arg&& arg)
246 {
247 return matches::eq(std::forward<Arg>(arg));
248 }
249
250 inline constexpr util::priority_tag<2> maxMakeArgMatcherTag{};
251
252 template <typename Arg, typename Target>
253 concept requirement_for = requires {
254 {
255 detail::make_arg_matcher<Target>(maxMakeArgMatcherTag, std::declval<Arg>())
256 } -> matcher_for<Target>;
257 };
258
259 template <
260 typename Signature,
261 std::size_t index,
262 typename Arg,
263 typename... Canary,
265 requires requirement_for<Arg, Param>
266 constexpr auto make_arg_policy(Arg&& arg)
267 {
268 return expect::arg<index>(
269 detail::make_arg_matcher<Param>(maxMakeArgMatcherTag, std::forward<Arg>(arg)));
270 }
271
272 template <typename Signature, typename Builder, std::size_t... indices, typename... Args>
273 [[nodiscard]]
274 constexpr auto extend_builder_with_arg_policies(
275 Builder&& builder,
276 [[maybe_unused]] std::index_sequence<indices...> const,
277 Args&&... args)
278 {
279 return (
280 std::forward<Builder>(builder)
281 && ...
282 && detail::make_arg_policy<Signature, indices>(std::forward<Args>(args)));
283 }
284
285 template <typename Signature, typename... Args>
286 constexpr auto make_expectation_builder(
287 std::shared_ptr<ExpectationCollection<Signature>> expectations,
288 reporting::TargetReport target,
289 Args&&... args)
290 {
291 using BaseBuilderT = BasicExpectationBuilder<
292 false,
293 sequence::detail::Config<>,
294 Signature,
295 expectation_policies::InitFinalize>;
296
297 return detail::extend_builder_with_arg_policies<Signature>(
298 BaseBuilderT{
299 std::move(expectations),
300 std::move(target),
301 TimesConfig{},
302 sequence::detail::Config<>{},
303 expectation_policies::InitFinalize{},
304 std::tuple{}},
305 std::index_sequence_for<Args...>{},
306 std::forward<Args>(args)...);
307 }
308}
309
310#endif
#define MIMICPP_ASSERT(condition, msg)
Definition Config.hpp:51
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
ScopedExpectation finalize(util::SourceLocation sourceLocation) &&
Definition ExpectationBuilder.hpp:180
BasicExpectationBuilder(BasicExpectationBuilder &&)=default
friend constexpr auto operator&&(BasicExpectationBuilder &&builder, Policy &&policy)
Definition ExpectationBuilder.hpp:112
BasicExpectationBuilder & operator=(BasicExpectationBuilder &&)=default
friend constexpr auto operator&&(BasicExpectationBuilder &&builder, detail::TimesConfig &&config)
Definition ExpectationBuilder.hpp:134
ExpectationCollection< Signature > StorageT
Definition ExpectationBuilder.hpp:45
friend constexpr auto operator&&(BasicExpectationBuilder &&builder, sequence::detail::Config< Sequences... > &&config)
Definition ExpectationBuilder.hpp:159
std::tuple< Policies... > PolicyListT
Definition ExpectationBuilder.hpp:46
BasicExpectationBuilder & operator=(const BasicExpectationBuilder &)=delete
typename Expectation< Signature >::ReturnT ReturnT
Definition ExpectationBuilder.hpp:47
BasicExpectationBuilder(const BasicExpectationBuilder &)=delete
friend constexpr auto operator&&(BasicExpectationBuilder &&builder, Policy &&policy)
Definition ExpectationBuilder.hpp:82
constexpr BasicExpectationBuilder(std::shared_ptr< StorageT > storage, reporting::TargetReport target, detail::TimesConfig timesConfig, SequenceConfig sequenceConfig, FinalizePolicyArg &&finalizePolicyArg, PolicyListArg &&policyListArg) noexcept
Definition ExpectationBuilder.hpp:55
The actual expectation template.
Definition Expectation.hpp:487
Definition ControlPolicies.hpp:161
Collects all expectations for a specific (decayed) signature.
Definition Expectation.hpp:258
The base interface for expectations.
Definition Expectation.hpp:148
signature_return_type_t< Signature > ReturnT
The return type.
Definition Expectation.hpp:158
Takes the ownership of an expectation and check whether it's satisfied during destruction.
Definition Expectation.hpp:645
Contains the extracted mock info.
Definition TargetReport.hpp:22
A thin wrapper around general source-location info.
Definition SourceLocation.hpp:38
Determines, whether the given type satisfies the requirements of an expectation-policy for the given ...
Definition Expectation.hpp:439
Determines, whether the given type satisfies the requirements of a finalize-policy for the given sign...
Definition Expectation.hpp:453
constexpr auto arg(Matcher &&matcher, Projection &&projection={}) noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< Matcher >, Matcher > &&std::is_nothrow_constructible_v< std::remove_cvref_t< Projection >, Projection >)
Checks whether the selected argument satisfies the given matcher.
Definition ArgRequirementPolicies.hpp:207
constexpr auto eq(Pattern &&pattern)
Tests, whether the target string compares equal to the expected string.
Definition StringMatchers.hpp:157
constexpr auto eq(T &&value)
Tests, whether the target compares equal to the expected value.
Definition GeneralMatchers.hpp:306
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:278
Definition Call.hpp:24