light/modules/surface/private/system.test.cpp
light7734 e36991e6de
test(surface): add fuzz testing
test(surface): add & fix unit tests

fix(surface): bugs

refactor(surface): minor refactors & some edge-case handling
2025-07-31 08:11:05 +03:30

198 lines
5.3 KiB
C++

#include <surface/system.hpp>
#include <test/test.hpp>
using namespace lt;
using std::ignore;
using surface::SurfaceComponent;
using surface::System;
using test::Case;
using test::expect_eq;
using test::expect_ne;
using test::expect_not_nullptr;
using test::expect_throw;
using test::Suite;
constexpr auto title = "TestWindow";
constexpr auto width = 800u;
constexpr auto height = 600u;
constexpr auto vsync = true;
constexpr auto visible = false;
class Fixture
{
public:
[[nodiscard]] auto registry() -> Ref<ecs::Registry>
{
return m_registry;
}
auto add_surface_component(
SurfaceComponent::CreateInfo info = SurfaceComponent::CreateInfo {
.title = title,
.resolution = { width, height },
.vsync = vsync,
.visible = visible,
}
) -> SurfaceComponent &
{
auto entity = m_registry->create_entity("");
return entity.add_component<SurfaceComponent>(info);
}
void check_values(const SurfaceComponent &component)
{
expect_ne(std::get<SurfaceComponent::X11NativeHandle>(component.get_native_handle()), 0);
expect_eq(component.get_resolution().x, width);
expect_eq(component.get_resolution().y, height);
expect_eq(component.get_title(), title);
expect_eq(component.is_vsync(), vsync);
expect_eq(component.is_visible(), visible);
}
private:
Ref<ecs::Registry> m_registry = create_ref<ecs::Registry>();
};
Suite raii = [] {
Case { "happy path won't throw" } = [] {
auto fixture = Fixture {};
ignore = System { fixture.registry() };
};
Case { "many won't freeze/throw" } = [] {
auto fixture = Fixture {};
/* range is small since glfw init/terminate is slow. */
for (auto idx : std::views::iota(0, 100))
{
ignore = System { fixture.registry() };
}
};
Case { "unhappy path throws" } = [] {
expect_throw([] { ignore = System { {} }; });
auto fixture = Fixture {};
fixture.add_surface_component();
expect_throw([&] { ignore = System { { fixture.registry() } }; });
};
Case { "post construct has correct state" } = [] {
auto fixture = Fixture {};
auto system = System { fixture.registry() };
expect_eq(fixture.registry()->view<SurfaceComponent>()->size(), 0);
};
Case { "post destruct has correct state" } = [] {
auto fixture = Fixture {};
auto system = create_scope<System>(fixture.registry());
fixture.add_surface_component();
expect_eq(fixture.registry()->view<SurfaceComponent>()->size(), 1);
system.reset();
expect_eq(fixture.registry()->view<SurfaceComponent>()->size(), 0);
};
};
Suite system_events = [] {
Case { "on_register won't throw" } = [] {
auto fixture = Fixture {};
auto system = System { fixture.registry() };
system.on_register();
expect_eq(fixture.registry()->view<SurfaceComponent>().size(), 0);
};
Case { "on_unregister won't throw" } = [] {
auto fixture = Fixture {};
auto system = System { fixture.registry() };
system.on_register();
system.on_unregister();
expect_eq(fixture.registry()->view<SurfaceComponent>().size(), 0);
};
};
Suite registry_events = [] {
Case { "on_construct<SurfaceComponent> initializes component" } = [] {
auto fixture = Fixture {};
auto system = System { fixture.registry() };
const auto &component = fixture.add_surface_component();
expect_eq(fixture.registry()->view<SurfaceComponent>().size(), 1);
fixture.check_values(component);
};
Case { "unhappy on_construct<SurfaceComponent> throws" } = [] {
auto fixture = Fixture {};
auto system = System { fixture.registry() };
expect_throw([&] { fixture.add_surface_component({ .resolution = { width, 0 } }); });
expect_throw([&] { fixture.add_surface_component({ .resolution = { 0, height } }); });
expect_throw([&] {
fixture.add_surface_component(
{ .title = "", .resolution = { SurfaceComponent::max_dimension + 1, height } }
);
});
expect_throw([&] {
fixture.add_surface_component(
{ .title = "", .resolution = { width, SurfaceComponent::max_dimension + 1 } }
);
});
auto big_str = std::string {};
big_str.resize(SurfaceComponent::max_title_length + 1);
expect_throw([&] {
fixture.add_surface_component({ .title = big_str, .resolution = { width, height } });
});
};
Case { "unhappy on_construct<SurfaceComponent> removes component" } = [] {
auto fixture = Fixture {};
auto system = System { fixture.registry() };
expect_throw([&] { fixture.add_surface_component({ .resolution = { width, 0 } }); });
expect_eq(fixture.registry()->view<SurfaceComponent>().size(), 0);
};
Case { "on_destrroy<SurfaceComponent> cleans up component" } = [] {
auto fixture = Fixture {};
auto system = create_scope<System>(fixture.registry());
const auto &component = fixture.add_surface_component();
expect_eq(fixture.registry()->view<SurfaceComponent>().size(), 1);
fixture.check_values(component);
system.reset();
expect_eq(fixture.registry()->view<SurfaceComponent>().size(), 0);
};
};
Suite tick = [] {
Case { "ticking on empty registry won't throw" } = [] {
auto fixture = Fixture {};
System { fixture.registry() }.tick();
};
Case { "ticking on non-empty registry won't throw" } = [] {
auto fixture = Fixture {};
auto system = System { fixture.registry() };
fixture.add_surface_component();
system.tick();
};
Case { "ticking on chaotic registry won't throw" } = [] {
};
};
Suite property_setters = [] {
};
Suite listeners = [] {
};