mimic++ v10.0.1
Loading...
Searching...
No Matches
RequirementPolicies.hpp
Go to the documentation of this file.
1// Copyright Dominic (DNKpp) Koepke 2024-2026.
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_POLICIES_ARG_REQUIREMENT_POLICIES_HPP
7#define MIMICPP_EXPECTATION_POLICIES_ARG_REQUIREMENT_POLICIES_HPP
8
9#pragma once
10
18
19#ifndef MIMICPP_DETAIL_IS_MODULE
20 #include <concepts>
21 #include <cstddef>
22 // ReSharper disable once CppUnusedIncludeDirective
23 #include <functional> // std::invoke
24 #include <tuple>
25 #include <type_traits>
26 #include <utility>
27#endif
28
30{
31 template <typename Matcher>
33 {
34 using matches_fn = mimicpp::detail::matches_hook::matches_fn;
35
36 public:
37 Matcher const& matcher;
38
39 template <typename... Args>
40 requires std::invocable<matches_fn, Matcher const&, Args&...>
41 [[nodiscard]]
42 // projected arguments may come as value, so Args& won't work in all cases
43 // just forward them as lvalue-ref
44 MatchResult operator()(Args&&... args) const
45 noexcept(std::is_nothrow_invocable_v<matches_fn, Matcher const&, Args&...>)
46 {
47 return mimicpp::detail::matches_hook::matches(matcher, args...);
48 }
49 };
50
51 template <typename Matcher, typename MatchesStrategy, typename DescribeStrategy>
53 {
54 public:
55 [[nodiscard]]
56 explicit constexpr ArgsRequirement(Matcher matcher, MatchesStrategy matchesStrategy, DescribeStrategy describeStrategy)
57 noexcept(
58 std::is_nothrow_move_constructible_v<Matcher>
59 && std::is_nothrow_move_constructible_v<MatchesStrategy>
60 && std::is_nothrow_move_constructible_v<DescribeStrategy>)
61 : m_Matcher{std::move(matcher)},
62 m_MatchesStrategy{std::move(matchesStrategy)},
63 m_DescribeStrategy{std::move(describeStrategy)}
64 {
65 }
66
67 [[nodiscard]]
68 static constexpr bool is_satisfied() noexcept
69 {
70 return true;
71 }
72
73 template <typename Return, typename... Args>
74 requires std::is_invocable_r_v<MatchResult, MatchesStrategy const&, matcher_matches_fn<Matcher>, call::Info<Return, Args...> const&>
75 [[nodiscard]]
77 noexcept(std::is_nothrow_invocable_v<MatchesStrategy const&, matcher_matches_fn<Matcher>, call::Info<Return, Args...> const&>)
78 {
79 matcher_matches_fn<Matcher> const matches{m_Matcher};
80 auto result = std::invoke(m_MatchesStrategy, matches, info);
81 std::visit(
82 [&](auto& inner) {
83 if (auto& description = inner.description)
84 {
85 description = std::invoke(m_DescribeStrategy, *description);
86 }
87 },
88 result);
89
90 return result;
91 }
92
93 template <typename Return, typename... Args>
94 static constexpr void consume([[maybe_unused]] call::Info<Return, Args...> const& info) noexcept
95 {
96 }
97
98 private:
99 Matcher m_Matcher;
100 [[no_unique_address]] MatchesStrategy m_MatchesStrategy;
101 [[no_unique_address]] DescribeStrategy m_DescribeStrategy;
102 };
103
104 template <typename Target, typename Matcher>
107 {
108 public:
111
112 ~ThatRequirement() = default;
113
114 [[nodiscard]]
117
118 [[nodiscard]]
119 explicit constexpr ThatRequirement(Target target, Matcher condition)
120 noexcept(std::is_nothrow_move_constructible_v<Target> && std::is_nothrow_move_constructible_v<Matcher>)
121 : m_Target{std::move(target)},
122 m_Matcher{std::move(condition)}
123 {
124 }
125
126 [[nodiscard]]
127 static constexpr bool is_satisfied() noexcept
128 {
129 return true;
130 }
131
132 template <typename Return, typename... Args>
133 [[nodiscard]]
135 {
136 return mimicpp::detail::matches_hook::matches(m_Matcher, util::unwrap_ref(m_Target));
137 }
138
139 template <typename Return, typename... Args>
140 static constexpr void consume(call::Info<Return, Args...> const& /*call*/) noexcept
141 {
142 }
143
144 private:
145 Target m_Target;
146 Matcher m_Matcher;
147 };
148}
149
150namespace mimicpp::expectation::policies::detail
151{
152 template <std::size_t index, std::size_t... others>
153 struct arg_requirement_describer
154 {
155 [[nodiscard]]
156 StringT operator()(StringViewT const matcherDescription) const
157 {
158 StringStreamT out{};
159 out << "expect: arg[" << index;
160 ((out << ", " << others), ...);
161 out << "] " << matcherDescription;
162 return std::move(out).str();
163 }
164 };
165
166 struct all_args_requirement_describer
167 {
168 [[nodiscard]]
169 StringT operator()(StringViewT const matcherDescription) const
170 {
171 StringStreamT out{};
172 out << "expect: arg[all] " << matcherDescription;
173 return std::move(out).str();
174 }
175 };
176
177 template <
178 std::size_t... indices,
179 typename Matcher,
180 typename... Projections>
181 [[nodiscard]]
182 constexpr auto make_args_policy(
183 Matcher&& matcher,
184 std::tuple<Projections...>&& projections)
185 {
186 static_assert(
187 sizeof...(indices) == sizeof...(Projections),
188 "Indices and projections size mismatch.");
189
190 using arg_selector_t = args_selector_fn<
191 std::add_lvalue_reference_t,
192 std::index_sequence<indices...>>;
193 using apply_strategy_t = arg_list_indirect_apply_fn<std::remove_cvref_t<Projections>...>;
194 using describe_strategy_t = arg_requirement_describer<indices...>;
195
196 return ArgsRequirement{
197 std::forward<Matcher>(matcher),
198 apply_args_fn(
199 arg_selector_t{},
200 apply_strategy_t{std::move(projections)}),
201 describe_strategy_t{}};
202 }
203}
204
206{
217
231 template <std::size_t index, typename Matcher, typename Projection = std::identity>
232 [[nodiscard]]
233 constexpr auto arg(Matcher&& matcher, Projection&& projection = {}) //
234 noexcept(
235 std::is_nothrow_constructible_v<std::remove_cvref_t<Matcher>, Matcher>
236 && std::is_nothrow_constructible_v<std::remove_cvref_t<Projection>, Projection>)
237 {
238 return expectation::policies::detail::make_args_policy<index>(
239 std::forward<Matcher>(matcher),
240 std::forward_as_tuple(std::forward<Projection>(projection)));
241 }
242
264 template <
265 std::size_t first,
266 std::size_t... others,
267 typename Matcher,
268 typename... Projections>
269 [[nodiscard]]
270 constexpr auto args(Matcher&& matcher, Projections&&... projections) //
271 noexcept(
272 std::is_nothrow_constructible_v<std::remove_cvref_t<Matcher>, Matcher>
273 && (... && std::is_nothrow_move_constructible_v<std::remove_cvref_t<Projections>>))
274 {
275 static_assert(
276 sizeof...(projections) <= 1u + sizeof...(others),
277 "The projection count exceeds the amount of indices.");
278
279 return expectation::policies::detail::make_args_policy<first, others...>(
280 std::forward<Matcher>(matcher),
281 util::detail::expand_tuple<std::identity, 1u + sizeof...(others)>(
282 std::forward_as_tuple(std::forward<Projections>(projections)...)));
283 }
284
297 template <typename Matcher>
298 [[nodiscard]]
299 constexpr auto all_args(Matcher&& matcher) //
300 noexcept(std::is_nothrow_constructible_v<std::remove_cvref_t<Matcher>, Matcher>)
301 {
302 using arg_selector_t = expectation::policies::detail::all_args_selector_fn<std::add_lvalue_reference_t>;
303 using apply_strategy_t = expectation::policies::detail::arg_list_forward_apply_fn;
304 using describe_strategy_t = expectation::policies::detail::all_args_requirement_describer;
305
307 std::forward<Matcher>(matcher),
308 expectation::policies::detail::apply_args_fn(arg_selector_t{}, apply_strategy_t{}),
309 describe_strategy_t{}};
310 }
311
336 template <typename Target, matcher_for<Target> Matcher>
337 [[nodiscard]]
338 constexpr auto that(Target&& target, Matcher&& matcher)
339 {
340 return expectation::policies::ThatRequirement{std::forward<Target>(target), std::forward<Matcher>(matcher)};
341 }
342
346}
347
348#endif
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
Definition Call.hpp:27
Definition RequirementPolicies.hpp:53
constexpr ArgsRequirement(Matcher matcher, MatchesStrategy matchesStrategy, DescribeStrategy describeStrategy) noexcept(std::is_nothrow_move_constructible_v< Matcher > &&std::is_nothrow_move_constructible_v< MatchesStrategy > &&std::is_nothrow_move_constructible_v< DescribeStrategy >)
Definition RequirementPolicies.hpp:56
static constexpr void consume(call::Info< Return, Args... > const &info) noexcept
Definition RequirementPolicies.hpp:94
MatchResult matches(call::Info< Return, Args... > const &info) const noexcept(std::is_nothrow_invocable_v< MatchesStrategy const &, matcher_matches_fn< Matcher >, call::Info< Return, Args... > const & >)
Definition RequirementPolicies.hpp:76
static constexpr bool is_satisfied() noexcept
Definition RequirementPolicies.hpp:68
Definition RequirementPolicies.hpp:107
ThatRequirement(ThatRequirement const &)=delete
static constexpr bool is_satisfied() noexcept
Definition RequirementPolicies.hpp:127
constexpr ThatRequirement(Target target, Matcher condition) noexcept(std::is_nothrow_move_constructible_v< Target > &&std::is_nothrow_move_constructible_v< Matcher >)
Definition RequirementPolicies.hpp:119
ThatRequirement & operator=(ThatRequirement &&)=default
ThatRequirement(ThatRequirement &&)=default
static constexpr void consume(call::Info< Return, Args... > const &) noexcept
Definition RequirementPolicies.hpp:140
MatchResult matches(call::Info< Return, Args... > const &) const
Definition RequirementPolicies.hpp:134
ThatRequirement & operator=(ThatRequirement const &)=delete
Definition Common.hpp:206
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 RequirementPolicies.hpp:233
constexpr auto all_args(Matcher &&matcher) noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< Matcher >, Matcher >)
Checks whether the all arguments satisfy the given matcher.
Definition RequirementPolicies.hpp:299
constexpr auto args(Matcher &&matcher, Projections &&... projections) noexcept(std::is_nothrow_constructible_v< std::remove_cvref_t< Matcher >, Matcher > &&(... &&std::is_nothrow_move_constructible_v< std::remove_cvref_t< Projections > >))
Checks whether the selected arguments satisfy the given matcher.
Definition RequirementPolicies.hpp:270
constexpr auto that(Target &&target, Matcher &&matcher)
Checks whether the given target satisfies the given matcher.
Definition RequirementPolicies.hpp:338
Definition ControlPolicies.hpp:254
Definition ArgumentList.hpp:24
std::variant< MatchSuccess, MatchFailure > MatchResult
Definition Common.hpp:41
constexpr T & unwrap_ref(std::reference_wrapper< T > const ref) noexcept
Unwraps the given std::reference_wrapper and returns the referenced object.
Definition UnwrapRef.hpp:29
std::basic_ostringstream< CharT, CharTraitsT > StringStreamT
Definition Format.hpp:38
std::basic_string_view< CharT, CharTraitsT > StringViewT
Definition Fwd.hpp:398
std::basic_string< CharT, CharTraitsT > StringT
Definition Fwd.hpp:397
Definition RequirementPolicies.hpp:33
mimicpp::detail::matches_hook::matches_fn matches_fn
Definition RequirementPolicies.hpp:34
Matcher const & matcher
Definition RequirementPolicies.hpp:37
MatchResult operator()(Args &&... args) const noexcept(std::is_nothrow_invocable_v< matches_fn, Matcher const &, Args &... >)
Definition RequirementPolicies.hpp:44