summaryrefslogtreecommitdiff
path: root/src/tests
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-03 18:44:41 +0100
committerskal <pascal.massimino@gmail.com>2026-02-03 18:44:41 +0100
commitbf46e44e1cb6027a072819a2a3aa3be32651f6e1 (patch)
tree21267e7ef52fd91e7b99271ed87e275e91b3de3c /src/tests
parent815c428dea14a6a1ea5c421c400985d0c14d473d (diff)
refactor: Task #20 - Platform & Code Hygiene
- Consolidated all WebGPU shims and platform-specific logic into src/platform.h. - Refactored platform_init to return PlatformState by value and platform_poll to automatically refresh time and aspect_ratio. - Removed STL dependencies (std::map, std::vector, std::string) from AssetManager and Procedural subsystems. - Fixed Windows cross-compilation by adjusting include paths and linker flags in CMakeLists.txt and updating build_win.sh. - Removed redundant direct inclusions of GLFW/glfw3.h and WebGPU headers across the project. - Applied clang-format and updated documentation. handoff(Gemini): Completed Task #20 and 20.1. Platform abstraction is now unified, and core paths are STL-free. Windows build is stable.
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/test_3d_render.cc45
-rw-r--r--src/tests/test_shader_assets.cc111
-rw-r--r--src/tests/test_shader_composer.cc46
-rw-r--r--src/tests/test_texture_manager.cc34
-rw-r--r--src/tests/test_tracker.cc21
5 files changed, 122 insertions, 135 deletions
diff --git a/src/tests/test_3d_render.cc b/src/tests/test_3d_render.cc
index cc7dce6..6e639cd 100644
--- a/src/tests/test_3d_render.cc
+++ b/src/tests/test_3d_render.cc
@@ -5,21 +5,15 @@
#include "3d/object.h"
#include "3d/renderer.h"
#include "3d/scene.h"
-#include "gpu/texture_manager.h"
#include "gpu/effects/shaders.h"
+#include "gpu/texture_manager.h"
#include "platform.h"
#include "procedural/generator.h"
#include <cmath>
+#include <cstdio>
#include <cstring>
-#include <iostream>
#include <vector>
-#if defined(DEMO_CROSS_COMPILE_WIN32)
-#include <webgpu/webgpu.h>
-#else
-#include <webgpu.h>
-#endif
-
// Global State
static Renderer3D g_renderer;
static TextureManager g_textures;
@@ -35,13 +29,13 @@ static WGPUTextureFormat g_format = WGPUTextureFormat_Undefined;
void init_wgpu(PlatformState* platform_state) {
WGPUInstance instance = wgpuCreateInstance(nullptr);
if (!instance) {
- std::cerr << "Failed to create WGPU instance." << std::endl;
+ fprintf(stderr, "Failed to create WGPU instance.\n");
exit(1);
}
g_surface = platform_create_wgpu_surface(instance, platform_state);
if (!g_surface) {
- std::cerr << "Failed to create WGPU surface." << std::endl;
+ fprintf(stderr, "Failed to create WGPU surface.\n");
exit(1);
}
@@ -60,6 +54,7 @@ void init_wgpu(PlatformState* platform_state) {
#else
auto on_adapter = [](WGPURequestAdapterStatus status, WGPUAdapter adapter,
WGPUStringView message, void* userdata, void* user2) {
+ (void)user2;
if (status == WGPURequestAdapterStatus_Success) {
*(WGPUAdapter*)userdata = adapter;
}
@@ -71,15 +66,8 @@ void init_wgpu(PlatformState* platform_state) {
wgpuInstanceRequestAdapter(instance, &adapter_opts, adapter_cb);
#endif
-#if !defined(DEMO_CROSS_COMPILE_WIN32)
while (!g_adapter) {
- wgpuInstanceProcessEvents(instance);
- }
-#endif
-
- if (!g_adapter) {
- std::cerr << "Failed to get adapter." << std::endl;
- exit(1);
+ platform_wgpu_wait_any(instance);
}
WGPUDeviceDescriptor device_desc = {};
@@ -95,6 +83,7 @@ void init_wgpu(PlatformState* platform_state) {
#else
auto on_device = [](WGPURequestDeviceStatus status, WGPUDevice device,
WGPUStringView message, void* userdata, void* user2) {
+ (void)user2;
if (status == WGPURequestDeviceStatus_Success) {
*(WGPUDevice*)userdata = device;
}
@@ -106,15 +95,8 @@ void init_wgpu(PlatformState* platform_state) {
wgpuAdapterRequestDevice(g_adapter, &device_desc, device_cb);
#endif
-#if !defined(DEMO_CROSS_COMPILE_WIN32)
while (!g_device) {
- wgpuInstanceProcessEvents(instance);
- }
-#endif
-
- if (!g_device) {
- std::cerr << "Failed to get device." << std::endl;
- exit(1);
+ platform_wgpu_wait_any(instance);
}
g_queue = wgpuDeviceGetQueue(g_device);
@@ -206,8 +188,7 @@ int main(int argc, char** argv) {
(void)argv;
#endif
- PlatformState platform_state = {};
- platform_init(&platform_state, false, nullptr, nullptr);
+ PlatformState platform_state = platform_init(false, 1280, 720);
// The test's own WGPU init sequence
init_wgpu(&platform_state);
@@ -222,7 +203,8 @@ int main(int argc, char** argv) {
noise_def.width = 256;
noise_def.height = 256;
noise_def.gen_func = gen_periodic_noise;
- noise_def.params = {1234.0f, 16.0f};
+ noise_def.params.push_back(1234.0f);
+ noise_def.params.push_back(16.0f);
g_textures.create_procedural_texture("noise", noise_def);
g_renderer.set_noise_texture(g_textures.get_texture_view("noise"));
@@ -232,17 +214,16 @@ int main(int argc, char** argv) {
g_camera.position = vec3(0, 5, 10);
g_camera.target = vec3(0, 0, 0);
- float time = 0.0f;
while (!platform_should_close(&platform_state)) {
platform_poll(&platform_state);
- time = (float)platform_get_time();
+ float time = (float)platform_state.time;
float cam_radius = 10.0f + std::sin(time * 0.3f) * 4.0f;
float cam_height = 5.0f + std::cos(time * 0.4f) * 3.0f;
g_camera.set_look_at(vec3(std::sin(time * 0.5f) * cam_radius, cam_height,
std::cos(time * 0.5f) * cam_radius),
vec3(0, 0, 0), vec3(0, 1, 0));
- g_camera.aspect_ratio = platform_get_aspect_ratio(&platform_state);
+ g_camera.aspect_ratio = platform_state.aspect_ratio;
for (size_t i = 1; i < g_scene.objects.size(); ++i) {
// Rotation around a random-ish 3D axis
diff --git a/src/tests/test_shader_assets.cc b/src/tests/test_shader_assets.cc
index 42d1c4c..f1562ea 100644
--- a/src/tests/test_shader_assets.cc
+++ b/src/tests/test_shader_assets.cc
@@ -8,59 +8,84 @@
#include <string>
#include <vector>
-bool validate_shader(AssetId id, const char* name, const std::vector<const char*>& expected_keywords) {
- printf("Validating shader: %s...\n", name);
- size_t size = 0;
- const char* data = (const char*)GetAsset(id, &size);
+bool validate_shader(AssetId id, const char* name,
+ const std::vector<const char*>& expected_keywords) {
+ printf("Validating shader: %s...\n", name);
+ size_t size = 0;
+ const char* data = (const char*)GetAsset(id, &size);
- if (data == nullptr || size == 0) {
- printf("FAILED: Shader %s is missing or empty!\n", name);
- return false;
- }
+ if (data == nullptr || size == 0) {
+ printf("FAILED: Shader %s is missing or empty!\n", name);
+ return false;
+ }
- std::string code(data, size);
- for (const char* keyword : expected_keywords) {
- if (code.find(keyword) == std::string::npos) {
- printf("FAILED: Shader %s missing expected keyword '%s'!\n", name, keyword);
- // printf("Code snippet:\n%.100s...\n", data);
- return false;
- }
+ std::string code(data, size);
+ for (const char* keyword : expected_keywords) {
+ if (code.find(keyword) == std::string::npos) {
+ printf("FAILED: Shader %s missing expected keyword '%s'!\n", name,
+ keyword);
+ // printf("Code snippet:\n%.100s...\n", data);
+ return false;
}
+ }
- printf("PASSED: %s (%zu bytes)\n", name, size);
- return true;
+ printf("PASSED: %s (%zu bytes)\n", name, size);
+ return true;
}
int main() {
- printf("--- RUNNING SHADER ASSET VALIDATION ---\n");
+ printf("--- RUNNING SHADER ASSET VALIDATION ---\n");
- bool all_passed = true;
+ bool all_passed = true;
- // Snippets
- all_passed &= validate_shader(AssetId::ASSET_SHADER_COMMON_UNIFORMS, "COMMON_UNIFORMS", {"struct", "GlobalUniforms"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_SDF_PRIMITIVES, "SDF_PRIMITIVES", {"fn", "sd"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_LIGHTING, "LIGHTING", {"fn", "calc"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_RAY_BOX, "RAY_BOX", {"fn", "intersect"});
+ // Snippets
+ all_passed &=
+ validate_shader(AssetId::ASSET_SHADER_COMMON_UNIFORMS, "COMMON_UNIFORMS",
+ {"struct", "GlobalUniforms"});
+ all_passed &= validate_shader(AssetId::ASSET_SHADER_SDF_PRIMITIVES,
+ "SDF_PRIMITIVES", {"fn", "sd"});
+ all_passed &= validate_shader(AssetId::ASSET_SHADER_LIGHTING, "LIGHTING",
+ {"fn", "calc"});
+ all_passed &= validate_shader(AssetId::ASSET_SHADER_RAY_BOX, "RAY_BOX",
+ {"fn", "intersect"});
- // Full Shaders (Entry points)
- all_passed &= validate_shader(AssetId::ASSET_SHADER_RENDERER_3D, "RENDERER_3D", {"@vertex", "vs_main", "@fragment", "fs_main"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_MAIN, "MAIN", {"@vertex", "vs_main", "@fragment", "fs_main"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_PARTICLE_COMPUTE, "PARTICLE_COMPUTE", {"@compute", "main"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_PARTICLE_RENDER, "PARTICLE_RENDER", {"@vertex", "vs_main", "@fragment", "fs_main"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_PASSTHROUGH, "PASSTHROUGH", {"@vertex", "vs_main", "@fragment", "fs_main"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_ELLIPSE, "ELLIPSE", {"@vertex", "vs_main", "@fragment", "fs_main"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_PARTICLE_SPRAY_COMPUTE, "PARTICLE_SPRAY_COMPUTE", {"@compute", "main"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", {"@vertex", "vs_main", "@fragment", "fs_main"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_SOLARIZE, "SOLARIZE", {"@vertex", "vs_main", "@fragment", "fs_main"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_DISTORT, "DISTORT", {"@vertex", "vs_main", "@fragment", "fs_main"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_CHROMA_ABERRATION, "CHROMA_ABERRATION", {"@vertex", "vs_main", "@fragment", "fs_main"});
- all_passed &= validate_shader(AssetId::ASSET_SHADER_VISUAL_DEBUG, "VISUAL_DEBUG", {"@vertex", "vs_main", "@fragment", "fs_main"});
+ // Full Shaders (Entry points)
+ all_passed &=
+ validate_shader(AssetId::ASSET_SHADER_RENDERER_3D, "RENDERER_3D",
+ {"@vertex", "vs_main", "@fragment", "fs_main"});
+ all_passed &= validate_shader(AssetId::ASSET_SHADER_MAIN, "MAIN",
+ {"@vertex", "vs_main", "@fragment", "fs_main"});
+ all_passed &= validate_shader(AssetId::ASSET_SHADER_PARTICLE_COMPUTE,
+ "PARTICLE_COMPUTE", {"@compute", "main"});
+ all_passed &=
+ validate_shader(AssetId::ASSET_SHADER_PARTICLE_RENDER, "PARTICLE_RENDER",
+ {"@vertex", "vs_main", "@fragment", "fs_main"});
+ all_passed &=
+ validate_shader(AssetId::ASSET_SHADER_PASSTHROUGH, "PASSTHROUGH",
+ {"@vertex", "vs_main", "@fragment", "fs_main"});
+ all_passed &= validate_shader(AssetId::ASSET_SHADER_ELLIPSE, "ELLIPSE",
+ {"@vertex", "vs_main", "@fragment", "fs_main"});
+ all_passed &= validate_shader(AssetId::ASSET_SHADER_PARTICLE_SPRAY_COMPUTE,
+ "PARTICLE_SPRAY_COMPUTE", {"@compute", "main"});
+ all_passed &=
+ validate_shader(AssetId::ASSET_SHADER_GAUSSIAN_BLUR, "GAUSSIAN_BLUR",
+ {"@vertex", "vs_main", "@fragment", "fs_main"});
+ all_passed &= validate_shader(AssetId::ASSET_SHADER_SOLARIZE, "SOLARIZE",
+ {"@vertex", "vs_main", "@fragment", "fs_main"});
+ all_passed &= validate_shader(AssetId::ASSET_SHADER_DISTORT, "DISTORT",
+ {"@vertex", "vs_main", "@fragment", "fs_main"});
+ all_passed &= validate_shader(AssetId::ASSET_SHADER_CHROMA_ABERRATION,
+ "CHROMA_ABERRATION",
+ {"@vertex", "vs_main", "@fragment", "fs_main"});
+ all_passed &=
+ validate_shader(AssetId::ASSET_SHADER_VISUAL_DEBUG, "VISUAL_DEBUG",
+ {"@vertex", "vs_main", "@fragment", "fs_main"});
- if (!all_passed) {
- printf("--- SHADER ASSET VALIDATION FAILED ---\n");
- return 1;
- }
+ if (!all_passed) {
+ printf("--- SHADER ASSET VALIDATION FAILED ---\n");
+ return 1;
+ }
- printf("--- ALL SHADER ASSETS VALIDATED ---\n");
- return 0;
+ printf("--- ALL SHADER ASSETS VALIDATED ---\n");
+ return 0;
}
diff --git a/src/tests/test_shader_composer.cc b/src/tests/test_shader_composer.cc
index 7efcd83..16dabba 100644
--- a/src/tests/test_shader_composer.cc
+++ b/src/tests/test_shader_composer.cc
@@ -15,7 +15,6 @@
// Forward declaration for asset loading
const uint8_t* GetAsset(AssetId asset_id, size_t* out_size);
-
void test_composition() {
std::cout << "Testing Shader Composition..." << std::endl;
auto& sc = ShaderComposer::Get();
@@ -42,35 +41,38 @@ void test_composition() {
}
void test_asset_composition() {
- std::cout << "Testing Asset-Based Shader Composition..." << std::endl;
+ std::cout << "Testing Asset-Based Shader Composition..." << std::endl;
- // Use test assets
- auto& sc = ShaderComposer::Get();
+ // Use test assets
+ auto& sc = ShaderComposer::Get();
- size_t snippet_a_size;
- const char* snippet_a_code = (const char*)GetAsset(AssetId::ASSET_SHADER_SNIPPET_A, &snippet_a_size);
- assert(snippet_a_code != nullptr);
- sc.RegisterSnippet("SNIPPET_A", std::string(snippet_a_code, snippet_a_size));
+ size_t snippet_a_size;
+ const char* snippet_a_code =
+ (const char*)GetAsset(AssetId::ASSET_SHADER_SNIPPET_A, &snippet_a_size);
+ assert(snippet_a_code != nullptr);
+ sc.RegisterSnippet("SNIPPET_A", std::string(snippet_a_code, snippet_a_size));
- size_t snippet_b_size;
- const char* snippet_b_code = (const char*)GetAsset(AssetId::ASSET_SHADER_SNIPPET_B, &snippet_b_size);
- sc.RegisterSnippet("SNIPPET_B", std::string(snippet_b_code, snippet_b_size));
+ size_t snippet_b_size;
+ const char* snippet_b_code =
+ (const char*)GetAsset(AssetId::ASSET_SHADER_SNIPPET_B, &snippet_b_size);
+ sc.RegisterSnippet("SNIPPET_B", std::string(snippet_b_code, snippet_b_size));
- std::string main_code = "fn main() -> f32 { return snippet_a() + snippet_b(); }";
- std::string result = sc.Compose({"SNIPPET_A", "SNIPPET_B"}, main_code);
+ std::string main_code =
+ "fn main() -> f32 { return snippet_a() + snippet_b(); }";
+ std::string result = sc.Compose({"SNIPPET_A", "SNIPPET_B"}, main_code);
- assert(result.find("fn snippet_a()") != std::string::npos);
- assert(result.find("fn snippet_b()") != std::string::npos);
- assert(result.find("fn main()") != std::string::npos);
+ assert(result.find("fn snippet_a()") != std::string::npos);
+ assert(result.find("fn snippet_b()") != std::string::npos);
+ assert(result.find("fn main()") != std::string::npos);
- size_t pos_a = result.find("snippet_a");
- size_t pos_b = result.find("snippet_b");
- size_t pos_main = result.find("main");
+ size_t pos_a = result.find("snippet_a");
+ size_t pos_b = result.find("snippet_b");
+ size_t pos_main = result.find("main");
- assert(pos_a < pos_b);
- assert(pos_b < pos_main);
+ assert(pos_a < pos_b);
+ assert(pos_b < pos_main);
- std::cout << "Asset-based composition logic verified." << std::endl;
+ std::cout << "Asset-based composition logic verified." << std::endl;
}
int main() {
diff --git a/src/tests/test_texture_manager.cc b/src/tests/test_texture_manager.cc
index 5741d8c..75d897d 100644
--- a/src/tests/test_texture_manager.cc
+++ b/src/tests/test_texture_manager.cc
@@ -3,40 +3,18 @@
// with valid device).
#include "gpu/texture_manager.h"
+#include "platform.h"
#include "procedural/generator.h"
-#include <iostream>
-
-#include <GLFW/glfw3.h>
-#if defined(DEMO_CROSS_COMPILE_WIN32)
-#include <webgpu/webgpu.h>
-#else
-#include <webgpu.h>
-#endif
-
-// Forward decls from platform.h or similar (simplifying for test)
-// Note: This test requires a valid WebGPU device, which is hard in CI/headless.
-// We will structure it to compile, but runtime might skip if no device.
-// For now, we just test the C++ side logic if possible, but TextureManager
-// depends heavily on WGPU calls.
-
-// We will use a "Headless" approach if possible, or just skip if Init fails.
-// Actually, let's just make it a compilation test + basic logic check if we can
-// mock or stub. Since we don't have a mocking framework, we'll try to init
-// wgpu-native.
+#include <cstdio>
int main() {
- // Need to init GLFW for surface creation usually, even for headless in some
- // impls?
- if (!glfwInit()) {
- std::cerr << "Failed to init GLFW" << std::endl;
+ PlatformState state = platform_init(false, 100, 100);
+ if (!state.window) {
+ fprintf(stderr, "Failed to init platform\n");
return 1;
}
- // NOTE: In a real CI environment without GPU, this will likely fail or hang.
- // For this "demo" context, we assume the user has a GPU or we just verify it
- // compiles. We'll skip actual GPU init for this simple test to avoid hanging
- // the agent if no GPU.
- std::cout << "TextureManager Compilation Test Passed." << std::endl;
+ fprintf(stdout, "TextureManager Compilation Test Passed.\n");
/*
TextureManager tm;
diff --git a/src/tests/test_tracker.cc b/src/tests/test_tracker.cc
index ad84163..2a9239c 100644
--- a/src/tests/test_tracker.cc
+++ b/src/tests/test_tracker.cc
@@ -1,17 +1,16 @@
// This file is part of the 64k demo project.
// It tests the core functionality of the audio tracker engine.
-#include "audio/tracker.h"
-#include "audio/synth.h"
#include "audio/gen.h"
+#include "audio/synth.h"
+#include "audio/tracker.h"
// #include "generated/music_data.h" // Will be generated by tracker_compiler
#include <assert.h>
#include <stdio.h>
-// Forward declaration for generated data to avoid compilation issues before generation
-// extern const NoteParams g_tracker_samples[];
-// extern const uint32_t g_tracker_samples_count;
-// extern const TrackerPattern g_tracker_patterns[];
+// Forward declaration for generated data to avoid compilation issues before
+// generation extern const NoteParams g_tracker_samples[]; extern const uint32_t
+// g_tracker_samples_count; extern const TrackerPattern g_tracker_patterns[];
// extern const uint32_t g_tracker_patterns_count;
// extern const TrackerScore g_tracker_score;
@@ -28,7 +27,8 @@ void test_tracker_pattern_triggering() {
// Test 1: Trigger patterns at 0.0f
tracker_update(0.0f);
printf("Actual active voice count: %d\n", synth_get_active_voice_count());
- // Expect 3 voices (one for each pattern triggered at 0.0f: drum_loop, hihat_roll, em_melody)
+ // Expect 3 voices (one for each pattern triggered at 0.0f: drum_loop,
+ // hihat_roll, em_melody)
assert(synth_get_active_voice_count() == 3);
// Test 2: Advance time slightly
@@ -39,9 +39,10 @@ void test_tracker_pattern_triggering() {
tracker_update(3.0f);
// Voices from 0.0f triggers might have ended, but new ones haven't started.
// synth_get_active_voice_count might drop if previous voices ended.
- // For this test, we assume voices triggered at 0.0f are still active for a short duration.
- // A more robust test would check for specific spectrograms or mock synth.
- // For now, we expect voices to still be somewhat active or new ones to be triggered if there's overlap
+ // For this test, we assume voices triggered at 0.0f are still active for a
+ // short duration. A more robust test would check for specific spectrograms or
+ // mock synth. For now, we expect voices to still be somewhat active or new
+ // ones to be triggered if there's overlap
assert(synth_get_active_voice_count() > 0);
printf("Tracker pattern triggering test PASSED\n");