diff --git a/.release b/.release index 87b75fde02ff38edc5a39741f2fed429127edd5a..f9f7a81457c881ab187986d0e51db124eecc4caa 100644 --- a/.release +++ b/.release @@ -1,2 +1,2 @@ -release=0.7.0 -tag=lmcbaseclasses-0.7.0 +release=0.7.1 +tag=lmcbaseclasses-0.7.1 diff --git a/README.md b/README.md index 95a0c07f1265a09513214176bcaac2140e163d1b..049ee081a35ba69b95d2d1aea76658b23fb3b104 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,9 @@ The lmc-base-classe repository contains set of eight classes as mentioned in SKA ## Version History +#### 0.7.1 +- Bugfix for Reset() command + #### 0.7.0 - Separate adminMode state machine from opState state machine - Add support for STANDBY opState diff --git a/src/ska/base/base_device.py b/src/ska/base/base_device.py index 2d8b824bad2e3141cd279271bcf8a9a8262668d9..12538e942ec82d2b9a14b30eda285ff6c7279b4b 100644 --- a/src/ska/base/base_device.py +++ b/src/ska/base/base_device.py @@ -1194,6 +1194,31 @@ class SKABaseDevice(Device): """ super().__init__(target, state_model, "reset", logger=logger) + def check_allowed(self): + """ + Checks whether the command is allowed to be run in the current + state of the state model. + + :returns: True if the command is allowed to be run + """ + return self._try_action("reset_succeeded_off") + + def is_allowed(self): + """ + Whether this command is allowed to run in the current state of + the state model. + + :returns: whether this command is allowed to run + :rtype: boolean + """ + return self._is_action_allowed("reset_succeeded_off") + + def succeeded(self): + """ + Action to take on successful completion of a reset + """ + self.state_model.perform_action("reset_succeeded_off") + def do(self): """ Stateless hook for device reset. diff --git a/src/ska/base/release.py b/src/ska/base/release.py index a983abcd3064aead4090cba2d4f7d79cfadaac3a..2c803a690f3776f544c751ba2e7ef1096331e4b7 100644 --- a/src/ska/base/release.py +++ b/src/ska/base/release.py @@ -7,7 +7,7 @@ """Release information for lmc-base-classes Python Package""" name = """lmcbaseclasses""" -version = "0.7.0" +version = "0.7.1" version_info = version.split(".") description = """A set of generic base devices for SKA Telescope.""" author = "SKA India and SARAO and CSIRO" diff --git a/tests/test_base_device.py b/tests/test_base_device.py index 049b61a60d4d5b69b9d27da1e807db9e6f23e4c4..ce6ff3b84797a13e2fd337c5ff213b56e2bd70b0 100644 --- a/tests/test_base_device.py +++ b/tests/test_base_device.py @@ -19,6 +19,8 @@ import tango from unittest import mock from tango import DevFailed, DevState +from ska.base import SKABaseDevice +from ska.base.commands import ResultCode from ska.base.control_model import ( AdminMode, ControlMode, HealthState, LoggingLevel, SimulationMode, TestMode ) @@ -30,7 +32,7 @@ from ska.base.base_device import ( DeviceStateModel, TangoLoggingServiceHandler, ) -from ska.base.faults import StateModelError +from ska.base.faults import CommandError, StateModelError from .conftest import load_state_machine_spec, StateMachineTester @@ -479,9 +481,8 @@ class TestSKABaseDevice(object): def test_Reset(self, tango_context): """Test for Reset""" # PROTECTED REGION ID(SKABaseDevice.test_Reset) ENABLED START # - # This is a pretty weak test, but Reset() is only allowed from - # device state FAULT, and we have no way of putting into FAULT - # state through its interface. + # The main test of this command is + # TestSKABaseDevice_commands::test_ResetCommand with pytest.raises(DevFailed): tango_context.device.Reset() # PROTECTED REGION END # // SKABaseDevice.test_Reset @@ -692,3 +693,47 @@ class TestSKABaseDevice(object): # PROTECTED REGION ID(SKABaseDevice.test_testMode) ENABLED START # assert tango_context.device.testMode == TestMode.NONE # PROTECTED REGION END # // SKABaseDevice.test_testMode + +class TestSKABaseDevice_commands: + """ + This class contains tests of SKASubarray commands + """ + + def test_ResetCommand(self, device_state_model): + """ + Test for SKBaseDevice.ResetCommand + """ + mock_device = mock.Mock() + + reset_command = SKABaseDevice.ResetCommand( + mock_device, + device_state_model + ) + + machine_spec = load_state_machine_spec("device_state_machine") + states = machine_spec["states"] + + transitions = { + "FAULT_MAINTENANCE": "OFF_MAINTENANCE", + "FAULT_ONLINE": "OFF_ONLINE", + } + + for state in states: + device_state_model._straight_to_state(**states[state]) + if state in transitions: + # the reset command is permitted, should succeed. + assert reset_command.is_allowed() + assert reset_command() == ( + ResultCode.OK, + "Reset command completed OK", + ) + expected = transitions[state] + else: + # the reset command is not permitted, should not be allowed, + # should fail, should have no side-effect + assert not reset_command.is_allowed() + with pytest.raises(CommandError): + reset_command() + expected = state + assert device_state_model.admin_mode == states[expected]["admin_mode"] + assert device_state_model.op_state == states[expected]["op_state"]