6#ifndef MIMICPP_MATCHERS_GENERAL_MATCHERS_HPP
7#define MIMICPP_MATCHERS_GENERAL_MATCHERS_HPP
20#ifndef MIMICPP_DETAIL_IS_MODULE
25 #include <type_traits>
29namespace mimicpp::detail
31 template <
typename Arg,
typename MatchesProjection = std::
identity,
typename DescribeProjection = pr
inting::Pr
intFn>
34 using matches_reference = std::invoke_result_t<MatchesProjection, const Arg&>;
35 using describe_reference = std::invoke_result_t<DescribeProjection, const Arg&>;
39 decltype(
auto) as_matches_arg()
const noexcept(std::is_nothrow_invocable_v<MatchesProjection, const Arg&>)
41 return std::invoke(MatchesProjection{}, arg);
44 decltype(
auto) as_describe_arg()
const noexcept(std::is_nothrow_invocable_v<DescribeProjection, const Arg&>)
46 return std::invoke(DescribeProjection{}, arg);
53 using type = arg_storage<T>;
56 template <
typename Arg,
typename MatchesProjection,
typename DescribeProjection>
57 struct to_arg_storage<arg_storage<Arg, MatchesProjection, DescribeProjection>>
59 using type = arg_storage<Arg, MatchesProjection, DescribeProjection>;
63 using to_arg_storage_t =
typename to_arg_storage<T>::type;
74 template <
typename Predicate,
typename... AdditionalArgs>
75 requires std::is_move_constructible_v<Predicate>
76 && (... && std::is_move_constructible_v<AdditionalArgs>)
80 using storage_t = std::tuple<detail::to_arg_storage_t<AdditionalArgs>...>;
82 using matches_reference_t =
typename detail::to_arg_storage_t<T>::matches_reference;
90 std::tuple<AdditionalArgs...> additionalArgs = {})
92 std::is_nothrow_move_constructible_v<Predicate>
93 && (... && std::is_nothrow_move_constructible_v<AdditionalArgs>))
94 : m_Predicate{std::move(predicate)},
95 m_FormatString{std::move(fmt)},
96 m_InvertedFormatString{std::move(invertedFmt)},
97 m_AdditionalArgs{std::move(additionalArgs)}
101 template <
typename First,
typename... Others>
102 requires std::predicate<
106 matches_reference_t<AdditionalArgs>...>
110 Others&... others)
const
112 std::is_nothrow_invocable_v<
116 matches_reference_t<AdditionalArgs>...>)
119 [&,
this](
auto&... additionalArgs) {
124 additionalArgs.as_matches_arg()...);
133 [&](
auto&... additionalArgs) {
134 std::array<
StringT,
sizeof...(additionalArgs)>
const descriptions{additionalArgs.as_describe_arg()...};
137 [&]<std::size_t... indices>(std::index_sequence<indices...>
const ) {
138 return format::vformat(m_FormatString, format::make_format_args(descriptions[indices]...));
140 std::index_sequence_for<AdditionalArgs...>{});
147 requires std::is_copy_constructible_v<Predicate>
148 && std::is_copy_constructible_v<storage_t>
150 return make_inverted(
152 m_InvertedFormatString,
160 return make_inverted(
161 std::move(m_Predicate),
162 std::move(m_InvertedFormatString),
163 std::move(m_FormatString),
164 std::move(m_AdditionalArgs));
168 [[no_unique_address]] Predicate m_Predicate;
171 storage_t m_AdditionalArgs;
173 template <
typename Fn>
175 static constexpr auto make_inverted(
181 using NotFnT =
decltype(std::not_fn(std::forward<Fn>(fn)));
183 std::not_fn(std::forward<Fn>(fn)),
185 std::move(invertedFmt),
195 template <
typename T>
197 : m_Value{std::forward<T>(value)},
199 m_PrintStrategy{&CapturedValue::print_to<std::remove_cvref_t<T>>}
203 using OutIter = std::ostreambuf_iterator<char>;
204 OutIter print_to(OutIter out)
const
209 return m_PrintStrategy(std::move(out), m_Fmt, m_Value);
216 PrintStrategy m_PrintStrategy;
218 template <
typename T>
222 return format::vformat_to(std::move(out), fmt, format::make_format_args(formatter));
230 using CapturedValue = detail::CapturedValue;
231 using CaptureSink = std::back_insert_iterator<std::vector<CapturedValue>>;
239 m_captureSink{std::move(captureSink)}
246 return m_Expectations;
249 template <
typename T>
252 *m_captureSink++ = CapturedValue{std::in_place, std::forward<T>(value)};
255 template <
typename T>
258 *m_captureSink++ = CapturedValue{std::in_place, std::forward<T>(value), std::move(fmt)};
263 CaptureSink m_captureSink;
266 template <
bool isInverted, util::unqualified Predicate, util::unqualified... Args>
267 requires std::is_move_constructible_v<Predicate>
268 && (... && std::is_move_constructible_v<Args>)
278 std::is_nothrow_move_constructible_v<Predicate>
279 && std::is_nothrow_move_constructible_v<ArgsStorage>)
280 : m_Predicate{std::move(predicate)},
281 m_FormatString{std::move(fmt)},
282 m_Args{std::move(args)}
286 template <
typename First,
typename... Others>
287 requires std::predicate<Predicate
const&, Context&, First&, Others&...>
291 std::vector<detail::CapturedValue> captures{};
294 describe_to(std::ostreambuf_iterator{ss});
296 if (
Context ctx{m_Args, std::back_inserter(captures)};
297 !isInverted == std::invoke(m_Predicate, ctx, first, others...))
302 if (!std::ranges::empty(captures))
304 ss <<
", but actually ";
305 auto iter = captures.cbegin();
306 iter->print_to(std::ostreambuf_iterator{ss});
308 for (++iter; iter != captures.cend(); ++iter)
311 iter->print_to(std::ostreambuf_iterator{ss});
320 requires std::is_copy_constructible_v<Predicate>
323 return GenericMatcher<!isInverted, Predicate, Args...>{m_Predicate, m_FormatString, m_Args};
329 return GenericMatcher<!isInverted, Predicate, Args...>{std::move(m_Predicate), std::move(m_FormatString), std::move(m_Args)};
333 Predicate m_Predicate;
334 format::vformat_string m_FormatString;
337 template <pr
int_iterator OutIter>
338 OutIter describe_to(OutIter out)
const
340 if constexpr (isInverted)
346 [&](
auto&&... args) {
347 return format::vformat_to(std::move(out), m_FormatString, format::make_format_args(args...));
349 std::tuple<format::fallback_formattable_t<Args const&>...>{m_Args});
351 if constexpr (isInverted)
360 template <
typename Predicate,
typename... Args>
363 Predicate && predicate,
369 std::forward<Predicate>(predicate),
371 std::forward_as_tuple(std::forward<Args>(args)...)};
394 template <
typename T>
398 template <
typename U>
479 template <
typename T>
487 template <
typename T>
489 constexpr auto eq(T&& value)
495 std::make_tuple(std::forward<T>(value))};
503 template <
typename T>
505 constexpr auto ne(T&& value)
511 std::make_tuple(std::forward<T>(value))};
519 template <
typename T>
521 constexpr auto lt(T&& value)
527 std::make_tuple(std::forward<T>(value))};
535 template <
typename T>
537 constexpr auto le(T&& value)
543 std::make_tuple(std::forward<T>(value))};
551 template <
typename T>
553 constexpr auto gt(T&& value)
559 std::make_tuple(std::forward<T>(value))};
567 template <
typename T>
569 constexpr auto ge(T&& value)
572 std::greater_equal{},
575 std::make_tuple(std::forward<T>(value))};
586 template <
typename UnaryPredicate>
591 StringViewT invertedDescription =
"fails predicate")
595 std::move(description),
596 std::move(invertedDescription),
606 template <util::satisfies<std::is_lvalue_reference> T>
611 []<
typename Other>(
auto& ctx, Other
const& target)
noexcept
612 requires std::is_convertible_v<std::remove_reference_t<T>
const volatile*, Other
const volatile*>
614 auto const& [expected] = ctx.expectations();
615 void const*
const targetPtr = std::addressof(target);
616 ctx.capture(targetPtr);
617 return expected == targetPtr;
620 static_cast<void const*
>(std::addressof(
instance)));
#define MIMICPP_ASSERT(condition, msg)
Definition Config.hpp:54
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
Definition GeneralMatchers.hpp:270
constexpr GenericMatcher(Predicate predicate, format::vformat_string fmt, ArgsStorage args) noexcept(std::is_nothrow_move_constructible_v< Predicate > &&std::is_nothrow_move_constructible_v< ArgsStorage >)
Definition GeneralMatchers.hpp:276
constexpr auto operator!() &&
Definition GeneralMatchers.hpp:327
MatchEvaluationContext< Args... > Context
Definition GeneralMatchers.hpp:272
constexpr auto operator!() const &
Definition GeneralMatchers.hpp:319
expectation::MatchResult matches(First &first, Others &... others) const
Definition GeneralMatchers.hpp:289
std::tuple< Args... > ArgsStorage
Definition GeneralMatchers.hpp:273
Definition GeneralMatchers.hpp:229
constexpr MatchEvaluationContext(expectation_refs expectations, CaptureSink captureSink)
Definition GeneralMatchers.hpp:237
void capture(T &&value)
Definition GeneralMatchers.hpp:250
std::tuple< std::unwrap_reference_t< Args > const &... > expectation_refs
Definition GeneralMatchers.hpp:234
constexpr expectation_refs expectations() const noexcept
Definition GeneralMatchers.hpp:244
void capture(T &&value, format::format_string< format::fallback_formattable_t< T > > fmt)
Definition GeneralMatchers.hpp:256
Generic matcher and the basic building block of most of the built-in matchers.
Definition GeneralMatchers.hpp:78
constexpr bool matches(First &first, Others &... others) const noexcept(std::is_nothrow_invocable_v< const Predicate &, First &, Others &..., matches_reference_t< AdditionalArgs >... >)
Definition GeneralMatchers.hpp:108
constexpr auto operator!() const &
Definition GeneralMatchers.hpp:146
constexpr auto operator!() &&
Definition GeneralMatchers.hpp:158
constexpr StringT describe() const
Definition GeneralMatchers.hpp:130
constexpr PredicateMatcher(Predicate predicate, StringViewT fmt, StringViewT invertedFmt, std::tuple< AdditionalArgs... > additionalArgs={}) noexcept(std::is_nothrow_move_constructible_v< Predicate > &&(... &&std::is_nothrow_move_constructible_v< AdditionalArgs >))
Definition GeneralMatchers.hpp:86
Matcher, which can be used to disambiguate between similar overloads.
Definition GeneralMatchers.hpp:396
static expectation::MatchResult matches(auto &&) noexcept
Definition GeneralMatchers.hpp:402
std::is_same< T, U > is_accepting
Definition GeneralMatchers.hpp:399
Matcher, which never fails.
Definition GeneralMatchers.hpp:380
static expectation::MatchResult matches(auto &&) noexcept
Definition GeneralMatchers.hpp:383
Determines, whether T is unqualified.
Definition Concepts.hpp:90
constexpr auto lt(T &&value)
Tests, whether the target is less than the expected value.
Definition GeneralMatchers.hpp:521
constexpr auto instance(T &&instance)
Tests whether the target is the expected instance.
Definition GeneralMatchers.hpp:608
constexpr auto le(T &&value)
Tests, whether the target is less than or equal to the expected value.
Definition GeneralMatchers.hpp:537
constexpr TypeMatcher< T > type
Matcher, which can be used as a last resort to disambiguate similar overloads.
Definition GeneralMatchers.hpp:480
constexpr WildcardMatcher _
The wildcard matcher, always matching.
Definition GeneralMatchers.hpp:472
constexpr auto eq(T &&value)
Tests, whether the target compares equal to the expected value.
Definition GeneralMatchers.hpp:489
constexpr auto gt(T &&value)
Tests, whether the target is greater than the expected value.
Definition GeneralMatchers.hpp:553
constexpr auto predicate(UnaryPredicate &&predicate, StringViewT description="passes predicate", StringViewT invertedDescription="fails predicate")
Tests, whether the target fulfills the given predicate.
Definition GeneralMatchers.hpp:588
constexpr auto ge(T &&value)
Tests, whether the target is greater than or equal to the expected value.
Definition GeneralMatchers.hpp:569
constexpr auto ne(T &&value)
Tests, whether the target compares not equal to the expected value.
Definition GeneralMatchers.hpp:505
std::variant< MatchSuccess, MatchFailure > MatchResult
Definition Common.hpp:41
Definition FloatingPointMatchers.hpp:25
constexpr auto make_generic_matcher(Predicate &&predicate, format::format_string< format::fallback_formattable_t< Args >... > const formatString, Args &&... args)
Definition GeneralMatchers.hpp:362
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