Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,16 @@ option(BUILD_TESTS "Build test suite" ON)
if(BUILD_TESTS)
enable_testing()


add_executable(test_framebuffer tests/test_framebuffer.cpp)
target_link_libraries(test_framebuffer PRIVATE soft_render)
add_test(NAME test_framebuffer COMMAND test_framebuffer)

add_executable(test_vec3 tests/test_vec3.cpp)
target_link_libraries(test_vec3 PRIVATE soft_render)
add_test(NAME test_vec3 COMMAND test_vec3)

add_executable(tests tests/test_math.cpp)
target_link_libraries(tests PRIVATE soft_render)
add_test(NAME test_math COMMAND tests)
function(sr_add_test name source)
add_executable(${name} ${source})
target_link_libraries(${name} PRIVATE soft_render)
add_test(NAME ${name} COMMAND ${name})
endfunction()

sr_add_test(test_framebuffer tests/test_framebuffer.cpp)
sr_add_test(test_vec3 tests/test_vec3.cpp)
sr_add_test(tests tests/test_math.cpp)
sr_add_test(test_math_invariants tests/test_math_invariants.cpp)
sr_add_test(test_rasterizer tests/test_rasterizer.cpp)
sr_add_test(test_pipeline_integration tests/test_pipeline_integration.cpp)
endif()
84 changes: 84 additions & 0 deletions tests/test_helpers.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#pragma once

// =============================================================================
// test_helpers.hpp — Shared test utilities and tolerance constants
//
// All floating-point comparisons use these two tiers:
// EPS (1e-4) — tight: single-operation results, exact math identities
// EPS_LOOSE (1e-2) — loose: chained transforms, accumulated floating-point error
// =============================================================================

#include <cmath>
#include <cstdint>
#include "soft_render/math/vec3.hpp"
#include "soft_render/core/framebuffer.hpp"

namespace sr_test {

using sr::math::Vec3;
using sr::core::Framebuffer;
using sr::core::Pixel;

// ---------------------------------------------------------------------------
// Tolerance constants
// ---------------------------------------------------------------------------
constexpr float EPS = 1e-4f; // Single-operation precision
constexpr float EPS_LOOSE = 1e-2f; // Multi-operation / chained transforms
constexpr float PI = 3.14159265358979f;

// ---------------------------------------------------------------------------
// Floating-point comparison helpers
// ---------------------------------------------------------------------------
inline bool approx(float a, float b, float eps = EPS) {
return std::abs(a - b) < eps;
}

inline bool approxVec3(const Vec3& a, const Vec3& b, float eps = EPS) {
return approx(a.x, b.x, eps) && approx(a.y, b.y, eps) && approx(a.z, b.z, eps);
}

// ---------------------------------------------------------------------------
// Deterministic PRNG (xorshift32) — reproducible but not hardcodeable
// ---------------------------------------------------------------------------
inline uint32_t& rng_state() {
static uint32_t s = 0xDEADBEEF;
return s;
}

inline float randf() {
auto& s = rng_state();
s ^= s << 13;
s ^= s >> 17;
s ^= s << 5;
return (s & 0xFFFFFF) / float(0xFFFFFF);
}

inline float randf_range(float lo, float hi) { return lo + randf() * (hi - lo); }

inline Vec3 randVec3(float range = 10.f) {
return { randf_range(-range, range), randf_range(-range, range), randf_range(-range, range) };
}

inline Vec3 randUnitVec3() { return randVec3().normalized(); }

// ---------------------------------------------------------------------------
// Framebuffer inspection helpers
// ---------------------------------------------------------------------------
inline int countNonBlack(const Framebuffer& fb) {
int count = 0;
const Pixel* px = fb.pixels();
for (int i = 0; i < fb.width() * fb.height(); ++i)
if (px[i].r > 0 || px[i].g > 0 || px[i].b > 0) ++count;
return count;
}

inline Pixel getPixel(const Framebuffer& fb, int x, int y) {
return fb.pixels()[y * fb.width() + x];
}

inline bool isLit(const Framebuffer& fb, int x, int y) {
Pixel p = getPixel(fb, x, y);
return p.r > 0 || p.g > 0 || p.b > 0;
}

} // namespace sr_test
Loading