From dd3d57d60f7741741d3a58b9d3e58d8b4bd2ed30 Mon Sep 17 00:00:00 2001
From: toor <elisabetta.giani@inaf.it>
Date: Mon, 15 Feb 2021 11:40:31 +0100
Subject: [PATCH] CT-215: Re-initialization process is able to handle the
 CSP.LMC subarray in scanning state. Running threads are stopped when subarray
 device is deleted (delete_device method invoked).

---
 csp-lmc-common/csp_lmc_common/CspSubarray.py  | 117 +++++++++++-------
 csp-lmc-mid/csp_lmc_mid/MidCspSubarrayBase.py |   1 -
 .../tests/integration/MidCspSubarray_test.py  |  93 ++++++++------
 .../tests/unit/midcspsubarray_unit_test.py    |   1 -
 4 files changed, 133 insertions(+), 79 deletions(-)

diff --git a/csp-lmc-common/csp_lmc_common/CspSubarray.py b/csp-lmc-common/csp_lmc_common/CspSubarray.py
index 9af0951..cbb6cb3 100644
--- a/csp-lmc-common/csp_lmc_common/CspSubarray.py
+++ b/csp-lmc-common/csp_lmc_common/CspSubarray.py
@@ -95,10 +95,12 @@ class CspSubarrayStateModel(SKASubarrayStateModel):
         self._action_breakdown["force_to_empty"] = ("force_to_empty", None)
         self._action_breakdown["force_to_ready"] = ("force_to_ready", None)
         self._action_breakdown["force_to_aborted"] = ("force_to_aborted", None)
+        self._action_breakdown["force_to_scanning"] = ("force_to_scanning", None)
         # add transtions to the ObservationStateMachine
         self._observation_state_machine.add_transition(trigger='force_to_empty', source='*', dest='EMPTY')
         self._observation_state_machine.add_transition(trigger='force_to_idle', source='*', dest='IDLE')
         self._observation_state_machine.add_transition(trigger='force_to_ready', source='*', dest='READY')
+        self._observation_state_machine.add_transition(trigger='force_to_scanning', source='*', dest='SCANNING')
         self._observation_state_machine.add_transition(trigger='force_to_aborted', source='*', dest='ABORTED')
 
 class CspSubarray(SKASubarray):
@@ -311,6 +313,7 @@ class CspSubarray(SKASubarray):
             # keys: the command name('on, 'off'...)
             # values: thread instance
             device._command_thread = {}
+            device._stop_thread = defaultdict(lambda: False)
             
             # _end_scan_event: thread event to signal EndScan
             device._end_scan_event = threading.Event()
@@ -416,15 +419,6 @@ class CspSubarray(SKASubarray):
             return (ResultCode.STARTED, "CSP Subarray Init STARTED")
 
         def initialize_thread(self):
-            allowed_coupled = {
-                  'RESOURCING': 'IDLE',
-                  'RESOURCING': 'EMPTY',
-                  'CONFIGURING': 'READY',
-                  'SCANNING': 'READY',
-                  'ABORTING': 'ABORTED',
-                  'RESETTING': 'IDLE',
-                  'RESTARTING': 'EMPTY'
-                   }
             try:
                 with EnsureOmniThread():
                     self.logger.info("Init thread started")
@@ -433,7 +427,6 @@ class CspSubarray(SKASubarray):
                     device.force_cmd_obj = device.ForceObsStateTransitionCommand(*args)
                     on_handler = device.OnCommand(*args)
 
-                    timeout = 10 # seconds
                     # Try connection with the CBF sub-array
                     device.connect_to_subarray_subcomponent(device.CbfSubarray)
                     # TODO: add connection to CSPMaster to get information
@@ -443,27 +436,42 @@ class CspSubarray(SKASubarray):
                     # put the device to OFF/EMPTY: no transition is allowed from INIT state
                     self.succeeded()
                     if device._sc_subarray_state[device.CbfSubarray] is not DevState.ON:
-                        self.logger.info('devo leggerlo se sono alla prima inizializzazione')
                         return
                     # put the device to ON/EMPTY
-                    self.logger.info('Non devo leggerlo se sono alla prima inizializzazione')  
                     on_handler.succeeded()
 
                     # CASE B: CSP is ON
+                    target_obs_state = device.obs_state_evaluator()
+                    if target_obs_state in ['RESOURCING', 'ABORTING', 'CONFIGURING', 'RESETTING','RESTARTING']:
+                        self.logger.info("Still to implement transitional state different from SCANNINNG")
+                        return
+                        #self.monitor_running_command(target_obs_state)
                     self.logger.info('CSP is already ON. Aligning to Sub-elements...')
-                    # start a loop in case of transitional states (CASE 2)
-                    timeout = 10
-                    starting_time = time.time()
-                    target_obs_state = 'FAULT'
-                    while time.time() - starting_time < timeout:
-                        target_obs_state = device.obs_state_evaluator()
-                        if target_obs_state in allowed_coupled.values() or (target_obs_state == 'FAULT'):
-                            break;
-                        time.sleep(0.1)
                     device.set_csp_obs_state(target_obs_state)
+                    if target_obs_state == 'SCANNING':
+                        return self.monitor_running_command(target_obs_state)
             except Exception as msg:
                 self.logger.info(f'error in thread: {msg}')
 
+        def monitor_running_command(self, csp_obs_state):
+            """
+            Helper method to monitor the CSP Subarray observing state at re-initialization if
+            the observing state is in a transitional state.
+            NOTE: Currently onlt the SCANNING obsState is handled.
+
+            :param csp_obs_state: the CSP.LMC Subarray observing state.
+            :type csp_obs_state: string
+            """
+            device = self.target
+            if csp_obs_state == 'SCANNING':
+                handler = device.ScanCommand(*args)
+                device._command_thread['scan'] = threading.Thread(target=handler.monitor_scan_execution,
+                                                   name="Thread-Scan",
+                                                   args=(device._sc_subarray_fqdn,))
+                device._cmd_execution_state['scan'] = CmdExecState.RUNNING
+                self.logger.info("Start scan thread")
+                device._command_thread['scan'].start()
+
     def obs_state_evaluator(self):
         """
         Helper method to evaluate the CSP Subarray observing state starting from the 
@@ -475,7 +483,8 @@ class CspSubarray(SKASubarray):
                   A component not ONLINE/MAINTENANCE does not contribute to the observing 
                   state value.
         
-        :return: The observing state string
+        :return: The observing state.
+        :rtype: string with the observing state name.
         """
         target_obs_state = 'FAULT'
         obs_states_list = []
@@ -653,6 +662,7 @@ class CspSubarray(SKASubarray):
            
             # the dictionary with the scan configuration
 
+            self.logger.info("ConfigureCommand at {}".format(time.time()))
             target_device = self.target
             try:
                 # if the stored configuration attribute is not empty, check
@@ -805,9 +815,10 @@ class CspSubarray(SKASubarray):
             device_done = defaultdict(lambda:False)
             # inside the end-less lop check the obsState of each sub-component
             device_list = input_arg[0]
+            self.logger.info("Trhead started at {}".format(time.time()))
             while True:
                 if target_device._abort_obs_event.is_set():
-                    self.logger.info("Received and ABORT request during configuration")
+                    self.logger.info("Received and ABORT request during configuration {}".format(time.time()))
                 command_progress = 0
                 for device in device_list:
                     self.logger.info("Current device {} obsState is {}".format(device,
@@ -830,8 +841,9 @@ class CspSubarray(SKASubarray):
                                               target_device._reconfiguring))
                     if target_device._sc_subarray_obs_state[device] == dev_successful_state:
                         if not target_device._reconfiguring:
-                            self.logger.info("Command {} ended with success on device {}.".format(cmd_name,
-                                                                                                      device))
+                            self.logger.info("Command {} ended with success on device {} at {}.".format(cmd_name,
+                                                                                                      device,
+                                                                                                      time.time()))
                             # update the list and number of device that completed the task
                             target_device._num_dev_completed_task[cmd_name]  += 1
                             target_device._list_dev_completed_task[cmd_name].append(device)
@@ -876,7 +888,7 @@ class CspSubarray(SKASubarray):
                     self.logger.info("device {} is in {}: reconfiguring is:{}".format(device, ObsState(target_device._sc_subarray_obs_state[device]).name,
                                                                                       target_device._reconfiguring))
                 if all(value == True for value in device_done.values()):
-                    self.logger.info("All devices have been handled!")
+                    self.logger.info("All devices have been handled at time {}!".format(time.time()))
                     break
                 # check for global timeout expiration
                 # may be this check is not necessary 
@@ -890,6 +902,7 @@ class CspSubarray(SKASubarray):
             # end of the while loop
             # acquire the mutex during the check of configuration success/failure. We don't want
             # to receive an boart during this phase otherwise could happen strange situation
+            self.logger.info("GOING To lock mutex at {}".format(time.time()))
             with target_device._mutex_obs_state:
                 # check for timeout/failure conditions on each sub-component
                 if any(target_device._sc_subarray_cmd_exec_state[device][cmd_name] == CmdExecState.TIMEOUT for device in device_list):
@@ -906,9 +919,9 @@ class CspSubarray(SKASubarray):
                 if target_device._abort_obs_event.is_set():
                     if target_device._timeout_expired or target_device._failure_raised:
                         return self.failed()
-                    self.logger.info("Abort configure ends with success!!")
+                    self.logger.info("Abort configure ends with success!! {}".format(time.time()))
                     if all(target_device._sc_subarray_obs_state[fqdn] == ObsState.ABORTED for fqdn in device_list):
-                        return  target_device.abort_cmd_obj.succeeded()
+                        return target_device.abort_cmd_obj.succeeded()
                     return target_device.abort_cmd_obj.abort_monitoring(device_list)
 
                 if target_device._timeout_expired or target_device._failure_raised:
@@ -923,7 +936,7 @@ class CspSubarray(SKASubarray):
                     target_device._cmd_duration_measured[cmd_name] = time.time() - command_start_time
                     target_device._cmd_progress[cmd_name] = 100
                     target_device._last_executed_command = cmd_name
-                    self.logger.info("Configure ends with success!!")
+                    self.logger.info("Configure ends with success!! {}".format(time.time()))
                     return self.succeeded()
 
         def validate_scan_configuration(self, argin):
@@ -1001,13 +1014,17 @@ class CspSubarray(SKASubarray):
             target_device._command_thread['scan'] = threading.Thread(target=self.monitor_scan_execution,
                                                                name="Thread-Scan",
                                                                args=(target_device._sc_subarray_assigned_fqdn,))
+            self.logger.info("Thread scan: {}".format(target_device._command_thread['scan']))
             target_device._cmd_execution_state['scan'] = CmdExecState.RUNNING
             target_device._command_thread['scan'].start()
             return (ResultCode.STARTED, "Scan command started") 
 
         def monitor_scan_execution(self, device_list):
+            self.logger.info("Starting scan thread")
             cmd_name = 'scan'
             target_device = self.target
+            target_device._end_scan_event.clear()
+            target_device._abort_obs_event.clear()
             dev_successful_state = ObsState.READY
             target_device._num_dev_completed_task[cmd_name] = 0
             target_device._list_dev_completed_task[cmd_name] = []
@@ -1023,12 +1040,14 @@ class CspSubarray(SKASubarray):
             elapsed_time = 0
             starting_time = time.time()
             stop_scan = False
-            target_device._end_scan_event.clear()
-            target_device._abort_obs_event.clear()
             # inside the end-less loop check the obsState of each sub-component
             while True:
-                self.logger.info("abort:{}".format(target_device._abort_obs_event.is_set()))
-                self.logger.info("end:{}".format(target_device._end_scan_event.is_set()))
+                #self.logger.info("abort:{}".format(target_device._abort_obs_event.is_set()))
+                #self.logger.info("end:{}".format(target_device._end_scan_event.is_set()))
+                if target_device._stop_thread[cmd_name]:
+                    target_device._stop_thread[cmd_name] = False
+                    self.logger.info("STOPPING THE THREAD!!!")
+                    return
                 if target_device._end_scan_event.is_set() or target_device._abort_obs_event.is_set(): 
                     if not stop_scan:
                         stop_scan = True
@@ -1068,7 +1087,6 @@ class CspSubarray(SKASubarray):
         def do(self):
             target_device = self.target
             device_list = target_device._sc_subarray_assigned_fqdn
-            self.logger.info("EndScan assigned_fqdn: {}".format(device_list))
             if not any(target_device._sc_subarray_assigned_fqdn):
                 # need to add a check also on PSTBeams belonging to subarray
                 device_list = target_device._sc_subarray_fqdn
@@ -1087,7 +1105,7 @@ class CspSubarray(SKASubarray):
                         self.logger.error("device {}: {}-{}".format(reply.dev_name(), err.desc, err.reason))
                 else:
                     (result_code,msg) = reply.get_data()
-                    self.logger.error("device {}: {}".format(reply.dev_name(), msg))
+                    self.logger.info("device {}: {}".format(reply.dev_name(), msg))
             if any(target_device._sc_subarray_obs_state[device]== ObsState.FAULT for device in  device_list):
                 return (ResultCode.FAILED, "EndScan Command FAILED")
             return (ResultCode.OK, "EndScan command executed OK")
@@ -1141,6 +1159,10 @@ class CspSubarray(SKASubarray):
             device_done = defaultdict(lambda:False)
             # inside the end-less loop check the obsState of each sub-component
             while True:
+                if target_device._stop_thread[cmd_name]:
+                    target_device._stop_thread[cmd_name] = False
+                    self.logger.info("STOPPING THE THREAD!!!")
+                    return
                 time.sleep(0.1)
                 for device in device_list:
                     if device_done[device] == True:
@@ -1300,6 +1322,10 @@ class CspSubarray(SKASubarray):
             elapsed_time = 0
             starting_time = time.time()
             while True:
+                if target_device._stop_thread[cmd_name]:
+                    target_device._stop_thread[cmd_name] = False
+                    self.logger.info("STOPPING THE THREAD!!!")
+                    return
                 for device in device_list:
                     if device_done[device] == True:
                         continue
@@ -1449,8 +1475,10 @@ class CspSubarray(SKASubarray):
                 self.logger.info(log_msg)
                 # update CSP sub-array SCM
                 #07-2020: with the new base classes, transitions are handled via actions.
-                #if evt.attr_value.name.lower() in ["state", "healthstate", "adminmode", "obsstate"]:
+                #if evt.attr_value.name.lower() in ["obsstate"]:
                 #    self.update_subarray_state()
+                if evt.attr_value.name.lower() in ["healthstate"]:
+                    self._update_subarray_health_state()
             except tango.DevFailed as df:
                 self.logger.error(str(df.args[0].desc))
             except Exception as except_occurred:
@@ -1592,18 +1620,21 @@ class CspSubarray(SKASubarray):
         Class protected method.
         Retrieve the State attribute values of the CSP sub-elements and aggregate
         them to build up the CSP global state.
+        This method should be called only when no command is running.
 
         :param: None
         :return: None
         """
         self.logger.info("update_subarray_state")
         self._update_subarray_health_state()
+        # check if a long-running command is in execution
         for key, thread in self._command_thread.items():
             if thread.is_alive():
                 self.logger.info("Tread {} is running".format(key))
                 return
         target_obs_state = self.obs_state_evaluator()
-        self.set_csp_obs_state(target_obs_state)
+        if target_obs_state != self._obs_state:
+            self.set_csp_obs_state(target_obs_state)
 
     def _update_subarray_health_state(self):
         """
@@ -1855,11 +1886,6 @@ class CspSubarray(SKASubarray):
         args = (self, self.state_model, self.logger)
         self.gotoidle_cmd_obj = self.GoToIdleCommand(*args)
         self.abort_cmd_obj = self.AbortCommand(*args)
-        #self._assignresources_cmd_obj = self.AssignResourcesCommand(*args)
-        #self._releaseresources_cmd_obj = self.ReleaseResourcesCommand(*args)
-        #self.register_command_object("AssignResources", self.AssignResourcesCommand(*args))
-        #self.register_command_object("ReleaseResources", self.ReleaseResourcesCommand(*args))
-        #self.register_command_object("ReleaseAllResources", self.ReleaseAllResourcesCommand(*args))
         self.register_command_object("GoToIdle", self.GoToIdleCommand(*args))
         self.register_command_object("Configure", self.ConfigureCommand(*args))
         self.register_command_object("Scan", self.ScanCommand(*args))
@@ -2319,6 +2345,12 @@ class CspSubarray(SKASubarray):
         """
         # PROTECTED REGION ID(CspSubarray.delete_device) ENABLED START #
         #release the allocated event resources
+        # check for running threads and stop them
+        for key, thread in self._command_thread.items():
+            is_alive = thread.is_alive()
+            if is_alive:
+                self._stop_thread[key] = True
+                thread.join()
         event_to_remove = {}
         for fqdn in self._sc_subarray_fqdn:
             try:
@@ -2842,6 +2874,7 @@ class CspSubarray(SKASubarray):
 
         :return:'DevVarLongStringArray'
         """
+        self.logger.info("CALL ABORT at time {}".format(time.time()))
         with self._mutex_obs_state:
             handler = self.get_command_object("Abort")
             (result_code, message) = handler()
diff --git a/csp-lmc-mid/csp_lmc_mid/MidCspSubarrayBase.py b/csp-lmc-mid/csp_lmc_mid/MidCspSubarrayBase.py
index 4ee1fd2..097c969 100644
--- a/csp-lmc-mid/csp_lmc_mid/MidCspSubarrayBase.py
+++ b/csp-lmc-mid/csp_lmc_mid/MidCspSubarrayBase.py
@@ -519,7 +519,6 @@ class MidCspSubarrayBase(CspSubarray):
         self.logger.info("Going to assign receptors {}".format(receptors_to_be_added))
 
         while True:
-            self.logger.info("device {} obs_state:{}".format(device, self._sc_subarray_obs_state[device]))
             if self._sc_subarray_obs_state[device] == ObsState.IDLE:
                 self.logger.info("Reconfiguring is:{}".format(self._reconfiguring))
                 assigned_receptors = self._receptors.assigned_to_subarray(self.SubID)
diff --git a/csp-lmc-mid/tests/integration/MidCspSubarray_test.py b/csp-lmc-mid/tests/integration/MidCspSubarray_test.py
index 56a56b3..ace4b2d 100755
--- a/csp-lmc-mid/tests/integration/MidCspSubarray_test.py
+++ b/csp-lmc-mid/tests/integration/MidCspSubarray_test.py
@@ -16,7 +16,6 @@ import time
 import random
 import numpy as np
 import logging
-import unittest
 import pytest
 import json
 
@@ -45,7 +44,7 @@ def prepare_configuration_string(filename="test_ConfigureScan_ADR4.json"):
 
 # Device test case
 @pytest.mark.usefixtures("midcsp_master", "midcsp_subarray01", "cbf_subarray01")
-class TestBase(unittest.TestCase):
+class TestBase(object):
     fixture_names = ()
 
     @pytest.fixture(autouse=True)
@@ -93,7 +92,8 @@ class TestCspSubarray(TestBase):
             obs_state = self.midcsp_subarray01.obsState
             if obs_state == ObsState.IDLE:
                 self._release_all_receptors()
-
+                prober_obs_state = Probe(self.midcsp_subarray01, "obsState", ObsState.EMPTY, f"CSP Subarray not EMPTY")
+                Poller(4, 0.2).check(prober_obs_state)
     def _setup_subarray_off(self):
         """
         Set the subarray state to OFF-EMPTY
@@ -193,8 +193,9 @@ class TestCspSubarray(TestBase):
     @pytest.mark.init_IDLE
     def test_re_initialization_when_IDLE(self):
         """
-        Test for re-initialization of mid-csp device after killing the Tango device. 
-        The CspSubarray align to the state/obsstate of CBFSubarray: ON/IDLE
+        Test for re-initialization of mid-csp device after a restart of
+        the Tango device. 
+        The CspSubarray aligns to the state/obsstate of CBFSubarray: ON/IDLE
         """
         self._setup_subarray()
         json_config= self._build_resources([1,2])
@@ -212,8 +213,9 @@ class TestCspSubarray(TestBase):
     @pytest.mark.init_READY
     def test_re_initialization_when_READY(self):
         """
-        Test for re-initialization of mid-csp device after killing the Tango device. 
-        The CspSubarray align to the state/obsstate of CBFSubarray: ON/IDLE
+        Test for re-initialization of mid-csp device after the restart of
+        the Tango device. 
+        The CspSubarray aligns to the state/obsstate of CBFSubarray: ON/READY
         """
         self._setup_subarray()
         self._configure_scan() 
@@ -226,29 +228,43 @@ class TestCspSubarray(TestBase):
         Poller(4, 0.2).check(prober_subarray_obsstate)
     
     @pytest.mark.init_SCANNING
-    def test_re_initialization_when_SCANNING(self):
+    @pytest.mark.parametrize("elapsed_time", [0.1, 0.2, 0.3, 0.4, 0.5,1,2])
+    def test_re_initialization_when_SCANNING(self, elapsed_time):
         """
-        Test for re-initialization of mid-csp device after killing the Tango device.
-        The CspSubarray align to the state/obsstate of CBFSubarray: ON/IDLE
+        Test for re-initialization of mid-csp device after the of the
+        Tango device.
+        The CspSubarray aligns to the state/obsstate of CBFSubarray: ON/SCANNING.
+        The tests ends with the CSP Subarray in READY.
+        Test is executed several times with different wait time (dealys) before
+        sending the EndScan.
         """
         self._setup_subarray()
         self._configure_scan()
         self.midcsp_subarray01.Scan('2')
         prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.SCANNING, f'CSP Subarray not SCANNING')
         Poller(10, 0.2).check(prober_subarray_obsstate)
+        # wait for a variable time
+        time.sleep(elapsed_time)
         # open a proxy to the adminstrative server
         dserver_proxy = tango.DeviceProxy(self.midcsp_subarray01.adm_name())
+        # restart the device to force a reinitialization
         dserver_proxy. devrestart('mid_csp/elt/subarray_01')
         prober_subarray_state = Probe(self.midcsp_subarray01, "State", DevState.ON, f"CSP Subarray not ON after re-initialization")
         Poller(10, 0.2).check(prober_subarray_state)
         prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.SCANNING, f"CSP Subarray not SCANNING after re-initialization")
         Poller(4, 0.2).check(prober_subarray_obsstate)
+        # wait a variable time before sending the endscan
+        time.sleep(elapsed_time)
+        self.midcsp_subarray01.EndScan()
+        prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.READY, f'CSP Subarray not SCANNING')
+        Poller(5, 0.2).check(prober_subarray_obsstate)
     
-    @pytest.mark.init_ARBORTED
+    @pytest.mark.init_ABORTED
     def test_re_initialization_when_ABORTED(self):
         """
-        Test for re-initialization of mid-csp device after killing the Tango device.
-        The CspSubarray align to the state/obsstate of CBFSubarray: ON/IDLE
+        Test for re-initialization of mid-csp device after the restart of the
+        Tango device.
+        The CspSubarray align to the state/obsstate of CBFSubarray: ON/ABORTED
         """
         self._setup_subarray()
         self._assign_receptors()
@@ -270,8 +286,10 @@ class TestCspSubarray(TestBase):
         """
         self._setup_subarray()
         self._assign_receptors()
-        self.midcsp_subarray01.Configure('{"input":"failed"}')
+        configuration_string = prepare_configuration_string("test_ConfigureScan_invalid_cbf_json.json")
+        self.midcsp_subarray01.Configure(configuration_string)
         prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.FAULT, f'CSP Subarray not FAULT')
+        Poller(10, 0.2).check(prober_subarray_obsstate)
         # open a proxy to the adminstrative server
         dserver_proxy = tango.DeviceProxy(self.midcsp_subarray01.adm_name())
         dserver_proxy. devrestart('mid_csp/elt/subarray_01')
@@ -280,8 +298,7 @@ class TestCspSubarray(TestBase):
         prober_subarray_obsstate = Probe(self.midcsp_subarray01, "obsState", ObsState.FAULT, f"CSP Subarray not FAULT after re-initialization")
         Poller(4, 0.2).check(prober_subarray_obsstate)
     
-    def test_subarray_state_AFTER_on_command_iexecution(self):
-
+    def test_subarray_state_AFTER_on_command_execution(self):
         """
         Test for State after CSP startup.
         The CspSubarray State at start is OFF.
@@ -300,7 +317,15 @@ class TestCspSubarray(TestBase):
         Test that the Off command send the device in OFF-EMPTY
         if it is ON-RESOURCING
         """
-        self._setup_subarray
+        self._setup_subarray()
+        subarray_state = self.midcsp_subarray01.State()
+        obs_state = self.midcsp_subarray01.obsState
+        LOGGER.info("CSPSubarray state before test:{}-{}".format(subarray_state, obs_state))
+        json_config= self._build_resources([1,2])
+        self.midcsp_subarray01.AssignResources(json_config)
+        subarray_state = self.midcsp_subarray01.State()
+        obs_state = self.midcsp_subarray01.obsState
+        LOGGER.info("CSPSubarray state before test:{}-{}".format(subarray_state, obs_state))
         self.midcsp_subarray01.Off()        
         prober_subarray_state = Probe(self.midcsp_subarray01, "State", DevState.OFF, f"CSP Subarray not OFF")
         Poller(4, 0.2).check(prober_subarray_state)
@@ -747,11 +772,15 @@ class TestCspSubarray(TestBase):
         prober_obs_state = Probe(self.midcsp_subarray01, "obsState", ObsState.IDLE, f"CSP Subarray not IDLE")
         Poller(4, 0.2).check(prober_obs_state)
 
-    @pytest.mark.csp_k8s
-    def test_send_abort_WHILE_in_configuring(self):
+    @pytest.mark.abort
+    #@pytest.mark.parametrize("elapsed_time", [0.4, 0.41, 0.42, 0.43, 0.44])
+    @pytest.mark.parametrize("elapsed_time", [0.42, 0.43, 0.44])
+    @pytest.mark.parametrize('execution_number', range(2))
+    def test_send_abort_WHILE_in_configuring(self, elapsed_time, execution_number):
         """
-        Configure the CSP Subarray with a JSon string including
-        the new ADR22 fields.
+        Test that the subarray is able to handle the Abort command when issued 
+        at any time.
+        The test is repeated several times with different delay times.
         """
         self._setup_subarray()
         self._assign_receptors()
@@ -762,7 +791,7 @@ class TestCspSubarray(TestBase):
         LOGGER.info(f"Configuring CSP subarray01")
         configuration_string = prepare_configuration_string()
         (result_code, msg) = self.midcsp_subarray01.Configure(configuration_string)
-        #time.sleep(0.1)
+        time.sleep(elapsed_time)
         self.midcsp_subarray01.Abort()
         # check
         prober_subarray_obstate = Probe(self.midcsp_subarray01, 'obsState', ObsState.ABORTED,
@@ -812,26 +841,20 @@ class TestCspSubarray(TestBase):
         prober_obs_state = Probe(self.midcsp_subarray01, "obsState", ObsState.EMPTY, f"CSP Subarray not EMPTY")
         Poller(4, 0.2).check(prober_obs_state)
 
-    '''
-    def test_configureScan_with_subarray_ready(self, midcsp_subarray01, midcsp_master):
+    def test_configureScan_WHEN_subarray_ready(self, midcsp_subarray01, midcsp_master):
         """
         Test that the Configure() command is issued when the Subarray
         state already READY
         """
+        self._configure_scan()
         obs_state = midcsp_subarray01.obsState
         assert obs_state == ObsState.READY
-        f = open(file_path +"/test_ConfigureScan_basic.json")
-        obs_state = midcsp_subarray01.obsState
-        try:
-            midcsp_subarray01.Configure(f.read().replace("\n", ""))
-        except tango.DevFailed as tango_err:
-            print("configure error:", tango_err.args[0].desc)
-        obs_state = midcsp_subarray01.obsState
-        f.close()
-        time.sleep(5)
-        obs_state = midcsp_subarray01.obsState
-        assert obs_state == ObsState.READY
+        configuration_string = prepare_configuration_string("test_ConfigureScan_basic.json")
+        self.midcsp_subarray01.Configure(configuration_string)
+        prober_obs_state = Probe(self.midcsp_subarray01, "obsState", ObsState.READY, f"CSP Subarray not READY")
+        Poller(4, 0.2).check(prober_obs_state)
 
+'''
     def test_remove_receptors_when_ready(self, midcsp_subarray01):
         """
         Test that the complete deallocation of receptors fails
diff --git a/csp-lmc-mid/tests/unit/midcspsubarray_unit_test.py b/csp-lmc-mid/tests/unit/midcspsubarray_unit_test.py
index 2478b49..d4accef 100644
--- a/csp-lmc-mid/tests/unit/midcspsubarray_unit_test.py
+++ b/csp-lmc-mid/tests/unit/midcspsubarray_unit_test.py
@@ -543,7 +543,6 @@ def test_midcspsubarray_obsstate_AFTER_timeout_during_configuration():
                 'dish': {'receptorIDList': receptor_list}}
             json_config = json.dumps(param)
             tango_context.device.AssignResources(json_config)
-
             #assert tango_context.device.obsState == ObsState.IDLE
             configuration_string = load_json_file("test_ConfigureScan_ADR4.json")
             tango_context.device.Configure(configuration_string)
-- 
GitLab