Skip to content

test: introduce a GoogleTest unit-test harness covering the engine-logic core - #181

Merged
TommyRadan merged 8 commits into
masterfrom
test/unit-test-harness
Jun 16, 2026
Merged

test: introduce a GoogleTest unit-test harness covering the engine-logic core#181
TommyRadan merged 8 commits into
masterfrom
test/unit-test-harness

Conversation

@TommyRadan

@TommyRadan TommyRadan commented Jun 16, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a unit-test suite under tests/, built on GoogleTest (fetched from source via FetchContent, matching the SDL3/GLM/glslang approach) and registered with ctest. A standalone AlphaEngineTests executable compiles the device-free subsystem sources directly, so the suite links no GPU or window code and runs headless. Gated behind ALPHAENGINE_BUILD_TESTS (default ON); a new Linux CI job builds and runs it on every push/PR.

This is a pure addition (plus one small, behaviour-preserving refactor noted below) — no engine behaviour changes.

Coverage (97 tests, all device-free)

  • core/mathvec2/3/4, mat3/4, quat, aabb, sphere, frustum, scalar lerp
  • core::pool — insert/get/erase, generation-based handle invalidation, slot recycling
  • core::event_busemit, type keying, enqueue/flush FIFO ordering and in-flush deferral
  • core::jobsparallel_for coverage/correctness, dispatch + wait_idle
  • runtime::node — transform hierarchy, cached world matrices, find, active/effective-active flags, component-store attach/get/remove
  • asset_cache — dedup by key, builder-runs-only-on-miss, collect_unused() weak-ref semantics, GPU-buffer release on last-handle drop

The one refactor

To exercise the asset layer headless, asset_cache and the reference-counted asset handles (texture_asset, mesh_asset) now resolve their gpu device through a small accessor — rendering_engine::asset_device() — instead of reaching into the runtime::current_engine() global. The engine installs the live device via set_asset_device() (identical production behaviour); tests install a lightweight test_support::fake_device. This keeps the cache tests in the same lean, headless binary rather than dragging both gpu backends + glslang into the test target.

Conventions

  • tests/ is intentionally kept out of the clang-format/clang-tidy scope (GoogleTest macros don't fit the snake_case gate). Documented in docs/testing.md and CLAUDE.md.
  • Test/suite names are snake_case and follow the surrounding Allman/4-space style.

Validation

  • 97/97 tests pass locally (Ninja + GCC, headless).
  • The full production AlphaEngine binary builds and links cleanly with the asset-device refactor.
  • clang-format-18 passes on all touched production files.

Not in scope (follow-ups)

  • asset_cache::load_texture / load_font decode paths (need fixture files) — only the mesh path is tested.
  • core::settings / core::time (trivially device-free, just not in issue 166's target list).
  • The rendering engine proper (gpu backends, passes, materials, window, debug_ui) — needs a live GPU.

Closes #166

Introduce a unit-test suite under tests/, built on GoogleTest (fetched
from source via FetchContent, matching the SDL3/GLM/glslang approach) and
registered with ctest. A standalone AlphaEngineTests executable compiles
the device-free subsystem sources directly, so the suite links no GPU or
window code and runs headless.

Coverage (all device-free):
- core/math: vec2/3/4, mat3/4, quat, aabb, sphere, frustum, scalar lerp
- core::pool: insert/get/erase, generation invalidation, slot recycling
- core::event_bus: emit, type keying, enqueue/flush ordering and deferral
- core::jobs: parallel_for coverage/correctness, dispatch + wait_idle

Gated behind ALPHAENGINE_BUILD_TESTS (default ON). tests/ is kept out of
the clang-format/clang-tidy scope.
The asset cache and the reference-counted asset handles (texture_asset,
mesh_asset) reached the gpu device through the runtime::current_engine()
global, including from their destructors. That coupled the whole asset
layer — and anything linking it — to the engine, the window, and both gpu
backends.

Route them through a small accessor instead: rendering_engine::asset_device(),
installed by the engine via set_asset_device() once the device is live and
cleared as it is torn down. Production behaviour is unchanged (the accessor
returns the engine's device), but the asset layer can now be exercised against
a fake device with no engine, window, or backend present.
runtime::node: parent/child links and re-parenting, cached world matrices,
world_position/set_world_position, find, active/effective-active flags, and the
component-store attach/get/remove path — all device-free.

asset_cache: dedup by structural key, builder-runs-only-on-miss, collect_unused
weak-ref semantics, and that a mesh_asset frees its GPU buffers when the last
handle drops. A test_support::fake_device implements the gpu device interface
with recording stubs and is installed via set_asset_device, so the cache is
exercised headless with no engine or backend linked.
@TommyRadan
TommyRadan force-pushed the test/unit-test-harness branch from 6dc3420 to 9bd1db8 Compare June 16, 2026 20:49
M_PI is a POSIX extension that MSVC does not define without
_USE_MATH_DEFINES, so the math tests failed to compile in the Windows CI
build. Use a local constexpr pi constant instead.
SDL3 is built from source via FetchContent and its CMake requires X11 (or
Wayland) development libraries on Linux, or configure fails — even though
the device-free tests never open a window. Install the X11 dev packages so
the job configures.
@github-actions

Copy link
Copy Markdown

CI build artifacts

Windows Debug and Release builds are attached to the workflow run summary under Artifacts:

  • AlphaEngine-windows-Debug — Debug AlphaEngine.exe + Khronos validation layer
  • AlphaEngine-windows-Release — Release AlphaEngine.exe

Run #243 — commit 4a52bff.

@TommyRadan
TommyRadan merged commit c65f1de into master Jun 16, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

test: introduce a unit-test harness and cover the engine-logic core

1 participant