feat(test): add option parsing && the --stop-on-fail & -h options

This commit is contained in:
light7734 2025-09-29 09:47:59 +03:30
parent cce627a350
commit 723ade84ea
Signed by: light7734
GPG key ID: 8C30176798F1A6BA
2 changed files with 93 additions and 9 deletions

View file

@ -1,15 +1,59 @@
#include <test/test.hpp>
auto main() -> int32_t
using namespace ::lt::test;
using namespace ::lt::test::details;
void parse_option(std::string_view option, Registry::Options &options)
{
if (option == "--stop-on-fail")
{
options.stop_on_fail = true;
return;
}
throw std::invalid_argument { std::format("Invalid argument: {}", option) };
}
void print_help()
{
std::println("Options: ");
std::println("--stop-on-fail --> Stops executing the remaining tests on first failure");
std::println("--stats --> Print statistics about the tests without running any");
std::println("--help | -h --> ~You just used it! :D");
}
auto main(int32_t argc, char **argv) -> int32_t
try
{
using namespace ::lt::test;
using namespace ::lt::test::details;
auto raw_arguments = std::span<char *>(argv, argc);
return Registry::run_all();
auto options = Registry::Options {};
for (auto idx = 0; auto &raw_argument : raw_arguments)
{
// First argument is the "cwd'
if (idx++ == 0)
{
continue;
}
auto argument = std::string_view(raw_argument);
if (argument == "-h" || argument == "--help")
{
print_help();
return 0;
}
if (argument.starts_with("--") || argument.starts_with("-"))
{
parse_option(argument, options);
}
}
return Registry::run_all(options);
}
catch (const std::exception &exp)
{
std::cout << "Terminated after uncaught exception:\n"; // NOLINT
std::cout << "Terminated after uncaught exception:\n";
std::cout << "exception.what: " << exp.what();
}

View file

@ -10,6 +10,11 @@ namespace details {
class Registry
{
public:
struct Options
{
bool stop_on_fail = false;
};
using FuzzFunction = int32_t (*)(const uint8_t *, size_t);
using SuiteFunction = void (*)();
@ -30,11 +35,29 @@ public:
instance().m_fuzz_harness = suite;
}
static auto run_all() -> int32_t
static auto run_all(Options options) -> int32_t
{
instance().m_options = options;
instance().print_options();
for (auto &test : instance().m_suites)
{
test();
try
{
test();
}
catch (const std::exception &exp)
{
if (options.stop_on_fail)
{
std::println("Quitting due to options.stop_on_fail == true");
break;
}
std::println("Uncaught exception when running suite:");
std::println("\twhat: {}", exp.what());
break;
}
}
std::cout << "Ran " << instance().m_failed_count + instance().m_pasesed_count << " tests:\n"
@ -67,7 +90,17 @@ public:
++instance().m_failed_count;
}
static auto should_return_on_failure() -> bool
{
return instance().m_options.stop_on_fail;
}
private:
void print_options()
{
std::println("stop-on-failure: {}", m_options.stop_on_fail);
}
Registry()
{
std::cout << "________________________________________________________________\n";
@ -79,6 +112,8 @@ private:
return registry;
}
Options m_options {};
std::vector<SuiteFunction> m_suites;
FuzzFunction m_fuzz_harness {};
@ -92,7 +127,8 @@ private:
struct Case
{
auto operator=(std::invocable auto test) -> void // NOLINT
// NOLINTNEXTLINE(misc-unconventional-assign-operator)
auto operator=(std::invocable auto test) -> void
{
std::cout << "[Running-----------] --> ";
std::cout << name << '\n';
@ -106,7 +142,11 @@ struct Case
std::cout << exp.what() << "\n";
std::cout << "[-----------FAIL !!]" << "\n\n";
details::Registry::increment_failed_count();
return; // TODO(Light): Should we run the remaining tests after a failure?
if (details::Registry::should_return_on_failure())
{
throw;
}
}
details::Registry::increment_passed_count();