summaryrefslogtreecommitdiff
path: root/src/tests/gpu/test_texture_manager.cc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-09 20:27:04 +0100
committerskal <pascal.massimino@gmail.com>2026-02-09 20:27:04 +0100
commiteff8d43479e7704df65fae2a80eefa787213f502 (patch)
tree76f2fb8fe8d3db2c15179449df2cf12f7f54e0bf /src/tests/gpu/test_texture_manager.cc
parent12378b1b7e9091ba59895b4360b2fa959180a56a (diff)
refactor: Reorganize tests into subsystem subdirectories
Restructured test suite for better organization and targeted testing: **Structure:** - src/tests/audio/ - 15 audio system tests - src/tests/gpu/ - 12 GPU/shader tests - src/tests/3d/ - 6 3D rendering tests - src/tests/assets/ - 2 asset system tests - src/tests/util/ - 3 utility tests - src/tests/common/ - 3 shared test helpers - src/tests/scripts/ - 2 bash test scripts (moved conceptually, not physically) **CMake changes:** - Updated add_demo_test macro to accept LABEL parameter - Applied CTest labels to all 36 tests for subsystem filtering - Updated all test file paths in CMakeLists.txt - Fixed common helper paths (webgpu_test_fixture, etc.) - Added custom targets for subsystem testing: - run_audio_tests, run_gpu_tests, run_3d_tests - run_assets_tests, run_util_tests, run_all_tests **Include path updates:** - Fixed relative includes in GPU tests to reference ../common/ **Documentation:** - Updated doc/HOWTO.md with subsystem test commands - Updated doc/CONTRIBUTING.md with new test organization - Updated scripts/check_all.sh to reflect new structure **Verification:** - All 36 tests passing (100%) - ctest -L <subsystem> filters work correctly - make run_<subsystem>_tests targets functional - scripts/check_all.sh passes Backward compatible: make test and ctest continue to work unchanged. handoff(Gemini): Test reorganization complete. 36/36 tests passing.
Diffstat (limited to 'src/tests/gpu/test_texture_manager.cc')
-rw-r--r--src/tests/gpu/test_texture_manager.cc257
1 files changed, 257 insertions, 0 deletions
diff --git a/src/tests/gpu/test_texture_manager.cc b/src/tests/gpu/test_texture_manager.cc
new file mode 100644
index 0000000..54a1a8a
--- /dev/null
+++ b/src/tests/gpu/test_texture_manager.cc
@@ -0,0 +1,257 @@
+// This file is part of the 64k demo project.
+// It tests the TextureManager for procedural texture generation and management.
+// Tests all public methods with both success and failure cases.
+
+#include "gpu/texture_manager.h"
+#include "procedural/generator.h"
+#include "../common/webgpu_test_fixture.h"
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+
+// Test 1: Basic initialization and shutdown
+static void test_init_shutdown() {
+ fprintf(stdout, "Testing init() and shutdown()...\n");
+
+ WebGPUTestFixture fixture;
+ if (!fixture.init()) {
+ fprintf(stdout, " ⚠ WebGPU unavailable - skipping test\n");
+ return;
+ }
+
+ TextureManager tm;
+
+ // Test init
+ tm.init(fixture.device(), fixture.queue());
+
+ // Test shutdown (should not crash with empty texture map)
+ tm.shutdown();
+
+ fprintf(stdout, " ✓ Init and shutdown OK\n");
+}
+
+// Test 2: Create texture from raw data
+static void test_create_texture_from_data() {
+ fprintf(stdout, "Testing create_texture() with raw data...\n");
+
+ WebGPUTestFixture fixture;
+ if (!fixture.init()) {
+ fprintf(stdout, " ⚠ WebGPU unavailable - skipping test\n");
+ return;
+ }
+
+ TextureManager tm;
+ tm.init(fixture.device(), fixture.queue());
+
+ // Create 4x4 red texture (RGBA8)
+ const int width = 4;
+ const int height = 4;
+ uint8_t pixels[4 * 4 * 4]; // 4x4 RGBA
+ for (int i = 0; i < width * height; ++i) {
+ pixels[i * 4 + 0] = 255; // R
+ pixels[i * 4 + 1] = 0; // G
+ pixels[i * 4 + 2] = 0; // B
+ pixels[i * 4 + 3] = 255; // A
+ }
+
+ tm.create_texture("red_texture", width, height, pixels);
+
+ // Verify texture view is valid
+ WGPUTextureView view = tm.get_texture_view("red_texture");
+ assert(view != nullptr && "Texture view should be valid");
+
+ tm.shutdown();
+ fprintf(stdout, " ✓ Create texture from raw data OK\n");
+}
+
+// Test 3: Create procedural texture
+static void test_create_procedural_texture() {
+ fprintf(stdout, "Testing create_procedural_texture()...\n");
+
+ WebGPUTestFixture fixture;
+ if (!fixture.init()) {
+ fprintf(stdout, " ⚠ WebGPU unavailable - skipping test\n");
+ return;
+ }
+
+ TextureManager tm;
+ tm.init(fixture.device(), fixture.queue());
+
+ // Create noise texture using procedural generator
+ ProceduralTextureDef noise_def;
+ noise_def.width = 64;
+ noise_def.height = 64;
+ noise_def.gen_func = procedural::gen_noise;
+ noise_def.params = {1234.0f, 1.0f}; // seed, frequency
+
+ tm.create_procedural_texture("noise", noise_def);
+
+ // Verify texture was created
+ WGPUTextureView view = tm.get_texture_view("noise");
+ assert(view != nullptr && "Procedural texture view should be valid");
+
+ tm.shutdown();
+ fprintf(stdout, " ✓ Create procedural texture OK\n");
+}
+
+// Test 4: Get texture view for non-existent texture
+static void test_get_nonexistent_texture() {
+ fprintf(stdout, "Testing get_texture_view() for non-existent texture...\n");
+
+ WebGPUTestFixture fixture;
+ if (!fixture.init()) {
+ fprintf(stdout, " ⚠ WebGPU unavailable - skipping test\n");
+ return;
+ }
+
+ TextureManager tm;
+ tm.init(fixture.device(), fixture.queue());
+
+ // Try to get non-existent texture
+ WGPUTextureView view = tm.get_texture_view("does_not_exist");
+ assert(view == nullptr && "Non-existent texture should return nullptr");
+
+ tm.shutdown();
+ fprintf(stdout, " ✓ Non-existent texture returns nullptr OK\n");
+}
+
+// Test 5: Create multiple textures and retrieve them
+static void test_multiple_textures() {
+ fprintf(stdout, "Testing multiple texture creation and retrieval...\n");
+
+ WebGPUTestFixture fixture;
+ if (!fixture.init()) {
+ fprintf(stdout, " ⚠ WebGPU unavailable - skipping test\n");
+ return;
+ }
+
+ TextureManager tm;
+ tm.init(fixture.device(), fixture.queue());
+
+ // Create multiple textures
+ const int size = 32;
+ uint8_t green_pixels[32 * 32 * 4];
+ uint8_t blue_pixels[32 * 32 * 4];
+
+ // Fill green texture
+ for (int i = 0; i < size * size; ++i) {
+ green_pixels[i * 4 + 0] = 0; // R
+ green_pixels[i * 4 + 1] = 255; // G
+ green_pixels[i * 4 + 2] = 0; // B
+ green_pixels[i * 4 + 3] = 255; // A
+ }
+
+ // Fill blue texture
+ for (int i = 0; i < size * size; ++i) {
+ blue_pixels[i * 4 + 0] = 0; // R
+ blue_pixels[i * 4 + 1] = 0; // G
+ blue_pixels[i * 4 + 2] = 255; // B
+ blue_pixels[i * 4 + 3] = 255; // A
+ }
+
+ tm.create_texture("green", size, size, green_pixels);
+ tm.create_texture("blue", size, size, blue_pixels);
+
+ // Verify both textures exist
+ WGPUTextureView green_view = tm.get_texture_view("green");
+ WGPUTextureView blue_view = tm.get_texture_view("blue");
+
+ assert(green_view != nullptr && "Green texture should exist");
+ assert(blue_view != nullptr && "Blue texture should exist");
+ assert(green_view != blue_view && "Textures should be different");
+
+ tm.shutdown();
+ fprintf(stdout, " ✓ Multiple textures OK\n");
+}
+
+// Test 6: Procedural generation failure handling
+static void test_procedural_generation_failure() {
+ fprintf(stdout, "Testing procedural generation failure handling...\n");
+
+ WebGPUTestFixture fixture;
+ if (!fixture.init()) {
+ fprintf(stdout, " ⚠ WebGPU unavailable - skipping test\n");
+ return;
+ }
+
+ TextureManager tm;
+ tm.init(fixture.device(), fixture.queue());
+
+ // Create a generator function that always fails
+ auto failing_gen = [](uint8_t* buffer, int w, int h, const float* params,
+ int num_params) -> bool {
+ (void)buffer;
+ (void)w;
+ (void)h;
+ (void)params;
+ (void)num_params;
+ return false; // Simulate failure
+ };
+
+ ProceduralTextureDef failing_def;
+ failing_def.width = 64;
+ failing_def.height = 64;
+ failing_def.gen_func = failing_gen;
+ failing_def.params = {};
+
+ // This should print error message but not crash
+ tm.create_procedural_texture("failing_texture", failing_def);
+
+ // Texture should NOT be created
+ WGPUTextureView view = tm.get_texture_view("failing_texture");
+ assert(view == nullptr &&
+ "Failed procedural generation should not create texture");
+
+ tm.shutdown();
+ fprintf(stdout, " ✓ Procedural generation failure handled OK\n");
+}
+
+// Test 7: Shutdown releases all textures
+static void test_shutdown_cleanup() {
+ fprintf(stdout, "Testing shutdown() releases all textures...\n");
+
+ WebGPUTestFixture fixture;
+ if (!fixture.init()) {
+ fprintf(stdout, " ⚠ WebGPU unavailable - skipping test\n");
+ return;
+ }
+
+ TextureManager tm;
+ tm.init(fixture.device(), fixture.queue());
+
+ // Create multiple textures
+ uint8_t pixels[16 * 16 * 4];
+ memset(pixels, 128, sizeof(pixels));
+
+ tm.create_texture("texture1", 16, 16, pixels);
+ tm.create_texture("texture2", 16, 16, pixels);
+ tm.create_texture("texture3", 16, 16, pixels);
+
+ // Verify textures exist
+ assert(tm.get_texture_view("texture1") != nullptr);
+ assert(tm.get_texture_view("texture2") != nullptr);
+ assert(tm.get_texture_view("texture3") != nullptr);
+
+ // Shutdown should release all textures
+ tm.shutdown();
+
+ // After shutdown, textures should be cleared (but we can't query them
+ // as the TextureManager's internal map is cleared)
+
+ fprintf(stdout, " ✓ Shutdown cleanup OK\n");
+}
+
+int main() {
+ fprintf(stdout, "=== TextureManager Tests ===\n");
+
+ test_init_shutdown();
+ test_create_texture_from_data();
+ test_create_procedural_texture();
+ test_get_nonexistent_texture();
+ test_multiple_textures();
+ test_procedural_generation_failure();
+ test_shutdown_cleanup();
+
+ fprintf(stdout, "=== All TextureManager Tests Passed ===\n");
+ return 0;
+}