This document provides a comprehensive guide to the testing framework used in the Hammer Game Engine project. All tests use the Boost Test Framework for consistency and are organized by component.
Current Test Coverage: 70 test executables covering AI systems, AI behaviors, UI performance, core systems, collision detection, pathfinding, WorkerBudget coordination, event management, particle systems, buffer management, rendering pipeline, SIMD correctness, camera systems, input handling, loading states, GameTime simulation, controller systems, entity state management, entity data management, background simulation, EDM integration tests, GPU rendering subsystem (when USE_SDL3_GPU=ON), and utility components with both functional validation and performance benchmarking.
The Hammer Game Engine has the following test suites:
-
AI System Tests
- AI Optimization Tests: Verify performance optimizations in the AI system
- Thread-Safe AI Tests: Validate thread safety of the AI management system
- Thread-Safe AI Integration Tests: Test integration of AI components with threading
- AI Benchmark Tests: Measure performance characteristics and scaling capabilities
- Behavior Functionality Tests: Comprehensive validation of all 8 AI behaviors and their modes
- ThreadSystem Queue Load Tests: Defensive monitoring to prevent ThreadSystem overload
- AIManager EDM Integration Tests: Validate AIManager's integration with EntityDataManager (sparse behavior vector, batch processing, state transitions)
-
UI System Tests
- UI Stress Tests: Validate UI performance and scalability in headless mode
- UI Benchmark Tests: Measure UI component processing throughput and memory efficiency
- UIManagerFunctionalTests: Comprehensive UI component creation, management, and interaction
-
Core Systems Tests
- Buffer Reuse Tests: Validate memory allocation patterns and buffer reuse across frames
- Camera Tests: Validate camera world/screen coordinate transformations
- InputManager Tests: Validate input handling and coordinate conversion
- Loading State Tests: Test async loading and deferred state transitions
- Rendering Pipeline Tests: Validate frame pacing and render coordination
- Save Manager Tests: Validate save/load functionality with directory creation and file operations
- Thread System Tests: Verify multi-threading capabilities and priority scheduling
- ThreadSystem Load Monitoring: Defensive tests ensuring AI doesn't overwhelm 4096 task limit
- Event Manager Tests: Validate event handling and integration with threading
- Event Types Tests: Test specific event type implementations (Weather, Scene Change, NPC Spawn)
- Weather Event Tests: Focused tests for weather event functionality
- Event Manager Scaling Benchmark: Performance testing for event system scalability
- Event Coordination Integration Tests: Multi-system event coordination and synchronization
- Particle Manager Tests: Comprehensive particle system validation covering core functionality, weather integration, performance, and threading
-
Collision System Tests
- AABB Tests: Validate axis-aligned bounding box intersection, containment, and closest point calculations
- SpatialHash Tests: Test spatial hash insertion, removal, updating, and querying with deduplication
- Collision Performance Tests: Benchmark insertion, query, and update operations with up to 10K entities
- Collision Stress Tests: High-density collision detection and boundary condition testing
- AI Collision Integration Tests: Integration tests for AI pathfinding with collision system
- CollisionManager EDM Integration Tests: Validate CollisionManager's integration with EntityDataManager (active tier filtering, dual index semantics, static/dynamic separation)
-
Pathfinding System Tests
- PathfindingGrid Tests: Validate A* pathfinding algorithm with grid coordinate conversion
- Pathfinding Configuration Tests: Test diagonal movement, cost configuration, and iteration limits
- Dynamic Weight Tests: Validate weight-based avoidance areas and path cost modification
- Pathfinding Performance Tests: Benchmark pathfinding across various grid sizes (50x50 to 200x200)
- Edge Case Tests: Test blocked start/goal positions, extreme distances, and nearest open cell finding
- PathfinderManager & AIManager Contention Tests: Integration tests for WorkerBudget coordination under heavy load
-
SIMD & Performance Tests
- SIMD Correctness Tests: Cross-platform SIMD correctness validation (SSE2/AVX2/NEON)
- SIMD Performance Benchmark: Performance validation of SIMD optimizations in AIManager, CollisionManager, ParticleManager
- Integrated System Benchmark: Full system performance profiling across all major systems
-
Utility System Tests
- JsonReader Tests: RFC 8259 compliant JSON parser validation with comprehensive error handling and type safety testing
-
GameTime System Tests
- GameTime Tests: Validate core time advancement, tick system, and time configuration
- GameTime Calendar Tests: Test fantasy calendar (months, days, year cycles)
- GameTime Season Tests: Validate seasonal transitions and weather probability changes
-
Controller Tests
- ControllerRegistry Tests: Type-safe controller registration, lifecycle management, batch operations
- WeatherController Tests: Weather event coordination and state transitions
- DayNightController Tests: Time period tracking and visual transitions
-
Entity State Machine Tests
- EntityStateManager Tests: State registration, transitions, lifecycle callbacks (enter/exit/update)
-
Entity Data Management Tests
- EntityDataManager Tests: Data-oriented entity storage, handle validation, tier management
- BackgroundSimulationManager Tests: Background entity simulation, tier-based processing, pause/resume
-
EDM Integration Tests
- AIManager EDM Integration Tests: Sparse behavior vector, batch processing with EDM indices, state transitions
- CollisionManager EDM Integration Tests: Active tier filtering, dual index semantics, static/dynamic separation
-
GPU System Tests (conditional on USE_SDL3_GPU)
- GPU Types Tests: Vertex struct layouts (SpriteVertex, ColorVertex), UBO alignment validation
- GPU Pipeline Config Tests: Pipeline configuration factory methods, blend modes
- GPU Device Tests: Device lifecycle, shader format queries, swapchain format
- GPU Shader Manager Tests: Shader loading, caching, SPIR-V/Metal path validation
- GPU Resource Tests: Buffer, texture, transfer buffer, sampler wrappers
- GPU Vertex Pool Tests: Triple-buffered vertex pool, frame cycling
- Sprite Batch Tests: Batch recording, vertex data verification
- GPU Renderer Tests: Full frame flow, pipeline/pool accessors, composite rendering
Test Execution Categories:
- Core Tests (16 suites): Fast functional validation (~4-8 minutes total)
- Benchmarks (5 suites): Performance and scalability testing (~8-20 minutes total)
- GPU Tests (8 suites): SDL3 GPU rendering validation (when USE_SDL3_GPU=ON)
- Total Coverage: 70 test executables with comprehensive automation scripts
Each test suite has dedicated scripts in the tests/test_scripts/ directory:
# Core functionality tests (fast execution)
./tests/test_scripts/run_thread_tests.sh # Thread system tests
./tests/test_scripts/run_buffer_utilization_tests.sh # WorkerBudget buffer thread utilization tests
./tests/test_scripts/run_thread_safe_ai_tests.sh # Thread-safe AI tests
./tests/test_scripts/run_thread_safe_ai_integration_tests.sh # Thread-safe AI integration tests
./tests/test_scripts/run_ai_optimization_tests.sh # AI optimization tests
./tests/test_scripts/run_behavior_functionality_tests.sh # Comprehensive AI behavior validation tests
./tests/test_scripts/run_save_tests.sh # Save manager and BinarySerializer tests
./tests/test_scripts/run_event_tests.sh # Event manager tests
./tests/test_scripts/run_json_reader_tests.sh # JSON parser validation tests
./tests/test_scripts/run_collision_tests.sh # Collision system and spatial hash tests
./tests/test_scripts/run_pathfinding_tests.sh # Pathfinding algorithm and grid tests
./tests/test_scripts/run_pathfinder_ai_contention_tests.sh # PathfinderManager & AIManager WorkerBudget coordination tests
./tests/test_scripts/run_game_time_tests.sh # GameTime system tests
./tests/test_scripts/run_controller_tests.sh # Controller tests (Registry, Weather, DayNight)
./tests/test_scripts/run_entity_state_manager_tests.sh # Entity state machine tests
./tests/test_scripts/run_entity_data_manager_tests.sh # EntityDataManager and BackgroundSimulationManager tests
./tests/test_scripts/run_ai_manager_edm_integration_tests.sh # AIManager EDM integration tests
./tests/test_scripts/run_collision_manager_edm_integration_tests.sh # CollisionManager EDM integration tests
# Performance scaling benchmarks (slow execution)
./tests/test_scripts/run_event_scaling_benchmark.sh # Event manager scaling benchmark
./tests/test_scripts/run_ai_benchmark.sh # AI scaling benchmark with realistic automatic threading
./tests/test_scripts/run_ui_stress_tests.sh # UI stress and performance tests
./tests/test_scripts/run_collision_benchmark.sh # Collision system performance benchmarks
./tests/test_scripts/run_pathfinder_benchmark.sh # Pathfinder system performance benchmarks
# Run all tests
./tests/test_scripts/run_all_tests.sh # Run all test scripts sequentially
# AI benchmark test examples with automatic threading
./tests/test_scripts/run_ai_benchmark.sh # Full realistic benchmark suite
./tests/test_scripts/run_ai_benchmark.sh --realistic-only # Clean realistic performance tests
./tests/test_scripts/run_ai_benchmark.sh --stress-test # 100K entity stress test only
./tests/test_scripts/run_ai_benchmark.sh --threshold-test # Threading threshold validation (200 entities)
# Individual UI stress test examples
./tests/test_scripts/run_ui_stress_tests.sh --level light --duration 30 # Quick UI test
./tests/test_scripts/run_ui_stress_tests.sh --level heavy --duration 60 # Heavy load test
./tests/test_scripts/run_ui_stress_tests.sh --benchmark # UI benchmark suite
./tests/test_scripts/run_ui_stress_tests.sh --level medium --verbose # Detailed output
# Save manager test examples with BinarySerializer
./tests/test_scripts/run_save_tests.sh --save-test # Basic save/load operations
./tests/test_scripts/run_save_tests.sh --serialization-test # New BinarySerializer system tests
./tests/test_scripts/run_save_tests.sh --performance-test # Serialization performance benchmarks
./tests/test_scripts/run_save_tests.sh --integration-test # BinarySerializer integration tests
./tests/test_scripts/run_save_tests.sh --error-test # Error handling tests
./tests/test_scripts/run_save_tests.sh --verbose # Detailed test output
# JSON reader test examples
./tests/test_scripts/run_json_reader_tests.sh --parse-test # Basic JSON parsing validation
./tests/test_scripts/run_json_reader_tests.sh --error-test # Error handling and malformed JSON tests
./tests/test_scripts/run_json_reader_tests.sh --file-test # File loading functionality tests
./tests/test_scripts/run_json_reader_tests.sh --game-test # Game item data parsing tests
./tests/test_scripts/run_json_reader_tests.sh --verbose # Detailed test output with all test cases# Core functionality tests (fast execution)
tests/test_scripts/run_thread_tests.bat # Thread system tests
tests/test_scripts/run_thread_safe_ai_tests.bat # Thread-safe AI tests
tests/test_scripts/run_thread_safe_ai_integration_tests.bat # Thread-safe AI integration tests
tests/test_scripts/run_ai_optimization_tests.bat # AI optimization tests
tests/test_scripts/run_behavior_functionality_tests.bat # Comprehensive AI behavior validation tests
tests/test_scripts/run_ai_benchmark.bat # AI scaling benchmark with realistic automatic threading
tests/test_scripts/run_save_tests.bat # Save manager and BinarySerializer tests
tests/test_scripts/run_event_tests.bat # Event manager tests
tests/test_scripts/run_collision_tests.bat # Collision system and spatial hash tests
tests/test_scripts/run_pathfinding_tests.bat # Pathfinding algorithm and grid tests
tests/test_scripts/run_game_time_tests.bat # GameTime system tests
tests/test_scripts/run_controller_tests.bat # Controller tests (Registry, Weather, DayNight)
tests/test_scripts/run_entity_state_manager_tests.bat # Entity state machine tests
tests/test_scripts/run_entity_data_manager_tests.bat # EntityDataManager and BackgroundSimulationManager tests
tests/test_scripts/run_ai_manager_edm_integration_tests.bat # AIManager EDM integration tests
tests/test_scripts/run_collision_manager_edm_integration_tests.bat # CollisionManager EDM integration tests
tests/test_scripts/run_json_reader_tests.bat # JSON parser validation tests
# Performance scaling benchmarks (slow execution)
tests/test_scripts/run_event_scaling_benchmark.bat # Event manager scaling benchmark
tests/test_scripts/run_ai_benchmark.bat # AI scaling benchmark
tests/test_scripts/run_ui_stress_tests.bat # UI stress and performance tests
tests/test_scripts/run_collision_benchmark.bat # Collision system performance benchmarks
tests/test_scripts/run_pathfinder_benchmark.bat # Pathfinder system performance benchmarks
# Run all tests
tests/test_scripts/run_all_tests.bat # Run all test scripts sequentially
# Individual UI stress test examples
tests/test_scripts/run_ui_stress_tests.bat /l light /d 30 # Quick UI test
tests/test_scripts/run_ui_stress_tests.bat /l heavy /d 60 # Heavy load test
tests/test_scripts/run_ui_stress_tests.bat /b # UI benchmark suite
tests/test_scripts/run_ui_stress_tests.bat /l medium /v # Detailed output
# Save manager test examples with BinarySerializer
tests/test_scripts/run_save_tests.bat --save-test # Basic save/load operations
tests/test_scripts/run_save_tests.bat --serialization-test # New BinarySerializer system tests
tests/test_scripts/run_save_tests.bat --performance-test # Serialization performance benchmarks
tests/test_scripts/run_save_tests.bat --integration-test # BinarySerializer integration tests
tests/test_scripts/run_save_tests.bat --error-test # Error handling tests
tests/test_scripts/run_save_tests.bat --verbose # Detailed test output
The tests/test_scripts/run_all_tests.sh script provides flexible execution control:
| Option | Description | Duration |
|---|---|---|
--core-only |
Run only core functionality tests | ~2-5 minutes |
--benchmarks-only |
Run only performance benchmarks (AI, Event, UI, Collision, Pathfinder) | ~8-20 minutes |
--no-benchmarks |
Run core tests but skip benchmarks | ~2-5 minutes |
| (default) | Run all tests sequentially | ~10-25 minutes |
# Quick validation during development
./tests/test_scripts/run_all_tests.sh --core-only
# Skip slow benchmarks in CI
./tests/test_scripts/run_all_tests.sh --no-benchmarks
# Performance testing only
./tests/test_scripts/run_all_tests.sh --benchmarks-only --verbose
# Complete test suite
./tests/test_scripts/run_all_tests.shIndividual test scripts support these options:
| Option | Description |
|---|---|
--verbose |
Show detailed test output |
--release |
Run tests in release mode (optimized) |
--clean |
Clean test artifacts before building |
--help |
Show help message for the script |
Special options:
--extremefor AI benchmark (runs extended benchmarks)--verbosefor scaling benchmarks (shows detailed performance metrics)--level LEVELfor UI stress tests (light|medium|heavy|extreme)--duration SECONDSfor UI stress tests (custom test duration)--benchmarkfor UI stress tests (runs benchmark suite instead of stress tests)
Test Execution Strategy: The script executes tests in optimal order for efficient development workflow:
- Core functionality tests (fast execution, ~5-30 seconds each)
- Performance scaling benchmarks (slow execution, 1-5+ minutes each)
This ordering provides quick feedback on basic functionality before running time-intensive performance tests.
Test results are saved in the test_results directory:
ai_optimization_tests_output.txt- Output from AI optimization testsevent_scaling_benchmark_output.txt- Output from EventManager scaling benchmarkai_optimization_tests_performance_metrics.txt- Performance metrics from optimization teststhread_safe_ai_test_output.txt- Output from thread-safe AI teststhread_safe_ai_performance_metrics.txt- Performance metrics from thread-safe AI testsai_scaling_benchmark_[timestamp].txt- AI scaling benchmark resultsui_stress/ui_stress_test_[timestamp].log- UI stress test results with performance metricssave_test_output.txt- Output from save manager teststhread_test_output.txt- Output from thread system testsevent_test_output.txt- Output from event manager testsevent_types_test_output.txt- Output from event types testsweather_event_test_output.txt- Output from weather event tests
When using the tests/test_scripts/run_all_tests scripts, combined results are also saved:
combined/all_tests_results.txt- Summary of all test script results
Located in AIOptimizationTest.cpp, these tests verify:
- Entity Component Caching: Tests caching mechanisms for faster entity-behavior lookups
- Batch Processing: Validates efficient batch processing of entities with similar behaviors
- Early Exit Conditions: Tests optimizations that skip unnecessary updates
- Message Queue System: Verifies batched message processing for efficient AI communication
- Priority-Based Scheduling: Tests the task priority system integration with AI behaviors
Located in ThreadSafeAIManagerTest.cpp, these tests verify:
- Thread-Safe Behavior Registration: Tests concurrent registration of behaviors
- Thread-Safe Entity Assignment: Validates behavior assignment from multiple threads
- Concurrent Behavior Processing: Tests running AI behaviors across multiple threads
- Thread-Safe Cache Invalidation: Validates optimization cache in multi-threaded context
- Thread-Safe Messaging: Tests message queuing with concurrent access
Special considerations for thread-safety tests:
- Use atomic operations with proper synchronization
- Disable threading before cleanup to prevent segmentation faults
- Allow time between operations for thread synchronization
- Use timeout when waiting for futures to prevent hanging
Located in AIScalingBenchmark.cpp, these tests measure realistic performance characteristics:
-
Realistic Performance Testing: Tests automatic threading behavior across key entity counts
- 100 entities: Validates single-threaded baseline (~170K updates/sec)
- 200+ entities: Validates automatic threading activation (~750K updates/sec)
- 1000+ entities: Confirms high-performance threading (~975K updates/sec)
- 10K entities: Target performance validation (~995K updates/sec, 5.85x improvement)
-
Realistic Scalability: Tests clean automatic threading behavior across entity ranges
- Tests 100-10K entity range with automatic mode selection
- Validates 200-entity threading threshold effectiveness (4.41x performance jump)
- Demonstrates consistent high performance scaling (5.29x-5.85x ratios)
-
Legacy Comparison: Forced threading modes for comparison with previous benchmarks
- Single-threaded forced mode for baseline comparison
- Multi-threaded forced mode for maximum performance comparison
-
Stress Testing: 100K entity extreme load testing
- Validates system stability under extreme stress
- Tests WorkerBudget system coordination
- Confirms queue capacity handling (4096 tasks)
Key Performance Targets:
- 100 entities: Single-threaded baseline (~170K updates/sec)
- 200 entities: Automatic threading activation (~750K updates/sec)
- 1000 entities: High threading performance (~975K updates/sec)
- 10K entities: Target performance achieved (~995K updates/sec, 5.85x improvement)
- 100K entities: Stress test validation (2.2M+ updates/sec)
Located in ui/ui_stress_test_main.cpp, these tests run in headless mode and measure:
- Processing Throughput: Components processed per second (real UI workload capacity)
- Memory Efficiency: Memory usage per component and total consumption
- Scalability: Performance degradation as component count increases
- Layout Performance: Layout calculations per second for responsive UI
- Input Responsiveness: Collision detection rate for mouse/touch interaction
- Iteration Performance: Time to process all UI components once
Key Metrics Measured:
- Processing Throughput: ~100k-400k components/sec (indicates UI system capacity)
- Average Iteration Time: ~0.25ms (UI overhead per frame, should be <1ms for 60fps)
- Memory Usage: Tracks peak memory consumption and growth per component
- Performance Degradation: How performance scales with component count (<2x ideal)
- Layout Calculations/sec: Algorithm performance for responsive layouts
- Collision Checks/sec: Input system responsiveness capacity
Test Modes:
- Stress Test: Creates components over time while measuring performance
- Benchmark Suite: Runs multiple test scenarios and compares results
- Headless Operation: No SDL video initialization - perfect for CI/automation
Real-World Application:
- Mobile games: Validate UI memory stays under 50MB
- Desktop games: Ensure UI uses <1% of 60fps frame budget
- Complex UIs: Test thousands of interactive elements
- Performance regression: Detect UI optimization regressions
Meaningful Headless Metrics: The UI stress tests run in headless mode and provide meaningful performance metrics instead of artificially high FPS numbers:
- Processing Throughput replaces meaningless FPS - shows actual UI workload capacity
- Average Iteration Time shows real UI system overhead per frame
- Memory per Component tracks actual resource consumption
- Performance Degradation measures scalability characteristics
- Layout/Collision rates show algorithm performance for real UI operations
This approach provides actionable insights for UI system optimization rather than misleading FPS metrics that don't reflect real rendering constraints.
Usage Examples:
# Quick development validation
./tests/test_scripts/run_ui_stress_tests.sh --level light --duration 10
# CI/CD pipeline validation
./tests/test_scripts/run_ui_stress_tests.sh --level medium --duration 30
# Performance profiling
./tests/test_scripts/run_ui_stress_tests.sh --benchmark --verbose
# Stress testing with custom parameters
./tests/test_scripts/run_ui_stress_tests.sh --level extreme --duration 120 --max-components 2000Located in SaveManagerTests.cpp with supporting MockPlayer class, these tests verify the BinarySerializer integration that replaces Boost serialization:
-
BinarySerializer Integration: Tests the new fast, header-only serialization system:
- Tests
BinarySerial::WriterandBinarySerial::Readerclasses - Verifies smart pointer-based memory management
- Tests convenience functions
saveToFile()andloadFromFile() - Validates cross-platform binary compatibility
- Tests
-
Data Serialization: Tests serialization of game objects using the new system:
TestNewSerializationSystem: Vector2D and custom object serializationTestBinaryWriterReader: Primitive types, strings, and direct Writer/Reader usageTestVectorSerialization: Container serialization with safety checksTestBinarySerializerIntegration: End-to-end serialization testing
-
Performance Testing:
TestPerformanceComparisonbenchmarks:- 100 serialization operations timing (typically ~13-25ms)
- Memory usage validation
- Cross-platform performance verification
-
File Operations: Tests using BinarySerializer for save file management:
TestSaveAndLoad: Basic save/load operations with MockPlayerTestSlotOperations: Multiple file handling and cleanup- File existence validation and proper error handling
-
Error Handling:
TestErrorHandlingcovers:- Non-existent file handling
- Invalid file path recovery
- Corrupted data detection through the BinarySerializer safety checks
Key Features Tested:
- Fast Performance: 10x faster than Boost for primitives, 4x faster for strings
- Smart Pointer Safety: Automatic memory management with
std::shared_ptrandstd::unique_ptr - Type Safety: Compile-time checks for trivially copyable types
- Logging Integration: Proper integration with Forge logging system (
SAVEGAME_*macros) - Cross-Platform: Header-only solution works on Windows, macOS, and Linux
Located in ThreadSystemTests.cpp, these tests verify:
- Task Scheduling: Tests scheduling and execution of tasks
- Thread Safety: Tests synchronization mechanisms
- Performance: Tests scaling with different numbers of threads
- Error Handling: Tests recovery from failed tasks
- Priority System: Tests the task priority levels (Critical, High, Normal, Low, Idle)
- Priority Scheduling: Verifies that higher priority tasks execute before lower priority ones
Located in BufferUtilizationTest.cpp, these tests verify the intelligent buffer thread utilization system:
- Hardware Tier Classification: Tests allocation strategies across ultra low-end to very high-end systems
- Dynamic Buffer Scaling: Validates workload-based buffer utilization (AI: >1000 entities, Events: >100 events)
- Conservative Burst Strategy: Tests systems using maximum 50% of base allocation from buffer
- Resource Allocation Logic: Verifies no over-allocation and proper fallback behavior
- Graceful Degradation: Tests single-threaded fallback on resource-constrained systems
Test Coverage:
- Ultra Low-End (1 worker): GameLoop only, AI/Events/Particles single-threaded
- Low-End (3-4 workers): Conservative allocation with limited buffer
- Target Minimum (7 workers): Optimal allocation (GameLoop: 1, AI: 3, Particles: 1, Buffer: 2)
- High-End (12+ workers): Full buffer utilization for burst capacity
Validation Examples:
# 12-worker system test results:
Base allocations - GameLoop: 2, AI: 6, Events: 3, Buffer: 1
Low workload (500 entities): 6 workers # Uses base allocation
High workload (5000 entities): 7 workers # Uses base + buffer
# 16-worker system test results:
Very high workload burst: 10 workers # AI gets 8 base + 2 bufferThe tests ensure the WorkerBudget system provides guaranteed minimum performance while enabling intelligent scaling for high workloads without resource conflicts.
Located in events/EventManagerTest.cpp, events/EventTypesTest.cpp, events/WeatherEventTest.cpp, and EventManagerScalingBenchmark.cpp, these tests verify:
- Event Registration: Tests registering different types of events with the EventManager
- Event Conditions: Tests condition-based event triggering
- Event Execution: Validates proper execution of event sequences
- Thread-Safe Processing: Tests concurrent event processing using ThreadSystem
- Message System: Tests the event messaging system for communication between events
- Priority-Based Scheduling: Tests task priority integration with event processing
- NPCSpawnEvent Integration: Tests NPC spawning functionality with mocked dependencies
- Performance Scaling: Comprehensive benchmarking from small to extreme scales (see EventManager Scaling Benchmark below)
EventManagerTest.cpp focuses on EventManager integration:
- Event registration and retrieval
- Event activation/deactivation
- Event messaging system
- Thread-safe event processing
- NPCSpawnEvent integration with EventManager
EventTypesTest.cpp tests specific event type implementations:
- WeatherEvent creation and parameter setting
- SceneChangeEvent functionality
- NPCSpawnEvent creation, spawn parameters, conditions, and limits
- EventFactory event creation methods
- Event sequences and cooldown functionality
WeatherEventTest.cpp provides focused weather event testing:
- Weather state transitions
- Particle effect integration
- Sound effect integration
- Time-based weather conditions
The NPCSpawnEvent tests use a comprehensive mocking infrastructure to avoid dependencies on the full game engine:
Mock Components:
MockNPC.hpp/cpp: Mock NPC class implementing Entity interface without game engine dependenciesMockGameEngine.hpp/cpp: Mock GameEngine providing basic window dimensions for testingNPCSpawnEventTest.cpp: Test-specific NPCSpawnEvent implementation using mocks
Mock Features:
- Complete NPCSpawnEvent functionality testing without real game engine
- Proper Vector2D usage with
getX()/getY()andsetX()/setY()methods - Correct Event base class implementation
- Mock entity creation and management
- Spawn parameter validation and condition testing
- Respawn logic and timer functionality
- Proximity and area-based spawning tests
Test Coverage:
- Spawn parameters (count, radius, positioning)
- Spawn conditions (proximity, time of day, custom conditions)
- Spawn limits and counting
- Respawn functionality and timing
- Spawn area management (points, rectangles, circles)
- Entity lifecycle and cleanup
- Message-based spawn requests
Located in EventManagerScalingBenchmark.cpp, this comprehensive performance test validates the EventManager's scalability across various workloads:
Test Scenarios:
- Basic Performance: Small scale validation (100 events, immediate vs batched)
- Medium Scale: Moderate load testing (5,000 events, 25,000 handler calls)
- Scalability Suite: Progressive testing from minimal to very large scales
- Concurrency Test: Multi-threaded event generation and processing
- Extreme Scale: Large simulation testing (100,000 events, 5,000,000 handler calls)
Performance Metrics Measured:
- Events per second throughput
- Handler calls per second
- Time per event and per handler call
- Memory usage and cache performance
- Thread safety validation
- Batching vs immediate processing comparison
Key Features Tested:
- Handler batching system performance
boost::flat_mapstorage optimization- Thread-safe concurrent event queuing
- Lock-free handler execution
- Cache locality optimization through event type grouping
Running the Scaling Benchmark:
# Run just the scaling benchmark
ctest -R EventManagerScaling
# Or run the executable directly for detailed output
./bin/debug/event_manager_scaling_benchmarkExpected Performance (on modern hardware):
- Small scale: ~540K events/sec
- Medium scale: ~78K events/sec
- Large scale: ~39K events/sec
- Extreme scale: ~7.8K events/sec with 5M handler calls
The benchmark validates that the EventManager can handle large-scale simulations (MMOs, city simulations, real-time strategy games) while maintaining consistent performance characteristics.
Located in particle/ directory, these tests provide comprehensive validation of the ParticleManager system covering core functionality, weather integration, performance benchmarks, and threading safety.
1. Core Tests (ParticleManagerCoreTest.cpp)
14 test cases covering basic ParticleManager functionality:
- Initialization and cleanup
- Effect registration and management
- Particle creation and lifecycle
- Global pause/resume functionality
- Performance statistics
- State transition handling
2. Weather Integration Tests (ParticleManagerWeatherTest.cpp)
9 test cases covering weather system integration:
- Weather effect triggering (Rain, Snow, Fog, Cloudy, Stormy, Clear)
- Weather transitions and timing
- Weather-specific particle behavior
- Intensity scaling
- Weather effect cleanup
- Multiple weather effect handling
3. Performance Tests (ParticleManagerPerformanceTest.cpp)
8 test cases covering performance characteristics:
- Large-scale particle simulation (1000+ particles)
- Update performance scaling
- Memory usage efficiency
- Sustained performance benchmarks
- Different effect type performance
- Cleanup performance
4. Threading Tests (ParticleManagerThreadingTest.cpp)
7 test cases covering multi-threading safety:
- Concurrent particle creation
- Thread-safe effect management
- Concurrent weather changes (using
triggerWeatherEffect()for accurate marking) - Parallel statistics access
- Mixed concurrent operations
- Enhanced resource cleanup safety with proper weather effect stopping
Quick Commands:
# Run all particle manager tests (4-6 minutes)
./tests/test_scripts/run_particle_manager_tests.sh
# Quick core validation (30 seconds)
./tests/test_scripts/run_particle_manager_tests.sh --core
# Weather functionality only (45 seconds)
./tests/test_scripts/run_particle_manager_tests.sh --weather
# Performance benchmarks (2-3 minutes)
./tests/test_scripts/run_particle_manager_tests.sh --performance
# Threading safety tests (1-2 minutes)
./tests/test_scripts/run_particle_manager_tests.sh --threading
# Verbose output
./tests/test_scripts/run_particle_manager_tests.sh --verboseCross-Platform Support:
- Linux/macOS:
run_particle_manager_tests.sh - Windows:
run_particle_manager_tests.bat
Both scripts support identical command-line options and functionality.
Test Results: Test results are automatically saved to:
test_results/particle_manager/- Individual test outputstest_results/particle_manager/all_particle_tests_results.txt- Combined summary
The particle manager tests are integrated into the main test runner:
# All tests (includes particle manager tests)
./tests/test_scripts/run_all_tests.sh
# Core functionality only (includes particle manager core tests)
./tests/test_scripts/run_all_tests.sh --core-onlyLocated in tests/collisions/CollisionSystemTests.cpp, these tests comprehensively validate the spatial hash collision system:
-
AABB Tests (
AABBTestssuite):- Basic bounding box properties (left, right, top, bottom)
- Intersection detection between AABBs
- Point containment testing
- Closest point calculation for AABBs
-
SpatialHash Tests (
SpatialHashTestssuite):- Entity insertion and spatial partitioning
- Entity removal and cell cleanup
- Position updates with cell transitions
- Query operations with result deduplication
- Clear operations for spatial hash cleanup
-
Performance Tests (
CollisionPerformanceTestssuite):- Insertion performance with up to 10,000 entities
- Query performance across various entity densities
- Update performance during entity movement
- Scalability benchmarking with performance assertions
-
Stress Tests (
CollisionStressTestssuite):- High-density collision detection (20 entities per cell)
- Boundary condition handling
- Large entity spanning multiple cells
- Edge case validation
# Linux/macOS
./tests/test_scripts/run_collision_tests.sh [--verbose]
# Windows
tests/test_scripts/run_collision_tests.bat [--verbose]Performance Targets:
- SpatialHash insertion: < 50μs per entity
- SpatialHash query: < 100μs per query
- SpatialHash update: < 75μs per update
Located in tests/pathfinding/PathfindingSystemTests.cpp, these tests validate the A* pathfinding implementation:
-
PathfindingGrid Basic Tests (
PathfindingGridBasicTestssuite):- Grid coordinate conversion (world ↔ grid)
- Bounds checking for grid coordinates
- Pathfinding system configuration (diagonal movement, costs, iteration limits)
-
Algorithm Tests (
PathfindingAlgorithmTestssuite):- A* pathfinding correctness validation
- Invalid start/goal position handling
- Same start/goal position edge cases
- Diagonal vs orthogonal movement comparison
-
Weight System Tests (
PathfindingWeightTestssuite):- Dynamic weight area application
- Weight circle placement and overlapping
- Path cost modification through weight systems
-
Performance Tests (
PathfindingPerformanceTestssuite):- Pathfinding across various grid sizes (50x50 to 200x200)
- Iteration limit impact on performance
- Memory usage validation through stress testing
-
Edge Cases (
PathfindingEdgeCaseTestssuite):- Nearest open cell finding for blocked positions
- Pathfinding with dynamic weight areas
- Extreme distance pathfinding
# Linux/macOS
./tests/test_scripts/run_pathfinding_tests.sh [--verbose]
# Windows
tests/test_scripts/run_pathfinding_tests.bat [--verbose]Performance Targets:
- Small grids (≤100x100): < 10ms per pathfinding request
- Large grids (≤200x200): < 50ms per pathfinding request
- Iteration limits prevent indefinite stalls
Located in tests/integration/PathfinderAIContentionTests.cpp, these integration tests validate WorkerBudget coordination between PathfinderManager and AIManager under heavy load:
-
WorkerBudget Allocation Tests:
- Verify each manager gets all workers during its update window (sequential execution model)
- Validate WorkerBudget returns full worker count for any active workload
- Confirm adaptive batch tuning adjusts based on timing feedback
- Check queue pressure monitoring prevents ThreadSystem overload
-
Simultaneous Load Tests:
- Submit 100+ simultaneous pathfinding requests alongside AI updates
- Validate both managers process work without starvation
- Confirm rate limiting (50 requests/frame) prevents queue flooding
- Verify queue pressure stays below critical threshold (< 95%)
-
Worker Starvation Prevention:
- Heavy load testing with 200+ pathfinding requests
- Concurrent AIManager updates to simulate realistic game conditions
- Validate neither manager monopolizes ThreadSystem workers
- Confirm graceful degradation under extreme stress
-
Queue Pressure Coordination:
- Test 150+ requests triggering rate limiting
- Monitor queue pressure across multiple update frames
- Verify adaptive batching responds to queue pressure
- Validate Normal priority prevents AIManager contention
# Linux/macOS
./tests/test_scripts/run_pathfinder_ai_contention_tests.sh [--verbose]
# Windows
tests/test_scripts/run_pathfinder_ai_contention_tests.bat [--verbose]Key Validations:
- WorkerBudget integration: Pathfinding uses 19% allocation properly
- Request batching: Adaptive batch sizes based on available workers
- Rate limiting: Maximum 50 requests processed per frame
- Queue pressure: Monitoring triggers graceful degradation
- No worker starvation: Both managers make progress under heavy load
Estimated Runtime: ~2 seconds (4 integration tests)
Located in tests/performance/CollisionBenchmark.cpp, this dedicated benchmark suite measures collision system performance:
- CollisionManager SOA Storage: Structure-of-Arrays performance testing
- SpatialHash Performance: Insertion, query, and update scaling (100 to 10,000 entities)
- Broadphase/Narrowphase Detection: Collision detection pipeline performance
- Threading Comparison: Single-threaded vs multi-threaded performance analysis
# Linux/macOS
./tests/test_scripts/run_collision_benchmark.sh [--verbose]
# Windows
tests/test_scripts/run_collision_benchmark.bat [--verbose]Estimated Runtime: 2-3 minutes
Performance Targets:
- SpatialHash insertion: < 50μs per entity
- SpatialHash query: < 100μs per query
- SpatialHash update: < 75μs per update
- Collision detection: < 5ms for 1000 entities
Located in tests/performance/PathfinderBenchmark.cpp, this dedicated benchmark suite measures pathfinding system performance:
- Immediate Pathfinding: Performance across grid sizes (50x50 to 200x200)
- Async Pathfinding: Request throughput and latency analysis
- Cache Performance: Hit rate analysis and speedup measurements
- Path Length Scaling: Computation time vs path complexity
- Threading Analysis: Overhead vs benefits comparison
# Linux/macOS
./tests/test_scripts/run_pathfinder_benchmark.sh [--verbose]
# Windows
tests/test_scripts/run_pathfinder_benchmark.bat [--verbose]Estimated Runtime: 3-5 minutes
Performance Targets:
- Immediate pathfinding: < 20ms per request
- Async throughput: > 100 paths/second
- Cache speedup: > 2x for repeated paths
- Success rate: > 90% for reasonable requests
Output Files:
test_results/collision_benchmark.csv- Collision system detailed metricstest_results/pathfinder_benchmark.csv- Pathfinder system detailed metricstest_results/collision_benchmark_results.txt- Human-readable collision resultstest_results/pathfinder_benchmark_results.txt- Human-readable pathfinder results
✅ Passing Test Suites:
- Core Tests: 14/14 passing - Basic functionality verified
- Weather Tests: 9/9 passing - Weather integration working correctly
- Performance Tests: Some tests may fail on slower systems or under load
- Threading Tests: Concurrency tests may be sensitive to system timing
These issues don't affect core functionality but may require system-specific tuning.
Expected Performance (Debug builds):
- Core tests: Complete in ~30 seconds
- Weather tests: Complete in ~45 seconds
- Performance tests: Complete in 2-3 minutes
- Threading tests: Complete in 1-2 minutes
Scaling Behavior: The ParticleManager is designed to handle:
- 1000+ active particles efficiently
- Multiple concurrent weather effects
- Thread-safe operations across multiple cores
- Sustained 60 FPS performance with realistic particle loads
Performance tests validate these capabilities and benchmark actual system performance.
Recent fixes to weather tests addressed:
- Timing issues: Tests now use multiple update cycles for particle emission
- Weather type mapping: Consistent use of weather type names (e.g., "Rainy" vs "Rain")
- Low emission rates: Special handling for effects like "Cloudy" with very low emission rates
- Particle lifecycle: Proper handling of particle fade and cleanup behavior
These fixes ensure reliable weather functionality testing across different systems.
5. Test Adjustments: Weather effects are now created using triggerWeatherEffect() to ensure proper marking and cleanup consistent with expected ParticleManager behavior.
Adding New Tests:
- Core functionality: Add to
ParticleManagerCoreTest.cpp - Weather features: Add to
ParticleManagerWeatherTest.cpp - Performance cases: Add to
ParticleManagerPerformanceTest.cpp - Threading scenarios: Add to
ParticleManagerThreadingTest.cpp
Test Fixture Pattern: All test files use the same fixture pattern:
struct ParticleManagerTestFixture {
ParticleManagerTestFixture() {
manager = &ParticleManager::Instance();
if (manager->isInitialized()) {
manager->clean();
}
}
~ParticleManagerTestFixture() {
if (manager->isInitialized()) {
manager->clean();
}
}
ParticleManager* manager;
};Best Practices:
- Always clean up: Use RAII pattern in test fixtures
- Multiple update cycles: Weather and effect tests need multiple
update()calls - Timing considerations: Performance tests should account for system variations
- Resource cleanup: Add delays between resource-intensive tests
Located in tests/core/, these tests validate the fantasy calendar and time simulation:
-
GameTime Core Tests (
GameTimeTest.cpp):- Time advancement and tick system
- Configuration and initialization
- Time scale modifications
-
Calendar Tests (
GameTimeCalendarTest.cpp):- Fantasy month system (Bloomtide, Sunpeak, Harvestmoon, Frosthold)
- Day advancement (30 days per month)
- Year cycle transitions
-
Season Tests (
GameTimeSeasonTest.cpp):- Season transitions (Spring→Summer→Fall→Winter)
- Weather probability changes per season
- Event dispatching on season change
# Linux/macOS
./tests/test_scripts/run_game_time_tests.sh [--verbose]
# Windows
tests/test_scripts/run_game_time_tests.bat [--verbose]Located in tests/controllers/, these tests validate the state-scoped controller pattern. Tests use a template-based infrastructure (tests/controllers/common/) that provides reusable test suites for common ControllerBase behaviors, reducing duplication across controller test files.
-
ControllerRegistry Tests (
ControllerRegistryTests.cpp):- Type-safe controller registration and retrieval
- Batch operations (subscribeAll, unsubscribeAll, suspendAll, resumeAll, updateAll)
- Lifecycle management (clear, move semantics)
- Empty registry edge cases
-
WeatherController Tests (
WeatherControllerTests.cpp):- Weather event coordination and state transitions
- All weather types (Clear, Cloudy, Rainy, Stormy, Foggy, Snowy, Windy)
- Weather descriptions and event filtering
-
DayNightController Tests (
DayNightControllerTests.cpp):- Time period tracking (Morning/Day/Evening/Night)
- Hour-to-period mapping and transitions
- Visual state management and descriptions
The tests/controllers/common/ directory provides reusable test templates:
ControllerTestFixture.hpp: Base fixture with EventManager/GameTimeManager setupControllerOwnershipTests.hpp: Instantiation, move semantics, RAII destructionControllerSubscriptionTests.hpp: Subscribe/unsubscribe lifecycleControllerSuspendResumeTests.hpp: Suspend/resume behaviorControllerGetNameTests.hpp: getName validation
# Linux/macOS
./tests/test_scripts/run_controller_tests.sh # Run all controller tests
./tests/test_scripts/run_controller_tests.sh --registry # ControllerRegistry tests only
./tests/test_scripts/run_controller_tests.sh --weather # WeatherController tests only
./tests/test_scripts/run_controller_tests.sh --daynight # DayNightController tests only
./tests/test_scripts/run_controller_tests.sh --verbose # Verbose output
# Windows
tests/test_scripts/run_controller_tests.bat # Run all controller tests
tests/test_scripts/run_controller_tests.bat --registry # ControllerRegistry tests only
tests/test_scripts/run_controller_tests.bat --weather # WeatherController tests only
tests/test_scripts/run_controller_tests.bat --daynight # DayNightController tests only
tests/test_scripts/run_controller_tests.bat --verbose # Verbose outputLocated in tests/EntityStateManagerTests.cpp, these tests validate the EntityStateManager class that manages entity state machines:
-
Basic State Management (5 tests):
- AddState: Verify state added and retrievable
- AddMultipleStates: Multiple state registration
- AddDuplicateStateThrows: Duplicate name throws exception
- HasStateReturnsFalseForNonExistent: Non-existing state checks
- GetCurrentStateNameEmptyWhenNoState: Empty state handling
-
State Transitions (4 tests):
- SetStateCallsEnter: Setting state triggers enter() callback
- SetStateTransitionCallsExitThenEnter: Proper exit/enter sequence
- SetSameStateTriggersCycle: Re-entering same state triggers cycle
- SetNonExistentStateResetsCurrentState: Invalid state handling
-
Update Propagation (4 tests):
- UpdateCallsCurrentStateUpdate: update() propagates to state
- UpdatePassesDeltaTimeCorrectly: DeltaTime passed accurately
- UpdateWithNoCurrentStateIsNoOp: Safe with no current state
- UpdateOnlyAffectsCurrentState: Only active state updated
-
Remove State (3 tests):
- RemoveState: Basic state removal
- RemoveCurrentStateResetsIt: Removing current state resets it
- RemoveNonExistentStateIsNoOp: Safe removal of non-existing state
-
Edge Cases (2 tests):
- EmptyManagerIsValid: Empty manager operations safe
- MultipleTransitions: Complex transition sequences
# Linux/macOS
./tests/test_scripts/run_entity_state_manager_tests.sh [--verbose]
./tests/test_scripts/run_entity_state_manager_tests.sh --basic-test # Basic state management only
./tests/test_scripts/run_entity_state_manager_tests.sh --transition-test # State transitions only
./tests/test_scripts/run_entity_state_manager_tests.sh --update-test # Update propagation only
# Windows
tests/test_scripts/run_entity_state_manager_tests.bat [--verbose]
tests/test_scripts/run_entity_state_manager_tests.bat --basic-test
tests/test_scripts/run_entity_state_manager_tests.bat --transition-test
tests/test_scripts/run_entity_state_manager_tests.bat --update-testEstimated Runtime: ~1 second (18 tests)
Located in tests/managers/, these tests validate the Data-Oriented Design (DoD) entity management system:
-
EntityDataManager Tests (
EntityDataManagerTests.cpp) - 65 test cases:Singleton & Lifecycle (6 tests):
- Singleton pattern validation
- Init/clean lifecycle
- State transition handling
- Double init prevention
Entity Creation (10 tests):
- NPC, Player, DroppedItem, Projectile, AreaEffect, StaticBody creation
- Handle validity after creation
- Entity kind assignment
- Initial tier placement
Handle Validation (8 tests):
- Valid/invalid handle detection
- Stale handle detection after destruction
- Generation increment verification
- Index extraction from handles
Data Access (12 tests):
- Transform data access (position, velocity, rotation)
- HotData access (flags, kind, tier)
- Type-specific data (CharacterData, ItemData, ProjectileData, AreaEffectData)
- Static vs dynamic entity separation
Destruction Queue (8 tests):
- Entity destruction queuing
- Batch destruction processing
- Slot reuse after destruction
- Generation increment on reuse
Simulation Tier System (12 tests):
- Tier assignment (Active, Background, Hibernated)
- Distance-based tier updates
- Active/Background index retrieval
- Tier transitions based on reference point
Queries & Lookups (9 tests):
- Radius-based entity queries
- Entity count by kind/tier
- EntityId lookup
- Handle-to-index mapping
-
BackgroundSimulationManager Tests (
BackgroundSimulationManagerTests.cpp) - 32 test cases:Singleton & Lifecycle (6 tests):
- Singleton pattern validation
- Init/clean lifecycle (including state reset)
- Dependency verification (requires EntityDataManager)
- State transition preparation
Pause/Resume (5 tests):
- Global pause stops all processing
- Resume continues processing
- No frame counter updates when paused
- No tier calculations when paused
Reference Point (5 tests):
- Reference point setting
- Movement threshold (32-unit) triggering tier recalc
- Initial reference point always sets dirty flag
Tier Management (6 tests):
- Tier update interval (120 frames)
- Manual tier invalidation
- hasWork() reflects background entity presence
- Tier update delegates to EntityDataManager
Configuration (5 tests):
- Active/Background radius configuration
- Update rate configuration
- Screen-size based configuration
- Default values validation
Update Processing (3 tests):
- Accumulator pattern (10Hz updates)
- Background entity processing
- Performance statistics tracking
Performance Stats (2 tests):
- Stats collection and retrieval
- Stats reset functionality
# Linux/macOS
./tests/test_scripts/run_entity_data_manager_tests.sh # Run all tests
./tests/test_scripts/run_entity_data_manager_tests.sh --edm # EntityDataManager tests only
./tests/test_scripts/run_entity_data_manager_tests.sh --bgsm # BackgroundSimulationManager tests only
./tests/test_scripts/run_entity_data_manager_tests.sh --verbose # Verbose output
# Windows
tests/test_scripts/run_entity_data_manager_tests.bat # Run all tests
tests/test_scripts/run_entity_data_manager_tests.bat --edm # EntityDataManager tests only
tests/test_scripts/run_entity_data_manager_tests.bat --bgsm # BackgroundSimulationManager tests only
tests/test_scripts/run_entity_data_manager_tests.bat --verbose # Verbose outputEstimated Runtime: ~2-3 seconds (97 tests total)
Located in tests/managers/ and tests/collisions/, these tests validate manager-specific integration with the EntityDataManager:
File: tests/managers/AIManagerEDMIntegrationTests.cpp (~400 lines, 12 test cases)
Test Coverage:
-
Sparse Behavior Vector Tests (4 tests):
- Behavior assignment creates EDM index mapping
- Sparse vector handles gaps correctly
- Behavior unassignment clears sparse behavior
- Behavior reassignment updates sparse behavior
-
Batch Processing EDM Tests (2 tests):
- Batch processing writes to EDM transform
- Multiple entities processed via batch
-
State Transition Tests (3 tests):
- prepareForStateTransition clears AI data
- State transition while batch processing
- AIManager reinit after state transition
-
EDM Index Caching Tests (2 tests):
- EDM index cached on behavior assignment
- Entity destruction doesn't affect other entities
-
Behavior Cloning Tests (1 test):
- Each entity gets separate behavior instance
File: tests/collisions/CollisionManagerEDMIntegrationTests.cpp (~480 lines, 17 test cases)
Test Coverage:
-
Active Tier Filtering Tests (3 tests):
- Only Active tier entities participate in collision
- Entities with collision disabled not in active list
- Background tier entities not in collision
-
Static vs Dynamic Separation Tests (3 tests):
- Static body added to storage (not EDM)
- Dynamic entity in EDM not in static storage
- Static bodies always checked for collision
-
Position Reading Tests (2 tests):
- Collision uses EDM position
- AABB computed from EDM half-size
-
Index Semantics Tests (2 tests):
- Movable-movable pair indices are EDM indices
- Movable-static pair uses mixed indices
-
State Transition Tests (2 tests):
- prepareForStateTransition clears dynamic data
- Static bodies preserved after dynamic clear
-
Layer Filtering Tests (2 tests):
- Collision layers read from EDM
- Trigger flag read from EDM
# Linux/macOS
./tests/test_scripts/run_ai_manager_edm_integration_tests.sh [--verbose]
./tests/test_scripts/run_collision_manager_edm_integration_tests.sh [--verbose]
# Windows
tests/test_scripts/run_ai_manager_edm_integration_tests.bat [--verbose]
tests/test_scripts/run_collision_manager_edm_integration_tests.bat [--verbose]Estimated Runtime: ~1-2 seconds per test suite
Explicit Radii for Deterministic Testing: Tests use explicit radii rather than screen-size calculations for deterministic results:
bgsm->setActiveRadius(500.0f);
bgsm->setBackgroundRadius(1000.0f);
// Entity at 750 units → Background tier
// Entity at 100 units → Active tierSingleton Lifecycle in Test Fixtures:
class EntityDataManagerTestFixture {
public:
EntityDataManagerTestFixture() {
edm = &EntityDataManager::Instance();
edm->init();
}
~EntityDataManagerTestFixture() {
edm->clean();
}
protected:
EntityDataManager* edm;
};Handle Validation Pattern:
auto handle = edm->createNPC(Vector2D(100, 100), 32, 32);
BOOST_CHECK(edm->isValidHandle(handle));
edm->destroyEntity(handle);
edm->processDestructionQueue();
BOOST_CHECK(!edm->isValidHandle(handle)); // Now stale- Choose the appropriate test file for your component
- Add test cases using the
BOOST_AUTO_TEST_CASEmacro - Follow the existing pattern for setup, execution, and verification
- Run tests with
--cleanto ensure your changes are compiled - For directory or file operation tests, always clean up created resources when tests complete
- For tests requiring game engine dependencies, consider creating mock implementations
When testing components that depend on complex systems (like NPCSpawnEvent depending on NPC and GameEngine):
- Create Mock Headers: Define mock classes that implement the same interface as real dependencies
- Mock Implementation: Provide minimal functionality needed for testing
- Test-Specific Compilation: Create test-specific source files that use mocks instead of real implementations
- CMake Integration: Update
tests/CMakeLists.txtto include mock files and dependencies
Example Mock Structure:
// MockNPC.hpp - Mock implementation of NPC for testing
class MockNPC : public Entity {
public:
MockNPC(const std::string& textureID, const Vector2D& position, int width, int height);
// Mock the required interface methods
void setWanderArea(float x1, float y1, float x2, float y2);
void setBoundsCheckEnabled(bool enabled);
// Factory method like real class
static std::shared_ptr<MockNPC> create(const std::string& textureID, const Vector2D& position, int width, int height);
};
// Define alias for testing
using NPC = MockNPC;Benefits of Mocking:
- Tests run faster without full game engine initialization
- Tests are more focused and isolated
- Easier to reproduce specific conditions
- No external dependencies like graphics, audio, or file systems
- Better test reliability and maintainability
For directory management tests (like in SaveManagerTests):
- Use a dedicated test directory that's different from production directories
- Implement proper cleanup in test class destructors or at the end of test cases
- Add detailed logging to identify filesystem operation failures
- Test both successful cases and error cases (e.g., permission denied, disk full)
// Define module name
#define BOOST_TEST_MODULE YourTestName
#include <boost/test/included/unit_test.hpp>
// For thread-safe tests, disable signal handling
#define BOOST_TEST_NO_SIGNAL_HANDLING
// Global fixture for setup/teardown
struct TestFixture {
TestFixture() {
// Setup code
}
~TestFixture() {
// Cleanup code
}
};
BOOST_GLOBAL_FIXTURE(TestFixture);
// Test cases
BOOST_AUTO_TEST_CASE(TestSomething) {
// Test code
BOOST_CHECK(condition); // Continues test if failed
BOOST_REQUIRE(condition); // Stops test if failed
}When working with singleton factories (like ResourceFactory) in tests, follow these important guidelines:
- Test Isolation: Use
clear()methods in test fixtures to ensure test isolation - Production Safety: NEVER call factory
clear()methods from production code or other singleton destructors - Static Object Destruction: Let static factories clean themselves up at program exit
Safe Test Pattern:
class ResourceFactoryTestFixture {
public:
ResourceFactoryTestFixture() {
ResourceFactory::initialize(); // Safe in tests
}
~ResourceFactoryTestFixture() {
ResourceFactory::clear(); // Safe in tests for isolation
}
};Unsafe Production Pattern (DO NOT DO):
// WRONG: Don't call factory clear() from other singletons
void SomeManager::clean() {
ResourceFactory::clear(); // ❌ Can cause crashes due to undefined destruction order
}Why This Matters:
- Static object destruction order is undefined between translation units
- Calling
clear()from other destructors can cause double-free or use-after-free errors - Test crashes like "Abort trap: 6" often indicate this anti-pattern
For thread-safety tests, follow these guidelines:
-
Test Initialization Order
- Initialize ThreadSystem first, then other systems
- Enable threading only after initialization is complete
- Configure task priorities during initialization if needed
-
Test Cleanup Order
- Disable threading before cleanup
- Wait for threads to complete with appropriate timeouts
- Clean up managers before cleaning up ThreadSystem
-
Preventing Deadlocks and Race Conditions
- Use atomic operations with proper synchronization
- Add sleep between operations to allow threads to complete
- Use timeouts when waiting for futures instead of blocking calls
- Use
compare_exchange_stronginstead of simpleexchangefor atomics - Be careful about task priority assignments to avoid priority inversion
-
Boost Test Options
- Add
#define BOOST_TEST_NO_SIGNAL_HANDLINGbefore including Boost.Test - Use
--catch_system_errors=no --no_result_code --detect_memory_leak=0test options
- Add
Problem: Errors related to Boost.Test initialization or missing symbols.
Solution:
- Add
#define BOOST_TEST_MODULE YourModuleNamebefore including Boost.Test - Use
#include <boost/test/included/unit_test.hpp>for header-only approach - Check CMakeLists.txt has correct Boost linking
- Use correct test macros (
BOOST_AUTO_TEST_CASE,BOOST_CHECK, etc.)
Problem: Tests crash with signal 11 (segmentation fault) during cleanup.
Solution:
- Add
#define BOOST_TEST_NO_SIGNAL_HANDLINGbefore including Boost.Test - Run with
--catch_system_errors=no --no_result_code --detect_memory_leak=0 - Disable threading before cleanup:
AIManager::Instance().enableThreading(false) - Add sleep between operations:
std::this_thread::sleep_for(std::chrono::milliseconds(100)) - Use timeout for futures:
future.wait_for(std::chrono::seconds(1)) - Don't register SIGSEGV handler in test code
Problem: Directory creation, file operations, or save/load functions fail during tests.
Solution:
- Check working directory: Tests might run from a different directory than expected
- Print and verify absolute paths:
std::filesystem::absolute(path).string() - Ensure parent directories exist before creating files
- Verify write permissions on directories with a small test file
- Use detailed logging to identify exactly which operation is failing
- Add proper error handling with try/catch blocks around all filesystem operations
- Always clean up test files/directories in both success and failure scenarios
- On Windows, ensure paths don't exceed MAX_PATH (260 characters)
Problem: Tests won't build or can't find dependencies.
Solution:
- Run with
--cleanto ensure clean rebuilding - Check that all required libraries are installed and linked in CMakeLists.txt
- Check proper include paths are set in CMakeLists.txt
The tests/test_scripts/run_all_tests scripts provide a convenient way to run all test suites sequentially:
./tests/test_scripts/run_all_tests.sh [options]tests/test_scripts/run_all_tests.bat [options]
These scripts:
- Run each test script one by one, giving them time to complete
- Pass along the
--verboseoption to individual test scripts if specified - Generate a summary showing which tests passed or failed
- Save combined results to
test_results/combined/all_tests_results.txt - Return a non-zero exit code if any tests fail
Tests are configured in tests/CMakeLists.txt with the following structure:
- Define test executables with source files
- Set compiler definitions for Boost.Test
- Link necessary libraries
- Register tests with CTest
For thread-safe tests, ensure BOOST_TEST_NO_SIGNAL_HANDLING is defined.
Located in tests/gpu/, these tests validate the SDL3 GPU rendering subsystem. Tests are organized into three categories based on GPU requirements.
GPUTypesTests.cpp - Vertex and UBO layout validation:
- SpriteVertex size (20 bytes) and member offsets
- ColorVertex size (12 bytes) and member offsets
- ViewProjectionUBO layout (64 bytes)
- CompositeUBO std140 alignment (32 bytes)
- Trivially copyable and standard layout verification
GPUPipelineConfigTests.cpp - Pipeline configuration creation:
- PipelineConfig default values
- PipelineType enum values
- Sprite config factory (opaque/alpha)
- Particle config factory (additive blending)
- Primitive and composite config factories
GPUDeviceTests.cpp - GPU device lifecycle:
- Singleton pattern validation
- Init/shutdown with valid window
- Double init/shutdown safety
- Shader format queries
- Swapchain format queries
- Driver name retrieval
- Format support queries
GPUShaderManagerTests.cpp - Shader loading and caching:
- Load all 6 shaders (sprite, color, composite × vert/frag)
- Shader caching and retrieval
- SPIR-V and Metal path verification
- Nonexistent shader handling
GPUResourceTests.cpp - Buffer, texture, sampler wrappers:
- GPUBuffer creation (vertex, index)
- GPUTexture creation (sampler, render target, combined)
- GPUTransferBuffer map/unmap operations
- GPUSampler factory methods (nearest, linear, mipmapped)
- Move semantics for all resource types
GPUVertexPoolTests.cpp - Triple-buffered vertex pool:
- Initialization with SpriteVertex/ColorVertex sizes
- Custom capacity configuration
- beginFrame/endFrame cycle
- Frame index advancement
- No GPU stall verification
SpriteBatchTests.cpp - Sprite batch recording:
- begin/draw/drawUV/end workflow
- Vertex count tracking
- Color tint application
- Capacity and hasSprites flag
- Vertex position and UV verification
GPURendererTests.cpp - Complete rendering pipeline:
- Singleton and lifecycle management
- Frame cycle (beginFrame, beginScenePass, beginSwapchainPass, endFrame)
- Pipeline accessor validation (7 pipelines)
- Vertex pool accessor validation (5 pools)
- Sampler and scene texture validation
- Composite params and day/night params
- Viewport management
- Orthographic matrix creation
# Run all GPU tests (requires GPU)
./tests/test_scripts/run_gpu_tests.sh
# Run only unit tests (no GPU required, works in CI)
./tests/test_scripts/run_gpu_tests.sh --unit-only
# Run only integration tests
./tests/test_scripts/run_gpu_tests.sh --integration-only
# Run only system tests
./tests/test_scripts/run_gpu_tests.sh --system-only
# Skip GPU-requiring tests (for headless CI)
./tests/test_scripts/run_gpu_tests.sh --skip-gpu
# Verbose output
./tests/test_scripts/run_gpu_tests.sh --verbose
# Run via CTest with GPU label
ctest -L GPU --output-on-failure
# Run unit tests only via CTest
ctest -L "GPU;Unit" --output-on-failureGPU tests are only built when USE_SDL3_GPU=ON:
cmake -B build/ -G Ninja -DCMAKE_BUILD_TYPE=Debug -DUSE_SDL3_GPU=ON && ninja -C buildGPU tests use a common fixture that handles GPU availability detection:
struct GPUTestFixture {
GPUTestFixture() {
// Initialize SDL and detect GPU availability
}
static bool isGPUAvailable();
static SDL_Window* getTestWindow();
};
// Use SKIP_IF_NO_GPU() macro for graceful skip in CI
BOOST_FIXTURE_TEST_CASE(TestName, GPUTestFixture) {
SKIP_IF_NO_GPU();
// Test code that requires GPU
}- Unit tests: ~20 test cases
- Integration tests: ~45 test cases
- System tests: ~25 test cases
- Total: ~90 test cases across 8 test executables
For specific testing scenarios and troubleshooting, refer to these additional documents:
BEHAVIOR_TESTING.md- Specific guidance for AI thread testing scenariosTROUBLESHOOTING.md- Common issues and their solutions across all components