light/modules/test/test.cppm

150 lines
2.9 KiB
Text
Raw Normal View History

export module test.test;
import test.expects;
import test.registry;
2026-01-20 09:58:35 +03:30
import preliminary;
2026-02-02 13:56:25 +03:30
import logger;
///////////////////////////////////////
// ----------* INTERFACE *--------- //
/////////////////////////////////////
namespace lt::test {
class TestCase
{
public:
2026-02-02 13:56:25 +03:30
TestCase(std::string name);
// NOLINTNEXTLINE(misc-unconventional-assign-operator)
auto operator=(std::invocable auto test) const -> void;
private:
void run_normal(std::invocable auto test) const;
private:
2026-02-02 13:56:25 +03:30
std::string m_name;
};
struct TestSuite
{
TestSuite(auto body);
TestSuite() = default;
};
struct TestFuzzHarness
{
constexpr TestFuzzHarness(auto body);
};
export using Case = const TestCase;
export using Suite = const TestSuite;
export using FuzzHarness = const TestFuzzHarness;
2026-01-20 09:58:35 +03:30
export auto operator""_suite(const char *name, size_t size) -> TestSuite;
///////////////////////////////////////
// * IMPLEMENTATION -- TEMPLATES * //
/////////////////////////////////////
// NOLINTNEXTLINE(misc-unconventional-assign-operator)
auto TestCase::operator=(std::invocable auto test) const -> void
{
using enum Registry::ExecutionPolicy;
switch (Registry::get_options().execution_policy)
{
case normal: run_normal(std::move(test)); break;
case stats: Registry::increment_total_case_count(); break;
}
}
void TestCase::run_normal(std::invocable auto test) const
{
Registry::increment_total_case_count();
// NOLINTNEXTLINE
if (!std::regex_search(m_name.data(), Registry::get_case_regex()))
{
Registry::increment_skipped_case_count();
return;
}
Registry::increment_matched_case_count();
2026-02-02 13:56:25 +03:30
auto padding = std::string {};
padding.resize(79 - m_name.size());
for (auto &ch : padding)
{
ch = ' ';
}
try
{
test();
}
catch (const std::exception &exp)
{
2026-02-02 13:56:25 +03:30
log::test(
"\033[1;31m{}{} | {}\033[0m",
std::string_view { m_name },
std::string { padding },
std::string { exp.what() }
);
Registry::increment_failed_case_count();
if (Registry::should_return_on_failure())
{
throw;
}
return;
}
Registry::increment_passed_case_count();
2026-02-02 13:56:25 +03:30
log::test("{}{} | \033[1;32mpass\033[0m", std::string_view { m_name }, std::string { padding });
}
TestSuite::TestSuite(auto body)
{
#ifndef LIGHT_SKIP_TESTS
Registry::register_suite(+body);
#endif
}
constexpr TestFuzzHarness::TestFuzzHarness(auto body)
{
#ifndef LIGHT_SKIP_FUZZ_TESTS
Registry::register_fuzz_harness(+body);
#endif
};
2026-01-20 09:58:35 +03:30
auto operator""_suite(const char *name, size_t size) -> TestSuite
{
2026-01-09 21:53:37 +03:30
// TODO(Light): do we need the size parameter?
2026-01-20 09:58:35 +03:30
ignore = size;
2026-01-09 21:53:37 +03:30
Registry::set_last_suite_name(name);
return {};
}
} // namespace lt::test
//////////////////////////////////////
// -------* IMPLEMENTATION *------- //
/////////////////////////////////////
module :private;
namespace lt::test {
2026-02-02 13:56:25 +03:30
TestCase::TestCase(std::string name): m_name(name)
{
2026-02-02 13:56:25 +03:30
if (m_name.size() > 79u)
{
m_name.resize(79u - 3);
m_name.append("...");
}
}
} // namespace lt::test