diff --git a/test/test.py b/test/test_core.py similarity index 79% rename from test/test.py rename to test/test_core.py index c074f9c..c25ecc9 100644 --- a/test/test.py +++ b/test/test_core.py @@ -1,41 +1,50 @@ import pytest import warnings -from nucon import Nucon, NuconConfig, PumpStatus, PumpDryStatus, PumpOverloadStatus, BreakerStatus +from nucon import Nucon, PumpStatus, PumpDryStatus, PumpOverloadStatus, BreakerStatus WARN_FLOAT_COULD_BE_INT = False @pytest.fixture(scope="module") def nucon_setup(): - Nucon.set_dummy_mode(False) # Assume the game is running + Nucon.set_dummy_mode(False) Nucon.set_base_url("http://localhost:8785/") - yield - Nucon.set_dummy_mode(True) def test_read_all_parameters(nucon_setup): all_params = Nucon.get_all() assert len(all_params) == len(Nucon) for param, value in all_params.items(): - assert isinstance(value, param.param_type), f"Parameter {param.name} has incorrect type. Expected {param.param_type}, got {type(value)}" + assert isinstance(value, param.param_type), f"Parameter {param.id} has incorrect type. Expected {param.param_type}, got {type(value)}" if param.param_type == float and value.is_integer() and WARN_FLOAT_COULD_BE_INT: - warnings.warn(f"Parameter {param.name} is a float but has an integer value: {value}") + warnings.warn(f"Parameter {param.id} is a float but has an integer value: {value}") + if param.param_type == str: + try: + float(value) + raise ValueError(f"Parameter {param.id} is a string that looks like a number: {value}") + except ValueError: + pass + try: + bool(value.lower()) + raise ValueError(f"Parameter {param.id} is a string that looks like a boolean: {value}") + except ValueError: + pass def test_write_writable_parameters(nucon_setup): writable_params = Nucon.get_all_writable() for param in writable_params: current_value = param.value param.value = current_value - assert param.value == current_value, f"Failed to write to parameter {param.name}" + assert param.value == current_value, f"Failed to write to parameter {param.id}" def test_non_writable_parameters(nucon_setup): non_writable_params = [param for param in Nucon if not param.is_writable] for param in non_writable_params: # Test that normal set raises an error - with pytest.raises(ValueError, match=f"Parameter {param.name} is not writable"): + with pytest.raises(ValueError, match=f"Parameter {param.id} is not writable"): param.value = param.value # Attempt to write the current value # Test that force_set is refused by the webserver current_value = param.value - with pytest.raises(Exception, match=f"Failed to set parameter {param.name}"): + with pytest.raises(Exception, match=f"Failed to set parameter {param.id}"): Nucon.set(param, current_value, force=True) def test_enum_parameters(nucon_setup): diff --git a/test/test_sim.py b/test/test_sim.py new file mode 100644 index 0000000..6d63962 --- /dev/null +++ b/test/test_sim.py @@ -0,0 +1,114 @@ +import pytest +import time +from nucon import Nucon, PumpStatus, PumpDryStatus, PumpOverloadStatus, BreakerStatus +from nucon.sim import NuconSimulator, OperatingState + +@pytest.fixture(scope="module") +def simulator_setup(): + simulator = NuconSimulator(port=8786) + simulator.run() + time.sleep(1) # Give the simulator time to start + nucon = Nucon(port=8786) + return simulator, nucon + +def test_simulator_initialization(simulator_setup): + simulator, nucon = simulator_setup + assert simulator is not None + assert nucon is not None + +def test_read_all_parameters(simulator_setup): + _, nucon = simulator_setup + all_params = nucon.get_all() + assert len(all_params) == len(nucon) + for param_id, value in all_params.items(): + param = nucon[param_id] + assert isinstance(value, param.param_type), f"Parameter {param.id} has incorrect type. Expected {param.param_type}, got {type(value)}" + +def test_write_writable_parameters(simulator_setup): + _, nucon = simulator_setup + writable_params = nucon.get_all_writable() + for param in writable_params.values(): + current_value = param.value + if param.param_type == float: + new_value = current_value + 1.0 + elif param.param_type == int: + new_value = current_value + 1 + elif param.param_type == bool: + new_value = not current_value + elif issubclass(param.param_type, Enum): + new_value = list(param.param_type)[0] + else: + continue # Skip if we can't determine a new value + + param.value = new_value + assert param.value == new_value, f"Failed to write to parameter {param.id}" + +def test_non_writable_parameters(simulator_setup): + _, nucon = simulator_setup + non_writable_params = [param for param in nucon.get_all_readable().values() if not param.is_writable] + for param in non_writable_params: + with pytest.raises(ValueError, match=f"Parameter {param.id} is not writable"): + param.value = param.value # Attempt to write the current value + +def test_enum_parameters(simulator_setup): + _, nucon = simulator_setup + pump_status = nucon.COOLANT_CORE_CIRCULATION_PUMP_0_STATUS.value + assert isinstance(pump_status, PumpStatus) + + dry_status = nucon.COOLANT_CORE_CIRCULATION_PUMP_0_DRY_STATUS.value + assert isinstance(dry_status, PumpDryStatus) + + overload_status = nucon.COOLANT_CORE_CIRCULATION_PUMP_0_OVERLOAD_STATUS.value + assert isinstance(overload_status, PumpOverloadStatus) + + breaker_status = nucon.GENERATOR_0_BREAKER.value + assert isinstance(breaker_status, BreakerStatus) + +def test_custom_truthy_values(simulator_setup): + _, nucon = simulator_setup + assert bool(nucon.COOLANT_CORE_CIRCULATION_PUMP_0_STATUS.value) == (nucon.COOLANT_CORE_CIRCULATION_PUMP_0_STATUS.value in [PumpStatus.ACTIVE_NO_SPEED_REACHED, PumpStatus.ACTIVE_SPEED_REACHED]) + assert bool(nucon.COOLANT_CORE_CIRCULATION_PUMP_0_DRY_STATUS.value) == (nucon.COOLANT_CORE_CIRCULATION_PUMP_0_DRY_STATUS.value == PumpDryStatus.INACTIVE_OR_ACTIVE_WITH_FLUID) + assert bool(nucon.COOLANT_CORE_CIRCULATION_PUMP_0_OVERLOAD_STATUS.value) == (nucon.COOLANT_CORE_CIRCULATION_PUMP_0_OVERLOAD_STATUS.value == PumpOverloadStatus.INACTIVE_OR_ACTIVE_NO_OVERLOAD) + assert bool(nucon.GENERATOR_0_BREAKER.value) == (nucon.GENERATOR_0_BREAKER.value == BreakerStatus.OPEN) + +def test_get_multiple_parameters(simulator_setup): + _, nucon = simulator_setup + params_to_get = [nucon.CORE_TEMP, nucon.CORE_PRESSURE, nucon.RODS_POS_ACTUAL] + multiple_params = nucon.get_multiple(params_to_get) + assert len(multiple_params) == len(params_to_get) + for param_id, value in multiple_params.items(): + assert isinstance(value, nucon[param_id].param_type) + +def test_simulator_update(simulator_setup): + simulator, nucon = simulator_setup + initial_temp = nucon.CORE_TEMP.value + simulator.update(10) # Update for 10 seconds + new_temp = nucon.CORE_TEMP.value + assert new_temp != initial_temp, "Core temperature should change after update" + +def test_set_operating_state(simulator_setup): + simulator, nucon = simulator_setup + simulator._set_state(OperatingState.NOMINAL) + time.sleep(1) # Give the simulator time to update + assert nucon.CORE_STATE.value == 'NOMINAL' + assert 290 <= nucon.CORE_TEMP.value <= 370 + +def test_allow_all_writes(simulator_setup): + simulator, nucon = simulator_setup + simulator.set_allow_all_writes(True) + non_writable_param = next(param for param in nucon.get_all_readable().values() if not param.is_writable) + current_value = non_writable_param.value + new_value = current_value + 1 if isinstance(current_value, (int, float)) else not current_value + non_writable_param.value = new_value + assert non_writable_param.value == new_value, f"Failed to write to non-writable parameter {non_writable_param.id} when allow_all_writes is True" + +def test_simulator_consistency(simulator_setup): + simulator, nucon = simulator_setup + for _ in range(10): + simulator.update(1) + all_params = nucon.get_all() + for param_id, value in all_params.items(): + assert value == getattr(simulator.parameters, param_id), f"Inconsistency found for parameter {param_id}" + +if __name__ == "__main__": + pytest.main() \ No newline at end of file