Skip to content

Commit

Permalink
Merge pull request #168 from CrustyAuklet/feat/list-tests-footer
Browse files Browse the repository at this point in the history
Catch2 emulation: list tests has a footer
  • Loading branch information
cschreib authored May 19, 2024
2 parents fe24bc4 + 4617561 commit f324947
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 130 deletions.
11 changes: 9 additions & 2 deletions include/snitch/snitch_registry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ class registry {
// Used when writing output to file.
std::optional<impl::file_writer> file_writer;

// the default console reporter
snitch::reporter::console::reporter console_reporter;

public:
enum class verbosity { quiet, normal, high, full } verbose = verbosity::normal;
bool with_color = SNITCH_DEFAULT_WITH_COLOR == 1;
Expand All @@ -122,8 +125,9 @@ class registry {
using report_function = snitch::report_function;
using finish_report_function = snitch::finish_report_function;

print_function print_callback = &snitch::impl::stdout_print;
report_function report_callback = &snitch::reporter::console::report;
print_function print_callback = &snitch::impl::stdout_print;
report_function report_callback = {
console_reporter, snitch::constant<&snitch::reporter::console::reporter::report>{}};
finish_report_function finish_callback = [](registry&) noexcept {};

// Internal API; do not use.
Expand Down Expand Up @@ -174,6 +178,9 @@ class registry {
const report_function& report,
const std::optional<finish_report_function>& finish);

// Internal API; do not use.
SNITCH_EXPORT std::string_view add_console_reporter();

// Internal API; do not use.
// Requires: number of tests + 1 <= max_test_cases, well-formed test ID.
SNITCH_EXPORT const char*
Expand Down
12 changes: 9 additions & 3 deletions include/snitch/snitch_reporter_console.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@
#include <string_view>

namespace snitch::reporter::console {
SNITCH_EXPORT void initialize(registry& r) noexcept;
struct reporter {
std::size_t counter = 0;

SNITCH_EXPORT bool configure(registry&, std::string_view, std::string_view) noexcept;
reporter() = default;

SNITCH_EXPORT void report(const registry& r, const snitch::event::data& event) noexcept;
SNITCH_EXPORT void init(registry& r) noexcept;

SNITCH_EXPORT bool configure(registry&, std::string_view, std::string_view) noexcept;

SNITCH_EXPORT void report(const registry& r, const snitch::event::data& event) noexcept;
};
} // namespace snitch::reporter::console

#endif
12 changes: 12 additions & 0 deletions src/snitch_registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,15 @@ std::string_view registry::add_reporter(
return name;
}

std::string_view registry::add_console_reporter() {
using reporter_type = snitch::reporter::console::reporter;
return add_reporter("console",
initialize_report_function{console_reporter, snitch::constant<&reporter_type::init>{}},
configure_report_function{console_reporter, snitch::constant<&reporter_type::configure>{}},
{console_reporter, snitch::constant<&snitch::reporter::console::reporter::report>{}},
{});
}

const char*
registry::add_impl(const test_id& id, const source_location& location, impl::test_ptr func) {
if (test_list.available() == 0u) {
Expand Down Expand Up @@ -1019,3 +1028,6 @@ small_vector_span<const registered_reporter> registry::reporters() const noexcep

constinit registry tests;
} // namespace snitch

static const std::string_view console_reporter_id [[maybe_unused]] =
snitch::tests.add_console_reporter();
217 changes: 104 additions & 113 deletions src/snitch_reporter_console.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,113 +84,13 @@ void print_message(const registry& r, const assertion_data& data) {
}},
data);
}

struct default_reporter_functor {
const registry& r;

void operator()(const snitch::event::test_run_started& e) const noexcept {
r.print(
make_colored("starting ", r.with_color, color::highlight2),
make_colored(e.name, r.with_color, color::highlight1),
make_colored(" with ", r.with_color, color::highlight2),
make_colored("snitch v" SNITCH_FULL_VERSION "\n", r.with_color, color::highlight1));
r.print("==========================================\n");
}

void operator()(const snitch::event::test_run_ended& e) const noexcept {
r.print("==========================================\n");

if (e.success) {
r.print(
make_colored("success:", r.with_color, color::pass), " all tests passed (",
e.run_count, " test cases, ", e.assertion_count, " assertions");
} else {
r.print(
make_colored("error:", r.with_color, color::fail), " ",
(e.fail_count == e.run_count ? "all" : "some"), " tests failed (", e.fail_count,
" out of ", e.run_count, " test cases, ", e.assertion_count, " assertions");
}

if (e.skip_count > 0) {
r.print(", ", e.skip_count, " test cases skipped");
}

#if SNITCH_WITH_TIMINGS
r.print(", ", e.duration, " seconds");
#endif

r.print(")\n");
}

void operator()(const snitch::event::test_case_started& e) const noexcept {
small_string<max_test_name_length> full_name;
make_full_name(full_name, e.id);

r.print(
make_colored("starting:", r.with_color, color::status), " ",
make_colored(full_name, r.with_color, color::highlight1), " at ", e.location.file, ":",
e.location.line, "\n");
}

void operator()(const snitch::event::test_case_ended& e) const noexcept {
small_string<max_test_name_length> full_name;
make_full_name(full_name, e.id);

#if SNITCH_WITH_TIMINGS
r.print(
make_colored("finished:", r.with_color, color::status), " ",
make_colored(full_name, r.with_color, color::highlight1), " (", e.duration, "s)\n");
#else
r.print(
make_colored("finished:", r.with_color, color::status), " ",
make_colored(full_name, r.with_color, color::highlight1), "\n");
#endif
}

void operator()(const snitch::event::test_case_skipped& e) const noexcept {
r.print(make_colored("skipped: ", r.with_color, color::skipped));
print_location(r, e.id, e.sections, e.captures, e.location);
r.print(" ", make_colored(e.message, r.with_color, color::highlight2), "\n");
}

void operator()(const snitch::event::assertion_failed& e) const noexcept {
if (e.expected) {
r.print(make_colored("expected failure: ", r.with_color, color::pass));
} else if (e.allowed) {
r.print(make_colored("allowed failure: ", r.with_color, color::pass));
} else {
r.print(make_colored("failed: ", r.with_color, color::fail));
}
print_location(r, e.id, e.sections, e.captures, e.location);
print_message(r, e.data);
}

void operator()(const snitch::event::assertion_succeeded& e) const noexcept {
r.print(make_colored("passed: ", r.with_color, color::pass));
print_location(r, e.id, e.sections, e.captures, e.location);
print_message(r, e.data);
}

void operator()(const snitch::event::list_test_run_started&) const noexcept {
r.print("Matching test cases:\n");
}

void operator()(const snitch::event::list_test_run_ended&) const noexcept {}

void operator()(const snitch::event::test_case_listed& e) {
small_string<max_test_name_length> full_name;
make_full_name(full_name, e.id);
r.print(" ", full_name, "\n");
if (!e.id.tags.empty()) {
r.print(" ", e.id.tags, "\n");
}
}
};
} // namespace

void initialize(registry&) noexcept {}
void reporter::init(registry&) noexcept {
counter = 0;
}

bool configure(registry& r, std::string_view option, std::string_view value) noexcept {
bool reporter::configure(registry& r, std::string_view option, std::string_view value) noexcept {
if (option == "color") {
parse_color_option(r, value);
return true;
Expand All @@ -203,14 +103,105 @@ bool configure(registry& r, std::string_view option, std::string_view value) noe
return false;
}

void report(const registry& r, const event::data& event) noexcept {
std::visit(default_reporter_functor{r}, event);
void reporter::report(const registry& r, const event::data& event) noexcept {
std::visit(
snitch::overload{
[&](const snitch::event::test_run_started& e) {
r.print(
make_colored("starting ", r.with_color, color::highlight2),
make_colored(e.name, r.with_color, color::highlight1),
make_colored(" with ", r.with_color, color::highlight2),
make_colored(
"snitch v" SNITCH_FULL_VERSION "\n", r.with_color, color::highlight1));
r.print("==========================================\n");
},
[&](const snitch::event::test_run_ended& e) {
r.print("==========================================\n");

if (e.success) {
r.print(
make_colored("success:", r.with_color, color::pass), " all tests passed (",
e.run_count, " test cases, ", e.assertion_count, " assertions");
} else {
r.print(
make_colored("error:", r.with_color, color::fail), " ",
(e.fail_count == e.run_count ? "all" : "some"), " tests failed (",
e.fail_count, " out of ", e.run_count, " test cases, ", e.assertion_count,
" assertions");
}

if (e.skip_count > 0) {
r.print(", ", e.skip_count, " test cases skipped");
}

#if SNITCH_WITH_TIMINGS
r.print(", ", e.duration, " seconds");
#endif

r.print(")\n");
},
[&](const snitch::event::test_case_started& e) {
small_string<max_test_name_length> full_name;
make_full_name(full_name, e.id);

r.print(
make_colored("starting:", r.with_color, color::status), " ",
make_colored(full_name, r.with_color, color::highlight1), " at ",
e.location.file, ":", e.location.line, "\n");
},
[&](const snitch::event::test_case_ended& e) {
small_string<max_test_name_length> full_name;
make_full_name(full_name, e.id);

#if SNITCH_WITH_TIMINGS
r.print(
make_colored("finished:", r.with_color, color::status), " ",
make_colored(full_name, r.with_color, color::highlight1), " (", e.duration,
"s)\n");
#else
r.print(
make_colored("finished:", r.with_color, color::status), " ",
make_colored(full_name, r.with_color, color::highlight1), "\n");
#endif
},
[&](const snitch::event::test_case_skipped& e) {
r.print(make_colored("skipped: ", r.with_color, color::skipped));
print_location(r, e.id, e.sections, e.captures, e.location);
r.print(
" ", make_colored(e.message, r.with_color, color::highlight2), "\n");
},
[&](const snitch::event::assertion_failed& e) {
if (e.expected) {
r.print(make_colored("expected failure: ", r.with_color, color::pass));
} else if (e.allowed) {
r.print(make_colored("allowed failure: ", r.with_color, color::pass));
} else {
r.print(make_colored("failed: ", r.with_color, color::fail));
}
print_location(r, e.id, e.sections, e.captures, e.location);
print_message(r, e.data);
},
[&](const snitch::event::assertion_succeeded& e) {
r.print(make_colored("passed: ", r.with_color, color::pass));
print_location(r, e.id, e.sections, e.captures, e.location);
print_message(r, e.data);
},
[&](const snitch::event::list_test_run_started&) {
r.print("Matching test cases:\n");
counter = 0;
},
[&](const snitch::event::list_test_run_ended&) {
r.print(counter, " matching test cases\n");
},
[&](const snitch::event::test_case_listed& e) {
small_string<max_test_name_length> full_name;
++counter;
make_full_name(full_name, e.id);
r.print(" ", full_name, "\n");
if (!e.id.tags.empty()) {
r.print(" ", e.id.tags, "\n");
}
}},
event);
}
} // namespace snitch::reporter::console

SNITCH_REGISTER_REPORTER_CALLBACKS(
"console",
&snitch::reporter::console::initialize,
&snitch::reporter::console::configure,
&snitch::reporter::console::report,
{});
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ Matching test cases:
test SECTION
test multiple SECTION
test SECTION & INFO
42 matching test cases
4 changes: 1 addition & 3 deletions tests/approval_tests/reporter_console.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ TEST_CASE("console reporter", "[reporters]") {
mock_framework framework;
register_tests_for_reporters(framework.registry);

framework.registry.add_reporter(
"console", &snitch::reporter::console::initialize, &snitch::reporter::console::configure,
&snitch::reporter::console::report, {});
framework.registry.add_console_reporter();

framework.registry.with_color = false;

Expand Down
2 changes: 1 addition & 1 deletion tests/runtime_tests/check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ SNITCH_WARNING_PUSH
SNITCH_WARNING_DISABLE_PRECEDENCE
SNITCH_WARNING_DISABLE_ASSIGNMENT

#if defined(SNITCH_COMPILER_MSVC) && _MSC_VER >= 1937 && _MSC_VER <= 1938
#if defined(__cpp_consteval) && __cpp_consteval <= 202211L
// Regression in MSVC compiler
// https://github.com/snitch-org/snitch/issues/140
// https://developercommunity.visualstudio.com/t/Regression:-False-positive-C7595:-std::/10509214
Expand Down
8 changes: 4 additions & 4 deletions tests/runtime_tests/registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,10 +583,9 @@ TEST_CASE("list tests", "[registry]") {
CAPTURE(tag);
console.messages.clear();

const auto header = "Matching test cases:\n"sv;

framework.registry.list_tests_with_tag(tag);
CHECK(console.messages == contains_substring(header));
CHECK(console.messages == contains_substring("Matching test cases:"));
CHECK(console.messages == contains_substring("matching test cases"));
if (tag == "[tag]"sv) {
CHECK(console.messages == contains_substring("how are you"));
CHECK(console.messages == contains_substring("how many lights"));
Expand Down Expand Up @@ -621,7 +620,8 @@ TEST_CASE("list tests", "[registry]") {
CHECK(console.messages == contains_substring("how many templated lights"));
CHECK(console.messages == contains_substring("hidden test 1"));
} else if (tag == "[wrong_tag]"sv || tag == "[.hidden]"sv) {
CHECK(console.messages == header);
const auto no_tests = "Matching test cases:\n0 matching test cases\n"sv;
CHECK(console.messages == no_tests);
}
}
}
Expand Down
1 change: 0 additions & 1 deletion tests/runtime_tests/section.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,6 @@ TEST_CASE("section readme example", "[test macros]") {
};

framework.registry.print_callback = print;
framework.registry.report_callback = &snitch::reporter::console::report;

framework.test_case.func = []() {
auto& reg = snitch::impl::get_current_test().reg;
Expand Down
4 changes: 1 addition & 3 deletions tests/testing_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,7 @@ std::optional<snitch::source_location> get_location(const owning_event::data& e)
}

mock_framework::mock_framework() noexcept {
registry.add_reporter(
"console", &snitch::reporter::console::initialize, &snitch::reporter::console::configure,
&snitch::reporter::console::report, {});
registry.add_console_reporter();

registry.print_callback = [](std::string_view msg) noexcept {
snitch::cli::console_print(msg);
Expand Down

0 comments on commit f324947

Please sign in to comment.