light/modules/test/public/test.hpp

123 lines
2.3 KiB
C++
Raw Normal View History

#pragma once
#include <concepts>
#include <test/expects.hpp>
namespace lt::test {
namespace concepts {
template<typename T>
concept printable = requires(std::ostream &os, T t) {
{ os << t } -> std::same_as<std::ostream &>;
};
2025-07-25 15:07:13 +03:30
// clang-format off
template<class T, auto expr = []{}>
concept test = requires(T test) {
{ test.name } -> printable;
{ test = expr } -> std::same_as<void>;
};
2025-07-25 15:07:13 +03:30
// clang-format on
} // namespace concepts
namespace details {
class Registry
{
public:
using Suite = void (*)();
static void register_suite(Suite suite)
{
instance().m_suites.emplace_back(suite);
}
static auto run_all() -> int32_t
{
for (auto &test : instance().m_suites)
{
test();
}
std::cout << "Ran " << instance().m_failed_count + instance().m_pasesed_count << " tests:\n"
2025-07-16 13:18:08 +03:30
<< "\tpassed: " << instance().m_pasesed_count << '\n'
<< "\tfailed: " << instance().m_failed_count << '\n';
std::cout << "________________________________________________________________\n\n\n";
return instance().m_failed_count;
}
static void increment_passed_count()
{
++instance().m_pasesed_count;
}
static void increment_failed_count()
{
++instance().m_failed_count;
}
private:
Registry()
{
std::cout << "________________________________________________________________\n";
}
[[nodiscard]] static auto instance() -> Registry &
{
static auto registry = Registry {};
return registry;
}
std::vector<void (*)()> m_suites;
int32_t m_pasesed_count {};
int32_t m_failed_count {};
};
} // namespace details
struct Case
{
auto operator=(std::invocable auto test) -> void // NOLINT
{
std::cout << "[Running-----------] --> ";
std::cout << name << '\n';
try
{
test();
}
catch (const std::exception &exp)
{
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?
}
2025-07-16 13:18:08 +03:30
details::Registry::increment_passed_count();
std::cout << "[--------SUCCESS :D]" << "\n\n";
}
std::string_view name;
};
struct TestSuite
{
template<class TSuite>
constexpr TestSuite(TSuite suite)
{
#ifndef LIGHT_SKIP_TESTS
details::Registry::register_suite(+suite);
#endif
}
};
using Suite = const TestSuite;
} // namespace lt::test