6#ifndef MIMICPP_REPORTING_STRINGIFY_REPORTS_HPP
7#define MIMICPP_REPORTING_STRINGIFY_REPORTS_HPP
22#ifndef MIMICPP_DETAIL_IS_MODULE
31namespace mimicpp::reporting::detail
33 template <pr
int_iterator OutIter>
34 OutIter stringify_stacktrace(OutIter out, util::Stacktrace
const& stacktrace)
36 if (!stacktrace.empty())
45 template <pr
int_iterator OutIter>
46 OutIter stringify_call_report_arguments(OutIter out, CallReport
const& call,
StringViewT const linePrefix)
48 if (call.argDetails.empty())
53 out = std::ranges::copy(linePrefix, std::move(out)).out;
57 auto const& [
type, state] : call.argDetails)
59 out = std::ranges::copy(linePrefix, std::move(out)).out;
61 out = std::ranges::copy(
type.name(), std::move(out)).out;
63 out = std::ranges::copy(state, std::move(out)).out;
70 template <pr
int_iterator OutIter>
71 OutIter stringify_call_report_from(OutIter out, CallReport
const& call)
75 if (!call.stacktrace.empty())
77 out = util::stacktrace::detail::print_entry(std::move(out), call.stacktrace, 0u);
88 template <pr
int_iterator OutIter>
89 OutIter stringify_call_report_target(OutIter out, CallReport
const& call)
93 "\tOn Target `{}` used Overload `{}`\n",
95 call.target.overloadReport.name());
100 template <pr
int_iterator OutIter>
101 OutIter stringify_expectation_report_from(OutIter out, ExpectationReport
const& expectation)
110 template <pr
int_iterator OutIter>
111 OutIter stringify_expectation_report_target(OutIter out, ExpectationReport
const& expectation)
115 "\tOf Target `{}` related to Overload `{}`\n",
116 expectation.target.name,
117 expectation.target.overloadReport.name());
122 template <pr
int_iterator OutIter>
123 OutIter stringify_expectation_report_requirement_adherences(
125 std::span<expectation::MatchResult const>
const adherences,
128 if (adherences.empty())
133 out = std::ranges::copy(linePrefix, std::move(out)).out;
136 for (
auto const& addherence : adherences)
138 auto const& [description] = std::get<expectation::MatchSuccess>(addherence);
141 out = std::ranges::copy(linePrefix, std::move(out)).out;
143 out = std::ranges::copy(*description, std::move(out)).out;
151 struct inapplicable_reason_printer
153 template <pr
int_iterator OutIter>
154 OutIter operator()([[maybe_unused]] OutIter out, [[maybe_unused]] state_applicable
const& state)
const
159 template <pr
int_iterator OutIter>
160 constexpr OutIter operator()(OutIter out, state_inapplicable
const& state)
const
162 auto const totalSequences = std::ranges::ssize(state.sequences)
163 + std::ranges::ssize(state.inapplicableSequences);
166 "it's not Head of {} Sequence(s) ({} total).\n",
167 std::ranges::ssize(state.inapplicableSequences),
170 MIMICPP_ASSERT(!state.inapplicableSequences.empty(),
"Inapplicable sequences can not be empty.");
171 for (
auto const& sequence : state.inapplicableSequences)
184 template <pr
int_iterator OutIter>
185 constexpr OutIter operator()(OutIter out, state_saturated
const& state)
const
189 "it's already saturated (matched {} out of {} times).\n",
197 template <pr
int_iterator OutIter>
198 OutIter stringify_expectation_report_requirement_violations(
200 std::span<expectation::MatchResult const>
const failures,
203 MIMICPP_ASSERT(!failures.empty(),
"Zero requirements can never be violated.");
205 out = std::ranges::copy(linePrefix, std::move(out)).out;
208 int withoutDescription{0};
209 for (
auto const& failure : failures)
211 auto const& [description] = std::get<expectation::MatchFailure>(failure);
214 out = std::ranges::copy(linePrefix, std::move(out)).out;
216 out = std::ranges::copy(*description, std::move(out)).out;
221 ++withoutDescription;
225 if (0 < withoutDescription)
227 out = std::ranges::copy(linePrefix, std::move(out)).out;
231 "{} Requirement(s) failed without further description.\n",
238 struct unfulfilled_reason_printer
240 template <pr
int_iterator OutIter>
241 OutIter operator()(OutIter out, state_applicable
const& state)
const
243 return stringify_times_state(
250 template <pr
int_iterator OutIter>
251 OutIter operator()(OutIter out, state_inapplicable
const& state)
const
253 return stringify_times_state(
260 template <pr
int_iterator OutIter>
261 OutIter operator()([[maybe_unused]] OutIter out, [[maybe_unused]] state_saturated
const& state)
const
267 template <pr
int_iterator OutIter>
268 static OutIter stringify_times_state(OutIter out,
int const current,
int const min,
int const max)
270 const auto verbalizeValue = [](OutIter o,
int const value) {
281 MIMICPP_ASSERT(current < min,
"State doesn't denote an unsatisfied state.");
288 out = verbalizeValue(std::move(out), min);
291 else if (max == std::numeric_limits<int>::max())
294 out = verbalizeValue(std::move(out), min);
301 "between {} and {} times ",
308 "was expected => requires {} further match(es).\n",
323 detail::stringify_call_report_from(std::ostreambuf_iterator{ss},
call);
324 detail::stringify_call_report_target(std::ostreambuf_iterator{ss},
call);
325 detail::stringify_call_report_arguments(std::ostreambuf_iterator{ss},
call,
"\t");
327 ss <<
"\t" <<
"Chose ";
328 detail::stringify_expectation_report_from(std::ostreambuf_iterator{ss}, match.
expectationReport);
335 [](
expectation::MatchResult const& m) ->
auto const& { return std::get<expectation::MatchSuccess>(m).description; });
336 detail::stringify_expectation_report_requirement_adherences(
337 std::ostreambuf_iterator{ss},
343 ss <<
"\t" <<
"Without any Requirements.\n";
346 detail::stringify_stacktrace(
347 std::ostreambuf_iterator{ss},
350 return std::move(ss).str();
361 detail::stringify_call_report_from(std::ostreambuf_iterator{ss},
call);
362 detail::stringify_call_report_target(std::ostreambuf_iterator{ss},
call);
363 detail::stringify_call_report_arguments(std::ostreambuf_iterator{ss},
call,
"\t");
365 ss << reports.size() <<
" inapplicable but otherwise matching Expectation(s):";
368 auto& report : reports)
370 auto& [expReport, matchReport] = report;
371 ss <<
"\n\t#" << ++i <<
" ";
372 detail::stringify_expectation_report_from(std::ostreambuf_iterator{ss}, expReport);
376 std::bind_front(detail::inapplicable_reason_printer{}, std::ostreambuf_iterator{ss}),
377 expReport.controlReport);
382 [](
expectation::MatchResult const& m) ->
auto const& {
return std::get<expectation::MatchSuccess>(m).description; });
383 detail::stringify_expectation_report_requirement_adherences(std::ostreambuf_iterator{ss}, matchReport,
"\t");
386 detail::stringify_stacktrace(
387 std::ostreambuf_iterator{ss},
390 return std::move(ss).str();
399 detail::stringify_call_report_from(std::ostreambuf_iterator{ss},
call);
400 detail::stringify_call_report_target(std::ostreambuf_iterator{ss},
call);
401 detail::stringify_call_report_arguments(std::ostreambuf_iterator{ss},
call,
"\t");
403 std::vector<MatchReport*> applicableReports{};
404 for (
auto& noMatch : noMatchReports)
406 if (std::holds_alternative<state_applicable>(noMatch.expectationReport.controlReport))
408 applicableReports.emplace_back(&noMatch);
412 if (applicableReports.empty())
414 ss <<
"No applicable Expectations available!\n";
418 ss << applicableReports.size() <<
" applicable non-matching Expectation(s):";
421 auto* report : applicableReports)
423 auto& [expReport, matchResults] = *report;
425 ss <<
"\n\t#" << ++i <<
" ";
426 detail::stringify_expectation_report_from(std::ostreambuf_iterator{ss}, expReport);
432 return std::visit([](
auto const& inner) ->
auto const& {
return inner.description; }, m);
434 std::ranges::subrange
const violations = std::ranges::stable_partition(
438 MIMICPP_ASSERT(!violations.empty(),
"Zero violations do not denote a no-match.");
439 detail::stringify_expectation_report_requirement_violations(std::ostreambuf_iterator{ss}, violations,
"\t");
440 detail::stringify_expectation_report_requirement_adherences(
441 std::ostreambuf_iterator{ss},
442 std::span{matchResults.data(), violations.data()},
447 detail::stringify_stacktrace(
448 std::ostreambuf_iterator{ss},
451 return std::move(ss).str();
459 ss <<
"Unfulfilled ";
460 detail::stringify_expectation_report_from(std::ostreambuf_iterator{ss}, expectationReport);
461 detail::stringify_expectation_report_target(std::ostreambuf_iterator{ss}, expectationReport);
464 std::bind_front(detail::unfulfilled_reason_printer{}, std::ostreambuf_iterator{ss}),
467 return std::move(ss).str();
474 std::exception_ptr
const& exception)
477 ss <<
"Unhandled Exception ";
481 std::rethrow_exception(exception);
483 catch (
const std::exception& e)
485 ss <<
"with message `" << e.what() <<
"`\n";
489 ss <<
"of unknown type.\n";
492 ss <<
"\t" <<
"While checking ";
493 detail::stringify_expectation_report_from(std::ostreambuf_iterator{ss}, expectationReport);
496 detail::stringify_call_report_from(std::ostreambuf_iterator{ss},
call);
497 detail::stringify_call_report_target(std::ostreambuf_iterator{ss},
call);
498 detail::stringify_call_report_arguments(std::ostreambuf_iterator{ss},
call,
"\t");
500 detail::stringify_stacktrace(
501 std::ostreambuf_iterator{ss},
504 return std::move(ss).str();
#define MIMICPP_ASSERT(condition, msg)
Definition Config.hpp:54
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
Contains the extracted info from a typed call::Info.
Definition CallReport.hpp:43
Contains the extracted info from a typed expectation.
Definition ExpectationReport.hpp:85
control_state_t controlReport
Definition ExpectationReport.hpp:89
Contains the expectation-report and the match-results to a specific call.
Definition MatchReport.hpp:22
ExpectationReport expectationReport
Definition MatchReport.hpp:24
expectation::MatchResults matchResults
Definition MatchReport.hpp:25
constexpr TypeMatcher< T > type
Matcher, which can be used as a last resort to disambiguate similar overloads.
Definition GeneralMatchers.hpp:480
constexpr printing::PrintFn print
Functional object, converting the given object to its textual representation.
Definition Print.hpp:183
std::variant< MatchSuccess, MatchFailure > MatchResult
Definition Common.hpp:41
Definition BasicReporter.hpp:26
StringT stringify_full_match(CallReport const &call, MatchReport match)
Definition StringifyReports.hpp:317
StringT stringify_unhandled_exception(CallReport const &call, ExpectationReport const &expectationReport, std::exception_ptr const &exception)
Definition StringifyReports.hpp:471
StringT stringify_unfulfilled_expectation(ExpectationReport const &expectationReport)
Definition StringifyReports.hpp:455
StringT stringify_inapplicable_matches(CallReport const &call, std::span< MatchReport > reports)
Definition StringifyReports.hpp:354
StringT stringify_no_matches(CallReport const &call, std::span< MatchReport > noMatchReports)
Definition StringifyReports.hpp:394
void unreachable()
Invokes undefined behavior.
Definition C++23Backports.hpp:40
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