6#ifndef MIMICPP_POLICIES_CONTROL_POLICY_HPP
7#define MIMICPP_POLICIES_CONTROL_POLICY_HPP
17#ifndef MIMICPP_DETAIL_IS_MODULE
27namespace mimicpp::detail
29 template <
typename... Sequences>
31 constexpr std::tuple<std::tuple<std::shared_ptr<Sequences>,
sequence::Id>...> make_sequence_entries(
32 util::SourceLocation loc,
33 std::tuple<std::shared_ptr<Sequences>...>
const& sequences)
noexcept
38 std::tuple<std::tuple<std::shared_ptr<Sequences>,
sequence::Id>...> result{};
40 [&]<std::size_t... indices>([[maybe_unused]] std::index_sequence<indices...>
const)
noexcept {
41 (..., (std::get<indices>(result) = std::tuple{
42 std::get<indices>(sequences),
43 std::get<indices>(sequences)->add(loc),
46 std::index_sequence_for<Sequences...>{});
54 TimesConfig() =
default;
57 constexpr TimesConfig(
int const min,
int const max)
63 throw std::invalid_argument{
64 "min must be less or equal to max and both must not be less than zero."};
72 constexpr int min() const noexcept
78 constexpr int max() const noexcept
94 constexpr std::tuple<std::vector<sequence::rating>, std::vector<reporting::SequenceReport>> gather_sequence_reports(
auto const& sequenceEntries)
96 std::vector<reporting::SequenceReport> inapplicable{};
97 std::vector<sequence::rating> ratings{};
99 auto const handleSequence = [&](
auto& seq,
sequence::Id const id) {
100 if (std::optional
const priority = seq->priority_of(
id))
102 ratings.emplace_back(*priority, seq->tag());
111 [&](
auto const&... entries) {
112 (..., handleSequence(std::get<0>(entries), std::get<1>(entries)));
116 return {std::move(ratings), std::move(inapplicable)};
124 auto const& sequenceEntries)
128 return reporting::state_saturated{
132 .sequences = std::apply(
133 [](
auto const&... entries) {
139 auto&& [ratings, inapplicable] = gather_sequence_reports(sequenceEntries);
140 if (!std::ranges::empty(inapplicable))
142 return reporting::state_inapplicable{
146 .sequences = std::move(ratings),
147 .inapplicableSequences = std::move(inapplicable)};
150 return reporting::state_applicable{
154 .sequenceRatings = std::move(ratings),
159 template <
typename... Sequences>
168 detail::TimesConfig
const& timesConfig,
169 sequence::detail::Config<Sequences...>
const& sequenceConfig) noexcept
170 : m_Min{timesConfig.min()},
171 m_Max{timesConfig.max()},
172 m_Sequences{detail::make_sequence_entries(std::move(loc), sequenceConfig.sequences())}
174 update_sequence_states();
180 return m_Min <= m_Count
187 return m_Count == m_Max;
193 return m_Count < m_Max
195 [](
auto const&... entries)
noexcept {
196 return (... && std::get<0>(entries)->is_consumable(std::get<1>(entries)));
206 [](
auto&... entries)
noexcept {
207 (..., std::get<0>(entries)->consume(std::get<1>(entries)));
212 update_sequence_states();
218 return detail::make_control_state(
230 std::tuple<std::shared_ptr<Sequences>,
sequence::Id>...>
233 constexpr void update_sequence_states() noexcept
235 if (m_Count == m_Max)
237 constexpr auto set_saturated = [](
auto& sequence,
auto const& id) { sequence->set_saturated(
id); };
239 [&](
auto&... entries)
noexcept { (..., std::apply(set_saturated, entries)); },
242 else if (m_Count == m_Min)
244 constexpr auto set_satisfied = [](
auto& sequence,
auto const& id) { sequence->set_satisfied(
id); };
246 [&](
auto&... entries)
noexcept { (..., std::apply(set_satisfied, entries)); },
283 constexpr auto times(
int const min,
int const max)
285 return mimicpp::detail::TimesConfig{min, max};
298 constexpr auto times(
int const exactly)
300 return mimicpp::detail::TimesConfig(exactly, exactly);
315 return mimicpp::detail::TimesConfig{min, std::numeric_limits<int>::max()};
330 return mimicpp::detail::TimesConfig{0, max};
342 constexpr mimicpp::detail::TimesConfig config{0, 0};
357 constexpr mimicpp::detail::TimesConfig config{1, 1};
372 constexpr mimicpp::detail::TimesConfig config{2, 2};
384 constexpr mimicpp::detail::TimesConfig config{0, std::numeric_limits<int>::max()};
#define MIMICPP_ASSERT(condition, msg)
Definition Config.hpp:51
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
reporting::control_state_t state() const
Definition ControlPolicies.hpp:216
constexpr void consume() noexcept
Definition ControlPolicies.hpp:201
constexpr ControlPolicy(util::SourceLocation loc, detail::TimesConfig const ×Config, sequence::detail::Config< Sequences... > const &sequenceConfig) noexcept
Definition ControlPolicies.hpp:166
constexpr bool is_satisfied() const noexcept
Definition ControlPolicies.hpp:178
static constexpr std::size_t sequenceCount
Definition ControlPolicies.hpp:163
constexpr bool is_saturated() const noexcept
Definition ControlPolicies.hpp:185
constexpr bool is_applicable() const noexcept
Definition ControlPolicies.hpp:191
A thin wrapper around general source-location info.
Definition SourceLocation.hpp:38
consteval auto never() noexcept
Specifies a times policy with both limits set to 0.
Definition ControlPolicies.hpp:340
constexpr auto times(int const min, int const max)
Specifies a times policy with a limit range.
Definition ControlPolicies.hpp:283
consteval auto any_times() noexcept
Specifies a times-policy with no constraints on how many times an expectation may match.
Definition ControlPolicies.hpp:382
constexpr auto at_least(int const min)
Specifies a times policy with just a lower limit.
Definition ControlPolicies.hpp:313
consteval auto twice() noexcept
Specifies a times policy with both limits set to 2.
Definition ControlPolicies.hpp:370
consteval auto once() noexcept
Specifies a times policy with both limits set to 1.
Definition ControlPolicies.hpp:355
constexpr auto at_most(int const max)
Specifies a times policy with just an upper limit.
Definition ControlPolicies.hpp:328
constexpr SequenceReport make_sequence_report(sequence::detail::BasicSequence< Id, priorityStrategy > const &seq)
Definition SequenceReport.hpp:36
std::variant< state_inapplicable, state_applicable, state_saturated > control_state_t
Denotes an expectation state.
Definition ExpectationReport.hpp:75
Definition ArgRequirementPolicies.hpp:125