"""Unit tests for physics state dataclasses and engine stub.""" import pytest from py_dvt_ate.simulation.physics.engine import PhysicsEngine from py_dvt_ate.simulation.physics.state import ElectricalState, ThermalState class TestThermalState: """Tests for the ThermalState dataclass.""" def test_creation(self) -> None: """Test ThermalState can be created with valid values.""" state = ThermalState( chamber_temperature=25.0, case_temperature=30.0, junction_temperature=35.0, timestamp=0.0, ) assert state.chamber_temperature == 25.0 assert state.case_temperature == 30.0 assert state.junction_temperature == 35.0 assert state.timestamp == 0.0 def test_immutability(self) -> None: """Test ThermalState is immutable (frozen dataclass).""" state = ThermalState( chamber_temperature=25.0, case_temperature=30.0, junction_temperature=35.0, timestamp=0.0, ) with pytest.raises(AttributeError): state.chamber_temperature = 50.0 # type: ignore[misc] def test_equality(self) -> None: """Test ThermalState equality comparison.""" state1 = ThermalState( chamber_temperature=25.0, case_temperature=30.0, junction_temperature=35.0, timestamp=0.0, ) state2 = ThermalState( chamber_temperature=25.0, case_temperature=30.0, junction_temperature=35.0, timestamp=0.0, ) assert state1 == state2 def test_hashable(self) -> None: """Test ThermalState is hashable (for use in sets/dicts).""" state = ThermalState( chamber_temperature=25.0, case_temperature=30.0, junction_temperature=35.0, timestamp=0.0, ) # Should not raise hash(state) _ = {state} # Can be added to a set class TestElectricalState: """Tests for the ElectricalState dataclass.""" def test_creation(self) -> None: """Test ElectricalState can be created with valid values.""" state = ElectricalState( input_voltage=5.0, output_voltage=3.3, load_current=0.1, quiescent_current=50e-6, power_dissipation=0.17, ) assert state.input_voltage == 5.0 assert state.output_voltage == 3.3 assert state.load_current == 0.1 assert state.quiescent_current == 50e-6 assert state.power_dissipation == 0.17 def test_immutability(self) -> None: """Test ElectricalState is immutable (frozen dataclass).""" state = ElectricalState( input_voltage=5.0, output_voltage=3.3, load_current=0.1, quiescent_current=50e-6, power_dissipation=0.17, ) with pytest.raises(AttributeError): state.output_voltage = 1.8 # type: ignore[misc] def test_equality(self) -> None: """Test ElectricalState equality comparison.""" state1 = ElectricalState( input_voltage=5.0, output_voltage=3.3, load_current=0.1, quiescent_current=50e-6, power_dissipation=0.17, ) state2 = ElectricalState( input_voltage=5.0, output_voltage=3.3, load_current=0.1, quiescent_current=50e-6, power_dissipation=0.17, ) assert state1 == state2 class TestPhysicsEngineStub: """Tests for the PhysicsEngine stub.""" def test_creation_default(self) -> None: """Test PhysicsEngine can be created with defaults.""" engine = PhysicsEngine() assert engine.dt == pytest.approx(0.01) # 100Hz -> 10ms def test_creation_custom_rate(self) -> None: """Test PhysicsEngine with custom update rate.""" engine = PhysicsEngine(update_rate_hz=50.0) assert engine.dt == pytest.approx(0.02) # 50Hz -> 20ms def test_step_advances_time(self) -> None: """Test step() advances simulation time.""" engine = PhysicsEngine(update_rate_hz=100.0) assert engine.simulation_time == pytest.approx(0.0) engine.step() assert engine.simulation_time == pytest.approx(0.01) engine.step() assert engine.simulation_time == pytest.approx(0.02) def test_get_thermal_state(self) -> None: """Test get_thermal_state returns ThermalState.""" engine = PhysicsEngine() state = engine.get_thermal_state() assert isinstance(state, ThermalState) assert state.chamber_temperature == 25.0 # Default assert state.timestamp == 0.0 def test_get_electrical_state(self) -> None: """Test get_electrical_state returns ElectricalState.""" engine = PhysicsEngine() state = engine.get_electrical_state() assert isinstance(state, ElectricalState) def test_set_chamber_setpoint(self) -> None: """Test set_chamber_setpoint updates setpoint.""" engine = PhysicsEngine() engine.set_chamber_setpoint(85.0) # Stub doesn't update chamber temp, just stores setpoint state = engine.get_thermal_state() assert state.chamber_temperature == 25.0 # Still at initial def test_set_input_voltage(self) -> None: """Test set_input_voltage updates voltage.""" engine = PhysicsEngine() engine.set_input_voltage(5.0) state = engine.get_electrical_state() assert state.input_voltage == 5.0 def test_set_load_current(self) -> None: """Test set_load_current updates current.""" engine = PhysicsEngine() engine.set_output_enabled(True) engine.set_load_current(0.1) state = engine.get_electrical_state() assert state.load_current == 0.1 def test_output_disabled_by_default(self) -> None: """Test output is disabled by default.""" engine = PhysicsEngine() assert not engine.is_output_enabled def test_enable_output(self) -> None: """Test set_output_enabled enables output.""" engine = PhysicsEngine() engine.set_output_enabled(True) assert engine.is_output_enabled def test_load_current_zero_when_disabled(self) -> None: """Test load current is zero when output disabled.""" engine = PhysicsEngine() engine.set_load_current(0.1) state = engine.get_electrical_state() assert state.load_current == 0.0 # Disabled, so zero