mirror of
https://github.com/johndoe6345789/SDL3CPlusPlus.git
synced 2026-04-25 06:04:57 +00:00
- Updated JsonConfigWriterService to structure the JSON output with new sections for scripts, window settings, input bindings, paths, rendering, and GUI configurations. - Introduced a new method in ICrashRecoveryService to record frame heartbeats, allowing for better tracking of long-running operations. - Refactored existing code to improve readability and maintainability, including the addition of helper functions for adding string members to JSON objects.
266 lines
10 KiB
Lua
266 lines
10 KiB
Lua
-- Test suite for scene_framework.lua
|
|
-- Run with: lua scripts/test_scene_framework.lua
|
|
|
|
-- Mock math3d for standalone testing
|
|
package.preload['math3d'] = function()
|
|
local math3d = {}
|
|
|
|
function math3d.translation(x, y, z)
|
|
return {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1}
|
|
end
|
|
|
|
function math3d.multiply(a, b)
|
|
-- Simplified matrix multiply for test purposes
|
|
return {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}
|
|
end
|
|
|
|
return math3d
|
|
end
|
|
|
|
local framework = require("scene_framework")
|
|
|
|
local tests_run = 0
|
|
local tests_passed = 0
|
|
local tests_failed = 0
|
|
|
|
local function assert_equal(actual, expected, message)
|
|
tests_run = tests_run + 1
|
|
if actual == expected then
|
|
tests_passed = tests_passed + 1
|
|
return true
|
|
else
|
|
tests_failed = tests_failed + 1
|
|
print(string.format("FAIL: %s (expected %s, got %s)", message, tostring(expected), tostring(actual)))
|
|
return false
|
|
end
|
|
end
|
|
|
|
local function assert_near(actual, expected, epsilon, message)
|
|
tests_run = tests_run + 1
|
|
local diff = math.abs(actual - expected)
|
|
if diff <= epsilon then
|
|
tests_passed = tests_passed + 1
|
|
return true
|
|
else
|
|
tests_failed = tests_failed + 1
|
|
print(string.format("FAIL: %s (expected %f±%f, got %f, diff %f)",
|
|
message, expected, epsilon, actual, diff))
|
|
return false
|
|
end
|
|
end
|
|
|
|
local function assert_true(condition, message)
|
|
return assert_equal(condition, true, message)
|
|
end
|
|
|
|
local function assert_not_nil(value, message)
|
|
tests_run = tests_run + 1
|
|
if value ~= nil then
|
|
tests_passed = tests_passed + 1
|
|
return true
|
|
else
|
|
tests_failed = tests_failed + 1
|
|
print(string.format("FAIL: %s (value is nil)", message))
|
|
return false
|
|
end
|
|
end
|
|
|
|
-- ============================================================================
|
|
-- Config Resolution Tests
|
|
-- ============================================================================
|
|
|
|
print("Testing config resolution utilities...")
|
|
|
|
assert_equal(framework.resolve_number(42, 0), 42, "resolve_number with number")
|
|
assert_equal(framework.resolve_number("not a number", 99), 99, "resolve_number with fallback")
|
|
assert_equal(framework.resolve_number(nil, 123), 123, "resolve_number with nil")
|
|
|
|
assert_equal(framework.resolve_boolean(true, false), true, "resolve_boolean with true")
|
|
assert_equal(framework.resolve_boolean(false, true), false, "resolve_boolean with false")
|
|
assert_equal(framework.resolve_boolean("not bool", true), true, "resolve_boolean with fallback")
|
|
|
|
assert_equal(framework.resolve_string("hello", "default"), "hello", "resolve_string with string")
|
|
assert_equal(framework.resolve_string(123, "default"), "default", "resolve_string with fallback")
|
|
|
|
local tbl = {1, 2, 3}
|
|
assert_equal(framework.resolve_table(tbl, {}), tbl, "resolve_table with table")
|
|
assert_equal(type(framework.resolve_table("not table", nil)), "table", "resolve_table creates empty table")
|
|
|
|
local vec = framework.resolve_vec3({1, 2, 3}, {0, 0, 0})
|
|
assert_equal(vec[1], 1, "resolve_vec3 x component")
|
|
assert_equal(vec[2], 2, "resolve_vec3 y component")
|
|
assert_equal(vec[3], 3, "resolve_vec3 z component")
|
|
|
|
local fallback_vec = framework.resolve_vec3("invalid", {7, 8, 9})
|
|
assert_equal(fallback_vec[1], 7, "resolve_vec3 fallback x")
|
|
assert_equal(fallback_vec[2], 8, "resolve_vec3 fallback y")
|
|
assert_equal(fallback_vec[3], 9, "resolve_vec3 fallback z")
|
|
|
|
-- ============================================================================
|
|
-- Mesh Generation Tests
|
|
-- ============================================================================
|
|
|
|
print("Testing mesh generation...")
|
|
|
|
-- Test plane mesh generation
|
|
local plane_verts, plane_indices = framework.generate_plane_mesh(10, 10, 2, {1.0, 0.5, 0.25})
|
|
assert_equal(#plane_verts, 9, "plane 2x2 subdivision has 9 vertices (3x3 grid)")
|
|
assert_equal(#plane_indices, 24, "plane 2x2 subdivision has 24 indices (8 triangles)")
|
|
|
|
-- Check first vertex
|
|
assert_not_nil(plane_verts[1], "plane first vertex exists")
|
|
assert_equal(type(plane_verts[1].position), "table", "vertex has position")
|
|
assert_equal(type(plane_verts[1].normal), "table", "vertex has normal")
|
|
assert_equal(type(plane_verts[1].color), "table", "vertex has color")
|
|
assert_equal(plane_verts[1].color[1], 1.0, "plane vertex color r")
|
|
assert_equal(plane_verts[1].color[2], 0.5, "plane vertex color g")
|
|
assert_equal(plane_verts[1].color[3], 0.25, "plane vertex color b")
|
|
|
|
-- Test plane with default color
|
|
local white_verts, _ = framework.generate_plane_mesh(10, 10, 1)
|
|
assert_equal(white_verts[1].color[1], 1.0, "default plane color is white r")
|
|
assert_equal(white_verts[1].color[2], 1.0, "default plane color is white g")
|
|
assert_equal(white_verts[1].color[3], 1.0, "default plane color is white b")
|
|
|
|
-- Test cube mesh generation
|
|
local cube_verts, cube_indices = framework.generate_cube_mesh(false)
|
|
assert_equal(#cube_verts, 24, "cube has 24 vertices (4 per face)")
|
|
assert_equal(#cube_indices, 36, "single-sided cube has 36 indices (12 triangles)")
|
|
|
|
local cube_double, cube_double_idx = framework.generate_cube_mesh(true)
|
|
assert_equal(#cube_double, 24, "double-sided cube still has 24 vertices")
|
|
assert_equal(#cube_double_idx, 72, "double-sided cube has 72 indices (24 triangles)")
|
|
|
|
-- Test apply color
|
|
local colored_verts = framework.apply_color_to_vertices(cube_verts, {0.8, 0.6, 0.4})
|
|
assert_equal(#colored_verts, #cube_verts, "colored vertices same count as input")
|
|
assert_equal(colored_verts[1].color[1], 0.8, "applied color r")
|
|
assert_equal(colored_verts[1].color[2], 0.6, "applied color g")
|
|
assert_equal(colored_verts[1].color[3], 0.4, "applied color b")
|
|
-- Verify original unchanged
|
|
assert_equal(cube_verts[1].color[1], 1.0, "original vertices unchanged")
|
|
|
|
-- Test flip normals
|
|
local test_verts = {
|
|
{position = {0, 0, 0}, normal = {0, 1, 0}, color = {1, 1, 1}, texcoord = {0, 0}},
|
|
{position = {1, 0, 0}, normal = {1, 0, 0}, color = {1, 1, 1}, texcoord = {1, 0}},
|
|
}
|
|
framework.flip_normals(test_verts)
|
|
assert_equal(test_verts[1].normal[2], -1, "flipped normal y to -1")
|
|
assert_equal(test_verts[2].normal[1], -1, "flipped normal x to -1")
|
|
|
|
-- ============================================================================
|
|
-- Object Builder Tests
|
|
-- ============================================================================
|
|
|
|
print("Testing object builders...")
|
|
|
|
-- Test static object creation
|
|
local static_obj = framework.create_static_object(
|
|
cube_verts,
|
|
cube_indices,
|
|
{5, 10, 15},
|
|
{2, 3, 4},
|
|
"test_shader",
|
|
"test_object"
|
|
)
|
|
|
|
assert_not_nil(static_obj, "static object created")
|
|
assert_equal(static_obj.vertices, cube_verts, "static object has vertices")
|
|
assert_equal(static_obj.indices, cube_indices, "static object has indices")
|
|
assert_equal(static_obj.shader_keys[1], "test_shader", "static object has shader key")
|
|
assert_equal(static_obj.object_type, "test_object", "static object has type")
|
|
assert_equal(type(static_obj.compute_model_matrix), "function", "static object has matrix function")
|
|
|
|
local matrix = static_obj.compute_model_matrix()
|
|
assert_equal(type(matrix), "table", "compute_model_matrix returns table")
|
|
|
|
-- Test static cube creation
|
|
local cube_obj = framework.create_static_cube(
|
|
{1, 2, 3},
|
|
{0.5, 0.5, 0.5},
|
|
{0.9, 0.1, 0.1},
|
|
"cube_shader",
|
|
"my_cube"
|
|
)
|
|
|
|
assert_not_nil(cube_obj, "static cube created")
|
|
assert_equal(cube_obj.object_type, "my_cube", "cube has correct type")
|
|
assert_equal(cube_obj.shader_keys[1], "cube_shader", "cube has correct shader")
|
|
assert_equal(cube_obj.vertices[1].color[1], 0.9, "cube has applied color")
|
|
|
|
-- Test dynamic object creation
|
|
local time_value = 0
|
|
local dynamic_obj = framework.create_dynamic_object(
|
|
plane_verts,
|
|
plane_indices,
|
|
function(time)
|
|
time_value = time
|
|
return {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}
|
|
end,
|
|
"dynamic_shader",
|
|
"animated"
|
|
)
|
|
|
|
assert_not_nil(dynamic_obj, "dynamic object created")
|
|
assert_equal(dynamic_obj.object_type, "animated", "dynamic object has type")
|
|
local _ = dynamic_obj.compute_model_matrix(42)
|
|
assert_equal(time_value, 42, "dynamic compute function receives time")
|
|
|
|
-- ============================================================================
|
|
-- Material Registry Tests
|
|
-- ============================================================================
|
|
|
|
print("Testing material registry...")
|
|
|
|
local test_config = {
|
|
rendering = {
|
|
materialx = {
|
|
materials = {
|
|
{shader_key = "floor", document = "floor.mtlx", material = "Floor"},
|
|
{shader_key = "wall", document = "wall.mtlx", material = "Wall"},
|
|
{shader_key = "ceiling", document = "ceiling.mtlx", material = "Ceiling"},
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
local registry = framework.MaterialRegistry.new(test_config)
|
|
assert_not_nil(registry, "material registry created")
|
|
|
|
assert_true(registry:has("floor"), "registry has floor material")
|
|
assert_true(registry:has("wall"), "registry has wall material")
|
|
assert_true(registry:has("ceiling"), "registry has ceiling material")
|
|
assert_equal(registry:has("nonexistent"), false, "registry doesn't have fake material")
|
|
|
|
local floor_mat = registry:get("floor")
|
|
assert_not_nil(floor_mat, "can get floor material")
|
|
assert_equal(floor_mat.shader_key, "floor", "floor material has correct key")
|
|
assert_equal(floor_mat.document, "floor.mtlx", "floor material has document")
|
|
|
|
assert_equal(registry:get_key("floor"), "floor", "get_key returns existing key")
|
|
assert_equal(registry:get_key("fake"), "floor", "get_key returns default for missing key")
|
|
|
|
-- Test empty registry
|
|
local empty_registry = framework.MaterialRegistry.new(nil)
|
|
assert_not_nil(empty_registry, "empty registry created")
|
|
assert_equal(empty_registry:has("anything"), false, "empty registry has nothing")
|
|
|
|
-- ============================================================================
|
|
-- Summary
|
|
-- ============================================================================
|
|
|
|
print("\n" .. string.rep("=", 60))
|
|
print(string.format("Tests run: %d", tests_run))
|
|
print(string.format("Passed: %d", tests_passed))
|
|
print(string.format("Failed: %d", tests_failed))
|
|
print(string.rep("=", 60))
|
|
|
|
if tests_failed == 0 then
|
|
print("✓ ALL TESTS PASSED")
|
|
os.exit(0)
|
|
else
|
|
print("✗ SOME TESTS FAILED")
|
|
os.exit(1)
|
|
end
|