383 lines
14 KiB
Python
383 lines
14 KiB
Python
"""
|
|
Tests for parameter validation module.
|
|
|
|
Testing validation of all input parameters with boundary conditions,
|
|
invalid types, and edge cases.
|
|
"""
|
|
|
|
import pytest
|
|
import math
|
|
from laser_control.validators import ParameterValidator
|
|
from laser_control.exceptions import (
|
|
ValidationError,
|
|
TemperatureOutOfRangeError,
|
|
CurrentOutOfRangeError,
|
|
InvalidParameterError
|
|
)
|
|
from laser_control.models import VariationType
|
|
|
|
|
|
class TestTemperatureValidation:
|
|
"""Test temperature parameter validation."""
|
|
|
|
def test_valid_temperature_range(self):
|
|
"""Test temperatures within valid range."""
|
|
# Valid temperatures should pass
|
|
assert ParameterValidator.validate_temperature(15.0, "temp1") == 15.0
|
|
assert ParameterValidator.validate_temperature(25.5, "temp2") == 25.5
|
|
assert ParameterValidator.validate_temperature(40.0, "temp1") == 40.0
|
|
|
|
def test_temperature_below_minimum(self):
|
|
"""Test temperature below minimum threshold."""
|
|
with pytest.raises(TemperatureOutOfRangeError) as exc_info:
|
|
ParameterValidator.validate_temperature(10.0, "temp1")
|
|
assert "temp1" in str(exc_info.value)
|
|
assert "15.0" in str(exc_info.value) # min value
|
|
|
|
def test_temperature_above_maximum(self):
|
|
"""Test temperature above maximum threshold."""
|
|
with pytest.raises(TemperatureOutOfRangeError) as exc_info:
|
|
ParameterValidator.validate_temperature(45.0, "temp2")
|
|
assert "temp2" in str(exc_info.value)
|
|
assert "40.0" in str(exc_info.value) # max value
|
|
|
|
def test_temperature_invalid_type(self):
|
|
"""Test invalid temperature type."""
|
|
with pytest.raises(InvalidParameterError) as exc_info:
|
|
ParameterValidator.validate_temperature("invalid", "temp1")
|
|
assert "temp1" in str(exc_info.value)
|
|
assert "number" in str(exc_info.value).lower()
|
|
|
|
def test_temperature_nan_value(self):
|
|
"""Test NaN temperature value."""
|
|
with pytest.raises(InvalidParameterError) as exc_info:
|
|
ParameterValidator.validate_temperature(float('nan'), "temp1")
|
|
assert "NaN" in str(exc_info.value)
|
|
|
|
def test_temperature_inf_value(self):
|
|
"""Test infinite temperature value."""
|
|
with pytest.raises(InvalidParameterError) as exc_info:
|
|
ParameterValidator.validate_temperature(float('inf'), "temp2")
|
|
assert "infinite" in str(exc_info.value).lower()
|
|
|
|
def test_temperature_none_value(self):
|
|
"""Test None temperature value."""
|
|
with pytest.raises(InvalidParameterError) as exc_info:
|
|
ParameterValidator.validate_temperature(None, "temp1")
|
|
assert "temp1" in str(exc_info.value)
|
|
|
|
|
|
class TestCurrentValidation:
|
|
"""Test current parameter validation."""
|
|
|
|
def test_valid_current_range(self):
|
|
"""Test currents within valid range."""
|
|
assert ParameterValidator.validate_current(15.0, "current1") == 15.0
|
|
assert ParameterValidator.validate_current(37.5, "current2") == 37.5
|
|
assert ParameterValidator.validate_current(60.0, "current1") == 60.0
|
|
|
|
def test_current_below_minimum(self):
|
|
"""Test current below minimum threshold."""
|
|
with pytest.raises(CurrentOutOfRangeError) as exc_info:
|
|
ParameterValidator.validate_current(10.0, "current1")
|
|
assert "current1" in str(exc_info.value)
|
|
assert "15.0" in str(exc_info.value) # min value
|
|
|
|
def test_current_above_maximum(self):
|
|
"""Test current above maximum threshold."""
|
|
with pytest.raises(CurrentOutOfRangeError) as exc_info:
|
|
ParameterValidator.validate_current(65.0, "current2")
|
|
assert "current2" in str(exc_info.value)
|
|
assert "60.0" in str(exc_info.value) # max value
|
|
|
|
def test_current_invalid_type(self):
|
|
"""Test invalid current type."""
|
|
with pytest.raises(InvalidParameterError) as exc_info:
|
|
ParameterValidator.validate_current([15, 20], "current1")
|
|
assert "current1" in str(exc_info.value)
|
|
|
|
def test_current_negative_value(self):
|
|
"""Test negative current value."""
|
|
with pytest.raises(CurrentOutOfRangeError) as exc_info:
|
|
ParameterValidator.validate_current(-5.0, "current1")
|
|
assert "current1" in str(exc_info.value)
|
|
|
|
|
|
class TestVariationParameterValidation:
|
|
"""Test variation mode parameter validation."""
|
|
|
|
def test_valid_current_variation_params(self):
|
|
"""Test valid parameters for current variation."""
|
|
params = {
|
|
'min_value': 20.0,
|
|
'max_value': 50.0,
|
|
'step': 0.5,
|
|
'time_step': 50, # microseconds
|
|
'delay_time': 5 # milliseconds
|
|
}
|
|
validated = ParameterValidator.validate_variation_params(
|
|
params,
|
|
VariationType.CHANGE_CURRENT_LD1
|
|
)
|
|
assert validated['min_value'] == 20.0
|
|
assert validated['max_value'] == 50.0
|
|
assert validated['step'] == 0.5
|
|
|
|
def test_variation_min_greater_than_max(self):
|
|
"""Test min value greater than max value."""
|
|
params = {
|
|
'min_value': 50.0,
|
|
'max_value': 20.0,
|
|
'step': 0.5,
|
|
'time_step': 50,
|
|
'delay_time': 5
|
|
}
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_variation_params(
|
|
params,
|
|
VariationType.CHANGE_CURRENT_LD1
|
|
)
|
|
assert "min" in str(exc_info.value).lower()
|
|
assert "max" in str(exc_info.value).lower()
|
|
|
|
def test_variation_invalid_step(self):
|
|
"""Test invalid step values."""
|
|
# Zero step
|
|
params = {
|
|
'min_value': 20.0,
|
|
'max_value': 50.0,
|
|
'step': 0,
|
|
'time_step': 50,
|
|
'delay_time': 5
|
|
}
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_variation_params(
|
|
params,
|
|
VariationType.CHANGE_CURRENT_LD1
|
|
)
|
|
assert "step" in str(exc_info.value).lower()
|
|
|
|
# Negative step
|
|
params['step'] = -0.5
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_variation_params(
|
|
params,
|
|
VariationType.CHANGE_CURRENT_LD1
|
|
)
|
|
assert "step" in str(exc_info.value).lower()
|
|
|
|
def test_variation_step_too_small(self):
|
|
"""Test step value too small for current."""
|
|
params = {
|
|
'min_value': 20.0,
|
|
'max_value': 50.0,
|
|
'step': 0.001, # Too small for current (min 0.002)
|
|
'time_step': 50,
|
|
'delay_time': 5
|
|
}
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_variation_params(
|
|
params,
|
|
VariationType.CHANGE_CURRENT_LD2
|
|
)
|
|
assert "step" in str(exc_info.value).lower()
|
|
assert "0.002" in str(exc_info.value)
|
|
|
|
def test_variation_step_too_large(self):
|
|
"""Test step value too large."""
|
|
params = {
|
|
'min_value': 20.0,
|
|
'max_value': 50.0,
|
|
'step': 10.0, # Too large for current (max 0.5)
|
|
'time_step': 50,
|
|
'delay_time': 5
|
|
}
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_variation_params(
|
|
params,
|
|
VariationType.CHANGE_CURRENT_LD1
|
|
)
|
|
assert "step" in str(exc_info.value).lower()
|
|
assert "0.5" in str(exc_info.value)
|
|
|
|
def test_valid_temperature_variation_params(self):
|
|
"""Test valid parameters for temperature variation."""
|
|
params = {
|
|
'min_value': 20.0,
|
|
'max_value': 35.0,
|
|
'step': 0.1,
|
|
'time_step': 50,
|
|
'delay_time': 5
|
|
}
|
|
validated = ParameterValidator.validate_variation_params(
|
|
params,
|
|
VariationType.CHANGE_TEMPERATURE_LD1
|
|
)
|
|
assert validated['min_value'] == 20.0
|
|
assert validated['max_value'] == 35.0
|
|
assert validated['step'] == 0.1
|
|
|
|
def test_temperature_variation_step_bounds(self):
|
|
"""Test temperature variation step boundaries."""
|
|
params = {
|
|
'min_value': 20.0,
|
|
'max_value': 35.0,
|
|
'step': 0.02, # Too small (min 0.05)
|
|
'time_step': 50,
|
|
'delay_time': 5
|
|
}
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_variation_params(
|
|
params,
|
|
VariationType.CHANGE_TEMPERATURE_LD2
|
|
)
|
|
assert "0.05" in str(exc_info.value)
|
|
|
|
params['step'] = 2.0 # Too large (max 1.0)
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_variation_params(
|
|
params,
|
|
VariationType.CHANGE_TEMPERATURE_LD1
|
|
)
|
|
assert "1.0" in str(exc_info.value)
|
|
|
|
def test_missing_required_params(self):
|
|
"""Test missing required parameters."""
|
|
params = {
|
|
'min_value': 20.0,
|
|
'max_value': 50.0
|
|
# Missing step, time_step, delay_time
|
|
}
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_variation_params(
|
|
params,
|
|
VariationType.CHANGE_CURRENT_LD1
|
|
)
|
|
assert "required" in str(exc_info.value).lower()
|
|
|
|
def test_invalid_variation_type(self):
|
|
"""Test invalid variation type."""
|
|
params = {
|
|
'min_value': 20.0,
|
|
'max_value': 50.0,
|
|
'step': 0.5,
|
|
'time_step': 50,
|
|
'delay_time': 5
|
|
}
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_variation_params(
|
|
params,
|
|
"INVALID_TYPE"
|
|
)
|
|
assert "variation type" in str(exc_info.value).lower()
|
|
|
|
|
|
class TestTimeParameterValidation:
|
|
"""Test time parameter validation."""
|
|
|
|
def test_valid_time_params(self):
|
|
"""Test valid time parameters."""
|
|
step_time, delay_time = ParameterValidator.validate_time_params(50, 5)
|
|
assert step_time == 50
|
|
assert delay_time == 5
|
|
|
|
step_time, delay_time = ParameterValidator.validate_time_params(20, 3)
|
|
assert step_time == 20
|
|
assert delay_time == 3
|
|
|
|
step_time, delay_time = ParameterValidator.validate_time_params(100, 10)
|
|
assert step_time == 100
|
|
assert delay_time == 10
|
|
|
|
def test_time_step_below_minimum(self):
|
|
"""Test time step below minimum."""
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_time_params(10, 5) # Min is 20
|
|
assert "time step" in str(exc_info.value).lower()
|
|
assert "20" in str(exc_info.value)
|
|
|
|
def test_time_step_above_maximum(self):
|
|
"""Test time step above maximum."""
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_time_params(150, 5) # Max is 100
|
|
assert "time step" in str(exc_info.value).lower()
|
|
assert "100" in str(exc_info.value)
|
|
|
|
def test_delay_time_below_minimum(self):
|
|
"""Test delay time below minimum."""
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_time_params(50, 1) # Min is 3
|
|
assert "delay" in str(exc_info.value).lower()
|
|
assert "3" in str(exc_info.value)
|
|
|
|
def test_delay_time_above_maximum(self):
|
|
"""Test delay time above maximum."""
|
|
with pytest.raises(ValidationError) as exc_info:
|
|
ParameterValidator.validate_time_params(50, 15) # Max is 10
|
|
assert "delay" in str(exc_info.value).lower()
|
|
assert "10" in str(exc_info.value)
|
|
|
|
def test_time_params_invalid_type(self):
|
|
"""Test invalid type for time parameters."""
|
|
with pytest.raises(InvalidParameterError):
|
|
ParameterValidator.validate_time_params("50", 5)
|
|
|
|
with pytest.raises(InvalidParameterError):
|
|
ParameterValidator.validate_time_params(50, [5])
|
|
|
|
def test_time_params_float_conversion(self):
|
|
"""Test float to int conversion for time parameters."""
|
|
step_time, delay_time = ParameterValidator.validate_time_params(50.7, 5.2)
|
|
assert step_time == 50 # Should be truncated to int
|
|
assert delay_time == 5
|
|
|
|
|
|
class TestManualModeValidation:
|
|
"""Test manual mode parameter validation."""
|
|
|
|
def test_validate_all_manual_params(self):
|
|
"""Test validation of all manual mode parameters at once."""
|
|
result = ParameterValidator.validate_manual_mode_params(
|
|
temp1=25.0,
|
|
temp2=30.0,
|
|
current1=40.0,
|
|
current2=35.0
|
|
)
|
|
assert result['temp1'] == 25.0
|
|
assert result['temp2'] == 30.0
|
|
assert result['current1'] == 40.0
|
|
assert result['current2'] == 35.0
|
|
|
|
def test_manual_mode_invalid_combination(self):
|
|
"""Test invalid parameter combinations in manual mode."""
|
|
# One invalid parameter should fail all validation
|
|
with pytest.raises(ValidationError):
|
|
ParameterValidator.validate_manual_mode_params(
|
|
temp1=25.0,
|
|
temp2=30.0,
|
|
current1=70.0, # Too high
|
|
current2=35.0
|
|
)
|
|
|
|
def test_manual_mode_boundary_values(self):
|
|
"""Test boundary values for manual mode."""
|
|
# All minimum values
|
|
result = ParameterValidator.validate_manual_mode_params(
|
|
temp1=15.0,
|
|
temp2=15.0,
|
|
current1=15.0,
|
|
current2=15.0
|
|
)
|
|
assert all(v in [15.0] for v in result.values())
|
|
|
|
# All maximum values
|
|
result = ParameterValidator.validate_manual_mode_params(
|
|
temp1=40.0,
|
|
temp2=40.0,
|
|
current1=60.0,
|
|
current2=60.0
|
|
)
|
|
assert result['temp1'] == 40.0
|
|
assert result['temp2'] == 40.0
|
|
assert result['current1'] == 60.0
|
|
assert result['current2'] == 60.0 |