"""Tests for ``arautopilot.core.alarms``.""" from __future__ import annotations import pytest from arautopilot.core.alarms import ( Alarm, AlarmSeverity, AlarmType, default_message, default_severity, triggers_auto_disengage, ) def test_catalogue_covers_every_alarm_type() -> None: """The internal catalogue must define metadata for every enum member.""" for at in AlarmType: # Calling any of the helpers must succeed for every type. sev = default_severity(at) msg = default_message(at) flag = triggers_auto_disengage(at) assert isinstance(sev, AlarmSeverity) assert isinstance(msg, str) and msg assert isinstance(flag, bool) @pytest.mark.parametrize( "alarm_type", [ AlarmType.OFF_COURSE_SEVERE, AlarmType.RUDDER_NOT_RESPONDING, AlarmType.HEADING_SENSOR_LOST, AlarmType.WATCHDOG_TRIPPED, AlarmType.VMS_CRITICAL, AlarmType.ACTUATOR_OVERCURRENT, AlarmType.VOLTAGE_LOW, ], ) def test_safety_critical_alarms_trigger_auto_disengage(alarm_type: AlarmType) -> None: """All EMERGENCY alarms (and HIGH overcurrent/voltage) must auto-disengage.""" assert triggers_auto_disengage(alarm_type) is True @pytest.mark.parametrize( "alarm_type", [AlarmType.OFF_COURSE, AlarmType.LIMIT_SWITCH_REACHED], ) def test_warning_alarms_do_not_disengage(alarm_type: AlarmType) -> None: assert triggers_auto_disengage(alarm_type) is False def test_alarm_from_type_uses_catalogue_defaults() -> None: a = Alarm.from_type(AlarmType.OFF_COURSE_SEVERE) assert a.type is AlarmType.OFF_COURSE_SEVERE assert a.severity is AlarmSeverity.EMERGENCY assert a.auto_disengage_triggered is True assert a.message # non-empty assert a.source == "firmware" assert a.acknowledged is False def test_alarm_is_frozen() -> None: a = Alarm.from_type(AlarmType.OFF_COURSE) with pytest.raises((TypeError, ValueError)): a.acknowledged = True # type: ignore[misc] def test_alarm_rejects_unknown_field() -> None: with pytest.raises(ValueError): Alarm( type=AlarmType.OFF_COURSE, severity=AlarmSeverity.LOW, message="hi", foo="bar", # type: ignore[call-arg] ) def test_alarm_message_length_limits() -> None: with pytest.raises(ValueError): Alarm(type=AlarmType.OFF_COURSE, severity=AlarmSeverity.LOW, message="") with pytest.raises(ValueError): Alarm( type=AlarmType.OFF_COURSE, severity=AlarmSeverity.LOW, message="x" * 241, )