summaryrefslogtreecommitdiff
path: root/src/tests/util
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-14 02:39:49 +0100
committerskal <pascal.massimino@gmail.com>2026-02-14 02:39:49 +0100
commit8dd77545b5ec2f45ce46b98dd7d94a3c4a13e290 (patch)
treea338b9c1356da64a609621155c81d8d96f7ca7fe /src/tests/util
parentc007d7fa6ddb1936108aeca156b2a4bda425ca84 (diff)
Factor common test patterns into reusable utilitiesHEADmain
Refactor duplicated test setup/teardown code into shared fixtures: - test_math_helpers.h: Float comparison (test_near, test_near_vec3) - AudioTestFixture: RAII wrapper for AudioEngine lifecycle - EffectTestFixture: Combined WebGPU + AudioEngine + MainSequence Migrated 9 test files (3 math, 6 audio) to use fixtures. Net reduction: 54 LOC (178 insertions, 232 deletions). All 34 tests passing. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'src/tests/util')
-rw-r--r--src/tests/util/test_maths.cc83
1 files changed, 39 insertions, 44 deletions
diff --git a/src/tests/util/test_maths.cc b/src/tests/util/test_maths.cc
index 0fed85c..4233adc 100644
--- a/src/tests/util/test_maths.cc
+++ b/src/tests/util/test_maths.cc
@@ -3,16 +3,11 @@
// Verifies vector operations, matrix transformations, and interpolation.
#include "util/mini_math.h"
+#include "../common/test_math_helpers.h"
#include <cassert>
-#include <cmath>
#include <iostream>
#include <vector>
-// Checks if two floats are approximately equal
-bool near(float a, float b, float e = 0.001f) {
- return std::abs(a - b) < e;
-}
-
// Generic test runner for any vector type (vec2, vec3, vec4)
template <typename T> void test_vector_ops(int n) {
T a, b;
@@ -25,37 +20,37 @@ template <typename T> void test_vector_ops(int n) {
// Add
T c = a + b;
for (int i = 0; i < n; ++i)
- assert(near(c[i], (float)(i + 1) + 10.0f));
+ assert(test_near(c[i], (float)(i + 1) + 10.0f, 0.001f));
// Scale
T s = a * 2.0f;
for (int i = 0; i < n; ++i)
- assert(near(s[i], (float)(i + 1) * 2.0f));
+ assert(test_near(s[i], (float)(i + 1) * 2.0f, 0.001f));
// Dot Product
// vec3(1,2,3) . vec3(1,2,3) = 1+4+9 = 14
float expected_dot = 0;
for (int i = 0; i < n; ++i)
expected_dot += a[i] * a[i];
- assert(near(T::dot(a, a), expected_dot));
+ assert(test_near(T::dot(a, a), expected_dot, 0.001f));
// Norm (Length)
- assert(near(a.norm(), std::sqrt(expected_dot)));
+ assert(test_near(a.norm(), std::sqrt(expected_dot), 0.001f));
// Normalize
T n_vec = a.normalize();
- assert(near(n_vec.norm(), 1.0f));
+ assert(test_near(n_vec.norm(), 1.0f, 0.001f));
// Normalize zero vector
T zero_vec = T(); // Default construct to zero
T norm_zero = zero_vec.normalize();
for (int i = 0; i < n; ++i)
- assert(near(norm_zero[i], 0.0f));
+ assert(test_near(norm_zero[i], 0.0f, 0.001f));
// Lerp
T l = lerp(a, b, 0.3f);
for (int i = 0; i < n; ++i)
- assert(near(l[i], .7 * (i + 1) + .3 * 10.0f));
+ assert(test_near(l[i], .7 * (i + 1) + .3 * 10.0f, 0.001f));
}
// Specific test for padding alignment in vec3
@@ -69,7 +64,7 @@ void test_vec3_special() {
// Cross Product
vec3 c = vec3::cross(v, v2);
- assert(near(c.x, 0) && near(c.y, 0) && near(c.z, 1));
+ assert(test_near(c.x, 0, 0.001f) && test_near(c.y, 0, 0.001f) && test_near(c.z, 1, 0.001f));
}
// Tests quaternion rotation, look_at, and slerp
@@ -80,48 +75,48 @@ void test_quat() {
vec3 v(1, 0, 0);
quat q = quat::from_axis({0, 1, 0}, 1.5708f); // 90 deg Y
vec3 r = q.rotate(v);
- assert(near(r.x, 0) && near(r.z, -1));
+ assert(test_near(r.x, 0, 0.001f) && test_near(r.z, -1, 0.001f));
// Rotation edge cases: 0 deg, 180 deg, zero vector
quat zero_rot = quat::from_axis({1, 0, 0}, 0.0f);
vec3 rotated_zero = zero_rot.rotate(v);
- assert(near(rotated_zero.x, 1.0f)); // Original vector
+ assert(test_near(rotated_zero.x, 1.0f, 0.001f)); // Original vector
quat half_pi_rot = quat::from_axis({0, 1, 0}, 3.14159f); // 180 deg Y
vec3 rotated_half_pi = half_pi_rot.rotate(v);
- assert(near(rotated_half_pi.x, -1.0f)); // Rotated 180 deg around Y
+ assert(test_near(rotated_half_pi.x, -1.0f, 0.001f)); // Rotated 180 deg around Y
vec3 zero_vec(0, 0, 0);
vec3 rotated_zero_vec = q.rotate(zero_vec);
- assert(near(rotated_zero_vec.x, 0.0f) && near(rotated_zero_vec.y, 0.0f) &&
- near(rotated_zero_vec.z, 0.0f));
+ assert(test_near(rotated_zero_vec.x, 0.0f, 0.001f) && test_near(rotated_zero_vec.y, 0.0f, 0.001f) &&
+ test_near(rotated_zero_vec.z, 0.0f, 0.001f));
// Look At
// Looking from origin to +X, with +Y as up.
// The local forward vector (0,0,-1) should be transformed to (1,0,0)
quat l = quat::look_at({0, 0, 0}, {10, 0, 0}, {0, 1, 0});
vec3 f = l.rotate({0, 0, -1});
- assert(near(f.x, 1.0f) && near(f.y, 0.0f) && near(f.z, 0.0f));
+ assert(test_near(f.x, 1.0f, 0.001f) && test_near(f.y, 0.0f, 0.001f) && test_near(f.z, 0.0f, 0.001f));
// Slerp Midpoint
quat q1(0, 0, 0, 1);
quat q2 = quat::from_axis({0, 1, 0}, 1.5708f); // 90 deg
quat mid = slerp(q1, q2, 0.5f); // 45 deg
- assert(near(mid.y, 0.3826f)); // sin(pi/8)
+ assert(test_near(mid.y, 0.3826f, 0.001f)); // sin(pi/8)
// Slerp edge cases
quat slerp_mid_edge = slerp(q1, q2, 0.0f);
- assert(near(slerp_mid_edge.w, q1.w) && near(slerp_mid_edge.x, q1.x) &&
- near(slerp_mid_edge.y, q1.y) && near(slerp_mid_edge.z, q1.z));
+ assert(test_near(slerp_mid_edge.w, q1.w, 0.001f) && test_near(slerp_mid_edge.x, q1.x, 0.001f) &&
+ test_near(slerp_mid_edge.y, q1.y, 0.001f) && test_near(slerp_mid_edge.z, q1.z, 0.001f));
slerp_mid_edge = slerp(q1, q2, 1.0f);
- assert(near(slerp_mid_edge.w, q2.w) && near(slerp_mid_edge.x, q2.x) &&
- near(slerp_mid_edge.y, q2.y) && near(slerp_mid_edge.z, q2.z));
+ assert(test_near(slerp_mid_edge.w, q2.w, 0.001f) && test_near(slerp_mid_edge.x, q2.x, 0.001f) &&
+ test_near(slerp_mid_edge.y, q2.y, 0.001f) && test_near(slerp_mid_edge.z, q2.z, 0.001f));
// FromTo
quat from_to_test =
quat::from_to({1, 0, 0}, {0, 1, 0}); // 90 deg rotation around Z
vec3 rotated = from_to_test.rotate({1, 0, 0});
- assert(near(rotated.y, 1.0f));
+ assert(test_near(rotated.y, 1.0f, 0.001f));
}
// Tests WebGPU specific matrices
@@ -134,8 +129,8 @@ void test_matrices() {
// Z_ndc = (m10 * Z_view + m14) / -Z_view
float z_near = (p.m[10] * -n + p.m[14]) / n;
float z_far = (p.m[10] * -f + p.m[14]) / f;
- assert(near(z_near, 0.0f));
- assert(near(z_far, 1.0f));
+ assert(test_near(z_near, 0.0f, 0.001f));
+ assert(test_near(z_far, 1.0f, 0.001f));
// Test mat4::look_at
vec3 eye(0, 0, 5);
@@ -143,7 +138,7 @@ void test_matrices() {
vec3 up(0, 1, 0);
mat4 view = mat4::look_at(eye, target, up);
// Point (0,0,0) in world should be at (0,0,-5) in view space
- assert(near(view.m[14], -5.0f));
+ assert(test_near(view.m[14], -5.0f, 0.001f));
// Test matrix multiplication
mat4 t = mat4::translate({1, 2, 3});
@@ -153,34 +148,34 @@ void test_matrices() {
// v = (1,1,1,1) -> scale(2,2,2) -> (2,2,2,1) -> translate(1,2,3) -> (3,4,5,1)
vec4 v(1, 1, 1, 1);
vec4 res = ts * v;
- assert(near(res.x, 3.0f));
- assert(near(res.y, 4.0f));
- assert(near(res.z, 5.0f));
+ assert(test_near(res.x, 3.0f, 0.001f));
+ assert(test_near(res.y, 4.0f, 0.001f));
+ assert(test_near(res.z, 5.0f, 0.001f));
// Test Rotation
// Rotate 90 deg around Z. (1,0,0) -> (0,1,0)
mat4 r = mat4::rotate({0, 0, 1}, 1.570796f);
vec4 v_rot = r * vec4(1, 0, 0, 1);
- assert(near(v_rot.x, 0.0f));
- assert(near(v_rot.y, 1.0f));
+ assert(test_near(v_rot.x, 0.0f, 0.001f));
+ assert(test_near(v_rot.y, 1.0f, 0.001f));
}
// Tests easing curves
void test_ease() {
std::cout << "Testing Easing..." << std::endl;
// Boundary tests
- assert(near(ease::out_cubic(0.0f), 0.0f));
- assert(near(ease::out_cubic(1.0f), 1.0f));
- assert(near(ease::in_out_quad(0.0f), 0.0f));
- assert(near(ease::in_out_quad(1.0f), 1.0f));
- assert(near(ease::out_expo(0.0f), 0.0f));
- assert(near(ease::out_expo(1.0f), 1.0f));
+ assert(test_near(ease::out_cubic(0.0f), 0.0f, 0.001f));
+ assert(test_near(ease::out_cubic(1.0f), 1.0f, 0.001f));
+ assert(test_near(ease::in_out_quad(0.0f), 0.0f, 0.001f));
+ assert(test_near(ease::in_out_quad(1.0f), 1.0f, 0.001f));
+ assert(test_near(ease::out_expo(0.0f), 0.0f, 0.001f));
+ assert(test_near(ease::out_expo(1.0f), 1.0f, 0.001f));
// Midpoint/Logic tests
assert(ease::out_cubic(0.5f) >
0.5f); // Out curves should exceed linear value early
assert(
- near(ease::in_out_quad(0.5f), 0.5f)); // Symmetric curves hit 0.5 at 0.5
+ test_near(ease::in_out_quad(0.5f), 0.5f, 0.001f)); // Symmetric curves hit 0.5 at 0.5
assert(ease::out_expo(0.5f) > 0.5f); // Exponential out should be above linear
}
@@ -198,7 +193,7 @@ void test_spring() {
v = 0;
for (int i = 0; i < 200; ++i)
spring::solve(p, v, 10.0f, 0.5f, 0.016f);
- assert(near(p, 10.0f, 0.1f)); // Should be very close to target
+ assert(test_near(p, 10.0f, 0.1f)); // Should be very close to target
// Test vector spring
vec3 vp(0, 0, 0), vv(0, 0, 0), vt(10, 0, 0);
@@ -210,7 +205,7 @@ void test_spring() {
void check_identity(const mat4& m) {
for (int i = 0; i < 16; ++i) {
float expected = (i % 5 == 0) ? 1.0f : 0.0f;
- if (!near(m.m[i], expected, 0.005f)) {
+ if (!test_near(m.m[i], expected, 0.005f)) {
std::cerr << "Matrix not Identity at index " << i << ": got " << m.m[i]
<< " expected " << expected << std::endl;
assert(false);
@@ -254,7 +249,7 @@ void test_matrix_inversion() {
mat4 trs_t = mat4::transpose(trs);
mat4 trs_tt = mat4::transpose(trs_t);
for (int i = 0; i < 16; ++i) {
- assert(near(trs.m[i], trs_tt.m[i]));
+ assert(test_near(trs.m[i], trs_tt.m[i], 0.001f));
}
// 7. Manual "stress" matrix (some small values, some large)