diff --git a/src/ska_tango_base/base/base_device.py b/src/ska_tango_base/base/base_device.py index cd8b719c85cef5abfed3b173d450640e5c8776e5..9e3d71f1052cfc83235b07dab7e161848d928572 100644 --- a/src/ska_tango_base/base/base_device.py +++ b/src/ska_tango_base/base/base_device.py @@ -36,7 +36,7 @@ import debugpy import ska_ser_logging from ska_tango_base import release from ska_tango_base.base import AdminModeModel, OpStateModel, BaseComponentManager -from ska_tango_base.base.task_queue_manager import QueueManager +from ska_tango_base.base.task_queue_manager import QueueManager, QueueTask from ska_tango_base.commands import ( BaseCommand, CompletionCommand, @@ -1230,10 +1230,16 @@ class SKABaseDevice(Device): information purpose only. :rtype: (ResultCode, str) """ - self.target.reset() - message = "Reset command completed OK" - self.logger.info(message) - return (ResultCode.OK, message) + + class ResetTask(QueueTask): + def do(self): + self.args[0].reset() + message = "Reset command completed OK" + self.logger.info(message) + return (ResultCode.OK, message) + + unique_id = self.target.enqueue(ResetTask(self.target, logger=self.logger)) + return ResultCode.OK, unique_id def is_Reset_allowed(self): """ @@ -1297,10 +1303,18 @@ class SKABaseDevice(Device): information purpose only. :rtype: (ResultCode, str) """ - self.target.standby() - message = "Standby command completed OK" - self.logger.info(message) - return (ResultCode.OK, message) + + class StandByTask(QueueTask): + def do(self): + self.args[0].standby() + message = "Standby command completed OK" + self.logger.info(message) + return (ResultCode.OK, message) + + unique_id = self.target.enqueue( + StandByTask(self.target, logger=self.logger) + ) + return ResultCode.OK, unique_id def is_Standby_allowed(self): """ @@ -1365,10 +1379,16 @@ class SKABaseDevice(Device): information purpose only. :rtype: (ResultCode, str) """ - self.target.off() - message = "Off command completed OK" - self.logger.info(message) - return (ResultCode.OK, message) + + class OffTask(QueueTask): + def do(self): + self.args[0].off() + message = "Off command completed OK" + self.logger.info(message) + return (ResultCode.OK, message) + + unique_id = self.target.enqueue(OffTask(self.target, logger=self.logger)) + return ResultCode.OK, unique_id def is_Off_allowed(self): """ @@ -1433,10 +1453,16 @@ class SKABaseDevice(Device): information purpose only. :rtype: (ResultCode, str) """ - self.target.on() - message = "On command completed OK" - self.logger.info(message) - return (ResultCode.OK, message) + + class OnTask(QueueTask): + def do(self): + self.args[0].on() + message = "On command completed OK" + self.logger.info(message) + return (ResultCode.OK, message) + + unique_id = self.target.enqueue(OnTask(self.target, logger=self.logger)) + return ResultCode.OK, unique_id def is_On_allowed(self): """ diff --git a/src/ska_tango_base/base/reference_base_device.py b/tests/reference_base_device.py similarity index 94% rename from src/ska_tango_base/base/reference_base_device.py rename to tests/reference_base_device.py index 938b94f4aa8fd4e64f865e82e9cc40c7601ed80c..6f96374789afb48db04adf071dcbb0c9ee7088f0 100644 --- a/src/ska_tango_base/base/reference_base_device.py +++ b/tests/reference_base_device.py @@ -7,8 +7,7 @@ There are two versions used for testing long running commands. - AsyncBaseDevice - Uses the custom QueueManager. Multiple threads, async commands/responses. -It is provided for explanatory purposes, and to support testing of this -package. +It is provided to support testing of the BaseDevice. """ import time from tango.server import command @@ -19,8 +18,10 @@ from ska_tango_base.base.base_device import SKABaseDevice from ska_tango_base.base.task_queue_manager import QueueManager, ResultCode, QueueTask from ska_tango_base.commands import ResponseCommand +from ska_tango_base.subarray import SubarrayObsStateModel -class BaseTestDevice(SKABaseDevice): + +class LongRunningCommandBaseTestDevice(SKABaseDevice): """Implement commands to test queued work.""" def init_command_objects(self): @@ -224,13 +225,13 @@ class BaseTestDevice(SKABaseDevice): return f"{return_code}", f"{message}" -class BlockingBaseDevice(BaseTestDevice): +class BlockingBaseDevice(LongRunningCommandBaseTestDevice): """Test device that has a component manager with the default queue manager that has no workers.""" pass -class AsyncBaseDevice(BaseTestDevice): +class AsyncBaseDevice(LongRunningCommandBaseTestDevice): """Test device that has a component manager with workers.""" def create_component_manager(self: SKABaseDevice): @@ -241,4 +242,7 @@ class AsyncBaseDevice(BaseTestDevice): logger=self.logger, push_change_event=self.push_change_event, ) - return BaseComponentManager(op_state_model=None, queue_manager=queue_manager) + return BaseComponentManager( + op_state_model=SubarrayObsStateModel(self.logger), + queue_manager=queue_manager, + ) diff --git a/tests/test_reference_base_device.py b/tests/test_reference_base_device.py index cb70b48f004fdf10ca6b63163889db102c072914..563d21f44d10450d4d04d4fdbb8a9cb29fc71096 100644 --- a/tests/test_reference_base_device.py +++ b/tests/test_reference_base_device.py @@ -9,15 +9,16 @@ from unittest import mock from tango import EventType from tango.test_context import DeviceTestContext from tango.utils import EventCallback -from ska_tango_base.base.reference_base_device import ( +from .reference_base_device import ( BlockingBaseDevice, AsyncBaseDevice, ) from ska_tango_base.base.task_queue_manager import TaskResult from ska_tango_base.commands import ResultCode +from ska_tango_base.control_model import AdminMode -@pytest.mark.skip("Works as expected when run alone. Segfaults in suite.") +@pytest.mark.forked class TestCommands: """Check that blocking and async commands behave the same way. @@ -29,7 +30,11 @@ class TestCommands: def test_short_command(self): """Test a simple command.""" for class_name in [BlockingBaseDevice, AsyncBaseDevice]: - with DeviceTestContext(class_name, process=True) as proxy: + with DeviceTestContext( + class_name, + process=True, + memorized={"adminMode": str(AdminMode.ONLINE.value)}, + ) as proxy: proxy.Short(1) # Wait for a result, if the task does not abort, we'll time out here while not proxy.longRunningCommandResult: @@ -91,7 +96,7 @@ class TestCommands: ) -@pytest.mark.skip("Works as expected when run alone. Segfaults in suite.") +@pytest.mark.forked def test_callbacks(): """Check that the callback is firing that sends the push change event.""" with mock.patch.object(AsyncBaseDevice, "push_change_event") as my_cb: @@ -155,7 +160,7 @@ def test_callbacks(): tr.task_result == "None" -@pytest.mark.skip("Works as expected when run alone. Segfaults in suite.") +@pytest.mark.forked def test_events(): """Testing the events.