mimic++ v2
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 Signature, std::size_t index, typename Arg>
199 requires matcher_for<
200 std::remove_cvref_t<Arg>,
202 [[nodiscard]]
203 constexpr auto make_arg_policy(Arg&& arg, [[maybe_unused]] const priority_tag<2>)
204 {
205 return expect::arg<index>(std::forward<Arg>(arg));
206 }
207
208 template <typename Signature, std::size_t index, std::equality_comparable_with<signature_param_type_t<index, Signature>> Arg>
209 [[nodiscard]]
210 constexpr auto make_arg_policy(Arg&& arg, [[maybe_unused]] const priority_tag<1>)
211 {
212 return expect::arg<index>(
213 matches::eq(std::forward<Arg>(arg)));
214 }
215
216 template <typename Signature, std::size_t index, typename Arg>
217 constexpr void
218 make_arg_policy(
219 [[maybe_unused]] Arg&& arg,
220 [[maybe_unused]] const priority_tag<0>
221 ) noexcept // NOLINT(cppcoreguidelines-missing-std-forward)
222 {
223 static_assert(
224 always_false<Arg>{},
225 "The provided argument is neither a matcher, nor is it equality comparable with the selected param.");
226 }
227
228 template <typename Signature, typename Builder, std::size_t... indices, typename... Args>
229 [[nodiscard]]
230 constexpr auto extend_builder_with_arg_policies(
231 Builder&& builder,
232 const std::index_sequence<indices...>,
233 Args&&... args
234 )
235 {
236 return (
237 std::forward<Builder>(builder)
238 && ...
239 && detail::make_arg_policy<Signature, indices>(
240 std::forward<Args>(args),
241 priority_tag<2>{}));
242 }
243
244 template <typename Signature, typename... Args>
245 constexpr auto make_expectation_builder(
246 std::shared_ptr<ExpectationCollection<Signature>> expectations,
247 Args&&... args
248 )
249 {
250 using BaseBuilderT = BasicExpectationBuilder<
251 false,
252 sequence::detail::Config<>,
253 Signature,
254 expectation_policies::InitFinalize
255 >;
256
257 return detail::extend_builder_with_arg_policies<Signature>(
258 BaseBuilderT{
259 std::move(expectations),
260 TimesConfig{},
261 sequence::detail::Config<>{},
262 expectation_policies::InitFinalize{},
263 std::tuple{}
264 },
265 std::index_sequence_for<Args...>{},
266 std::forward<Args>(args)...);
267 }
268}
269
270#define MIMICPP_DETAIL_UNIQUE_NAME(prefix, counter) prefix##counter
271#define MIMICPP_DETAIL_SCOPED_EXPECTATION_IMPL(counter) \
272 [[maybe_unused]] \
273 const ::mimicpp::ScopedExpectation MIMICPP_DETAIL_UNIQUE_NAME(_mimicpp_expectation_, counter) =
274
279#define MIMICPP_SCOPED_EXPECTATION MIMICPP_DETAIL_SCOPED_EXPECTATION_IMPL(__COUNTER__)
280
281#ifndef MIMICPP_CONFIG_ONLY_PREFIXED_MACROS
282
287 #define SCOPED_EXP MIMICPP_SCOPED_EXPECTATION
288
289#endif
290
291#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:166
Collects all expectations for a specific (decayed) signature.
Definition Fwd.hpp:81
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:303
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
Definition BoostTest.hpp:20
typename signature_param_type< index, Signature >::type signature_param_type_t
Definition Fwd.hpp:49