DynamicAbstractionSystem/tests/test_headless_engine.py
Sam 2daf5f7b19
Some checks failed
Build Simulation and Test / Run All Tests (push) Failing after 1m46s
Add unit tests for configuration and core simulation components
2025-11-08 19:45:35 -06:00

218 lines
7.3 KiB
Python

"""Tests for headless simulation engine."""
import time
from unittest.mock import Mock, patch
from engines.headless_engine import HeadlessSimulationEngine, HeadlessConfig
from config.simulation_config import SimulationConfig
class TestHeadlessConfig:
"""Test headless configuration."""
def test_custom_values(self):
"""Test custom configuration values."""
sim_config = SimulationConfig(initial_cells=50, default_tps=120.0)
config = HeadlessConfig(
simulation=sim_config,
max_ticks=10000,
max_duration=300.0,
output_dir="custom_output",
enable_metrics=False,
enable_entities=True,
enable_evolution=False,
metrics_interval=50,
entities_interval=500,
evolution_interval=2000,
output_formats=['json', 'csv'],
real_time=True
)
assert config.simulation == sim_config
assert config.max_ticks == 10000
assert config.max_duration == 300.0
assert config.output_dir == "custom_output"
assert config.enable_metrics == False
assert config.enable_entities == True
assert config.enable_evolution == False
assert config.metrics_interval == 50
assert config.entities_interval == 500
assert config.evolution_interval == 2000
assert config.output_formats == ['json', 'csv']
assert config.real_time == True
class TestHeadlessSimulationEngine:
"""Test headless simulation engine."""
def test_initialization(self):
"""Test engine initialization."""
sim_config = SimulationConfig(initial_cells=5, initial_food=10)
config = HeadlessConfig(
simulation=sim_config,
max_ticks=1000,
output_formats=['json']
)
engine = HeadlessSimulationEngine(config)
assert engine.config == config
assert engine.event_bus is not None
assert engine.simulation_core is not None
assert engine.file_writer is not None
assert engine.formatters is not None
assert engine.collectors is not None
assert engine.running == False
assert engine.start_time is None
def test_collectors_creation(self):
"""Test collectors are created based on configuration."""
sim_config = SimulationConfig()
config = HeadlessConfig(
simulation=sim_config,
enable_metrics=True,
enable_entities=True,
enable_evolution=False,
metrics_interval=50,
entities_interval=200
)
engine = HeadlessSimulationEngine(config)
assert 'metrics' in engine.collectors
assert 'entities' in engine.collectors
assert 'evolution' not in engine.collectors
assert engine.collectors['metrics'].collection_interval == 50
assert engine.collectors['entities'].collection_interval == 200
def test_formatters_creation(self):
"""Test formatters are created based on configuration."""
sim_config = SimulationConfig()
config = HeadlessConfig(
simulation=sim_config,
output_formats=['json', 'csv']
)
engine = HeadlessSimulationEngine(config)
assert 'json' in engine.formatters
assert 'csv' in engine.formatters
def test_should_terminate_max_ticks(self):
"""Test termination condition for max ticks."""
sim_config = SimulationConfig()
config = HeadlessConfig(simulation=sim_config, max_ticks=100)
engine = HeadlessSimulationEngine(config)
engine.running = True
engine.start_time = time.time()
# Mock the simulation core to report tick count
engine.simulation_core.state.total_ticks = 99
assert engine._should_terminate() == False
engine.simulation_core.state.total_ticks = 100
assert engine._should_terminate() == True
def test_should_terminate_max_duration(self):
"""Test termination condition for max duration."""
sim_config = SimulationConfig()
config = HeadlessConfig(simulation=sim_config, max_duration=1.0)
engine = HeadlessSimulationEngine(config)
engine.running = True
engine.start_time = time.time()
# Should not terminate immediately
assert engine._should_terminate() == False
# Mock time passage
with patch('time.time', return_value=engine.start_time + 1.5):
assert engine._should_terminate() == True
def test_should_terminate_no_limits(self):
"""Test no termination conditions."""
sim_config = SimulationConfig()
config = HeadlessConfig(simulation=sim_config)
engine = HeadlessSimulationEngine(config)
engine.running = True
engine.start_time = time.time()
# Should never terminate without limits
assert engine._should_terminate() == False
def test_collect_data(self):
"""Test data collection from collectors."""
sim_config = SimulationConfig()
config = HeadlessConfig(
simulation=sim_config,
enable_metrics=True,
enable_entities=False,
enable_evolution=False
)
engine = HeadlessSimulationEngine(config)
# Mock simulation core's get_world_state method
engine.simulation_core.get_world_state = Mock(return_value={
'tick_count': 1000,
'actual_tps': 60.0,
'entity_counts': {'total': 25}
})
# Mock collector
mock_collector = Mock()
mock_collector.update.return_value = [
{'tick_count': 1000, 'actual_tps': 60.0, 'collection_type': 'metrics'}
]
engine.collectors['metrics'] = mock_collector
engine._collect_data()
# Verify collector was called
mock_collector.update.assert_called_once()
# Verify data was collected
assert len(engine.batch_data['metrics']) == 1
assert engine.batch_data['metrics'][0]['tick_count'] == 1000
def test_get_real_time_status(self):
"""Test real-time status reporting."""
sim_config = SimulationConfig()
config = HeadlessConfig(simulation=sim_config)
engine = HeadlessSimulationEngine(config)
engine.running = True
engine.start_time = time.time() - 5.0
# Mock simulation state
engine.simulation_core.state.total_ticks = 300
engine.simulation_core.state.actual_tps = 60.0
engine.simulation_core.get_world_state = Mock(return_value={
'tick_count': 300,
'actual_tps': 60.0,
'entity_counts': {'total': 50}
})
status = engine.get_real_time_status()
assert status['running'] == True
assert status['ticks'] == 300
assert status['tps'] == 60.0
assert status['duration'] > 4.0 # Approximately 5 seconds
assert status['world_state']['tick_count'] == 300
def test_signal_handler(self):
"""Test signal handling for graceful shutdown."""
sim_config = SimulationConfig()
config = HeadlessConfig(simulation=sim_config)
engine = HeadlessSimulationEngine(config)
engine.running = True
# Simulate signal handler
engine._signal_handler(2, None) # SIGINT
assert engine.running == False