diff options
| author | skal <pascal.massimino@gmail.com> | 2026-02-09 20:27:04 +0100 |
|---|---|---|
| committer | skal <pascal.massimino@gmail.com> | 2026-02-09 20:27:04 +0100 |
| commit | eff8d43479e7704df65fae2a80eefa787213f502 (patch) | |
| tree | 76f2fb8fe8d3db2c15179449df2cf12f7f54e0bf /src/tests/gpu/test_texture_manager.cc | |
| parent | 12378b1b7e9091ba59895b4360b2fa959180a56a (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.cc | 257 |
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; +} |
