Skip to content

Testing

magmacrunchmedia edited this page Aug 28, 2026 · 2 revisions

Testing

build.bat test

236 checks across 7 suites, 41 named groups. Each test is its own binary, linked against the pure modules only: no GPU, no window, no mocking, no framework. The harness (tests/harness.h, ported from magnolia) counts checks, prints what failed and what it wanted, and exits non-zero.

The tests assert physics, not pixels. Almost every check compares against a number that can be worked out by hand, and most of the test files carry the derivation in a comment. That is the point: a rendering test that only says "this frame looks like it did yesterday" cannot tell you the optics were ever right.

Suite Checks
test_linalg 65 Vector arithmetic, reflection, Snell, Fresnel, the grating equation.
test_geometry 47 Rays against spheres, planes, parallelograms and conic dishes.
test_trace 40 The walk end to end: shading, mirrors, glass, spectral, polarization, focusing, orders.
test_spectrum 28 Wavelength sampling, CIE weights, albedo bands, Cauchy dispersion.
test_timestep 26 The fixed-step accumulator (inherited from magnolia).
test_polar 18 Stokes/Mueller: Malus, the paradox, Brewster, waveplates, TIR phase.
test_collision 12 Falling, wall stops, sliding, jumping.

The checks worth knowing about

These are the ones that would catch a real regression rather than a typo.

Closed-form optics

  • Snell to the decimal. 30° into n=1.5 emerges at 19.4712°, with the x-component exactly 1/3. The critical angle is bracketed from both sides: 41° escapes, 43° is trapped.
  • Fresnel at the landmarks. 4% at normal incidence; the p-component vanishing at Brewster's angle, giving degree of polarization exactly 1; reciprocity across the interface; R + T = 1 per polarization; and TIR's 36.9° phase difference for glass-to-air at 45°.
  • Abbe number. Feed the Cauchy model BK7's n_d = 1.5168, B = 0.0042 and the computed (n_d − 1)/(n_F − n_C) lands on 64.4, against a catalogue ~64.2. That single number validates the whole dispersion model.
  • Malus at five angles, and the three-polarizer paradox to the exact eighth: crossed polarizers pass 0, a 45° third between them passes 0.125. The second is the check that proves the Mueller machinery is real and not a filter metaphor.
  • Littrow. At sin θ = λ/2d the m = −1 order retroreflects exactly, the alignment every grating lab uses. Plus the conical invariant (the groove component conserved) and an order going evanescent past 90°.

Geometry that catches wrong normals

  • A paraboloid focuses every zone at R/2. Parallel rays at three different radii must all reflect through the focus. A wrong sag fails this; so does a correct sag with a wrong normal, which a sag-only test would pass.
  • An ellipsoid images focus onto focus at three angles, the property whisper galleries and X-ray telescope tolerances both live on.
  • Both survive an arbitrary rotation of the dish frame, which is what catches a basis built inconsistently between CPU and GPU.
  • The Gram solve. A skewed parallelogram rejects a point that independent edge projections would wrongly accept. That test exists because the naive version is right for rectangles and quietly wrong for everything else.

Scene-level invariants

  • The mirror-image property. Looking through a perfect mirror at a sphere equals looking directly at that sphere's mirrored position. Two scenes, one ray, identical colour.
  • Per-bounce attenuation. Five bounces off half-red mirrors attenuate red by exactly 0.5⁵.
  • Trapped light gives up dark. Perpendicular between two perfect mirrors, the walk hits its cap and returns black. Not a hang, not a stack overflow.
  • Glass neither makes nor eats light. A clear ball's branch weights sum to the hand-computed 0.998464, the shortfall being one branch legitimately culled by the throughput floor.
  • Spectral equals RGB on neutral scenes. A gray achromatic scene must render identically through both pipelines. Any daylight between them is a bug, not physics.
  • At the focus, the whole dish is the sun: exactly the disk intensity on the focus, plain sky half a metre off it.
  • An order appears as the wavelength shortens. Three orders propagate at 550 nm through a 1 µm grating; at 450 nm the second joins and the sum rises from 0.6 to 0.8. The grating equation, audited by addition.

The other half: the oracle

Host tests cover the arithmetic. They cannot tell you the shader computes the same thing. For that, every GPU example accepts --diff:

build\m9_spectrum.exe --diff

which renders the frame on the GPU, reads it back, renders it again through cpu_trace.c, and compares. Exit code is the verdict. See Architecture § the oracle for the bars and what the outlier allowance is for.

Run both before committing:

build.bat test
for %e in (m2_gpu m3_mirrors m4_glass m5_spectral m6_polarization m7_room m8_furnace m9_spectrum) do build\%e.exe --diff

Writing a new check

Put the derivation in the comment and the number in the assertion:

/* Brewster's angle, atan(1.5) = 56.31 degrees: the p-polarization
   vanishes -- the reflection is perfectly polarized. rs works out to
   0.1479 there, so unpolarized light reflects about 7.4%. */
float brewster = atanf(1.5f);
holo_fresnel(cosf(brewster), 1.0f, 1.5f, &rs, &rp);
check_close(rp, 0.0f, "p vanishes at Brewster");
check_close(rs, 0.1479f, "s at Brewster");

check_close uses an absolute tolerance of 1e-4, generous against float epsilon, far below anything a wrong formula produces. If you find yourself loosening it, the formula is probably wrong.

Clone this wiki locally