CSP Test Harness ================ Overview -------- The CSP Test Harness provides a structured environment for validating the Central Signal Processor (CSP) system of the SKA Telescope. It builds upon the work done in the original SKA Tango Harness, adopting and specializing its key design concepts—facades and wrappers—to suit the specific implementation needs of the CSP subsystem. The Harness leverages these abstractions to clearly separate business logic from lower-level device interactions, promoting modularity and reuse. It also integrates core components from the SKA Tango testing framework, such as the Tango Event Tracer and Action classes, which are imported and extended for CSP-specific testing scenarios. The CSP Test Harness is structured around the **System Under Test (SUT)**, encapsulated by the `CSPWrapper`. This Singleton class represents the entire CSP system and holds references to the subsystem wrappers (CSP.LMC, CBF, PST and PSS). .. note:: This documentation describes the purpose, structure, and usage of the CSP Test Harness components, focusing on the `CSPFacade` and the various wrapper classes. CSPFacade --------- The ``CSPFacade`` class provides a high-level interface to interact with the Central Signal Processor (CSP) system in integration tests. It abstracts the low-level Tango device interactions and test boilerplate to enable semantic and structured testing. The `CSPFacade` is the entry point for integration tests involving the CSP and it provides a simplified, business-oriented interface to perform system-level operations, such as assigning PST beams, starting a scan in a subarray, or checking observation states. It supports coordinated operations on all the CSP sub-systems. Core Responsibilities ~~~~~~~~~~~~~~~~~~~~~ - Expose access to CSP wrapper components (``lmc``, ``cbf``, ``pst``, ``pss``). - Provide high-level methods for CSP operations (assign, configure, scan, etc). - Manage Tango event subscriptions and trace Tango events. - Simplify test logic by centralizing command handling, validation, and setup/teardown. Test Isolation and System Cleanup ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A key responsibility of the ``CSPFacade`` is to ensure the system is left in a **well-defined and controlled state** after every test execution. This is achieved through two essential methods: - :py:meth:`.teardown`: attempts a graceful shutdown of the system by resetting all relevant devices to the appropriate `adminmode`, `obsstate`, and power states. - :py:meth:`.hard_reset`: forcibly reinitializes the system in cases where the standard `teardown` fails or when the system enters an undefined or error-prone condition. teardown ^^^^^^^^ Tears down the CSP system after test execution, ensuring it returns to a known and controlled state. This method is crucial for maintaining the reliability and repeatability of integration tests. It systematically: - Ensures all CSP Controller and subarray devices are communicating and in the correct state (`ON`) and `adminmode` (`ONLINE`); - Aborts any active scans and resets subarrays to the `EMPTY` observation state; - Turns off all Low PST beams to bring the system to a clean shutdown condition. By enforcing this teardown procedure, the CSP Test Harness avoids unintended side effects across test runs and ensures consistent test results. Any deviation from the expected device states during this process is logged and surfaced as an error. **Usage Example:** .. code-block:: python csp_facade.teardown() .. note:: The teardown method is designed to be robust against partially configured or failed test states. If any component is not properly set up, corrective actions (e.g., resetting `adminmode`) are attempted before proceeding. hard_reset ^^^^^^^^^^ Resets all devices in the CSP to their initial known states. This method reinitializes all devices in the CSP, including the CBF, PST, and LMC subsystems, and ensures that the CSP controller is set to the *ONLINE* state. It verifies the states of the devices to ensure that they are in a consistent operational condition. This is a crucial step to ensure that the system is returned to a known, clean state before starting a new test or before the system is used again in production. These methods are critical for **test isolation and reproducibility**, ensuring that each test starts from a clean baseline and that cascading failures across tests are avoided. Proper use of these mechanisms is **highly recommended** in all integration scenarios, especially when running suites of tests sequentially. CSP Test Harness' Wrappers -------------------------- Wrappers are internal, technical representations of the SUT. They: - Define the structure of the system (subsystems, devices). - Enable technical operations (e.g., tear-down to base state, version logging). - Abstract device emulation/production status. - Provide configuration interfaces. The following wrappers are introduce for the CSP subsystem: CSP.LMC, CBF, PSS and PST Wrappers. These are set up in the singleton CSP Wrapper. They should be written as generic classes to be specialized for Low and Mid telescope and to be furthermore specialized for Emulators and Production devices. Difference from Facades ~~~~~~~~~~~~~~~~~~~~~~~ As explained in the SKA Integration Test Harness documentation - `Facades` expose high-level, business-oriented operations (used in test scripts). - `Wrappers` expose low-level, technical operations (used internally or by actions). Facades are designed for readability and domain-relevance in test cases, while wrappers expose internals like emulation/production modes, and allow actions to avoid tight coupling. The CSPWrapper ~~~~~~~~~~~~~~ The `CSPWrapper` is the central access point for all the sub-systems within the Central Signal Processor (CSP) of the SKA Telescope. It is inspired by and mirrors the behavior of the `TelescopeWrapper` from the main SKA Integration Test Harness, but is tailored specifically for the CSP. This class is implemented as a **Singleton**, which ensures only one instance exists during a test session. This design avoids inconsistencies that might arise from having multiple instances with differently initialized sub-systems. Purpose ^^^^^^^ The `CSPWrapper` provides a structured and unified interface for accessing all CSP sub-systems within the test environment: - LMC (Local Monitoring and Control) - CBF (Central Beamformer) - PSS (Pulsar Search Subsystem) - PST (Pulsar Timing Subsystem) Each sub-system is encapsulated by its respective wrapper class, which abstracts implementation details, facilitates configuration, and supports automated testing. These wrapper classes are designed to be further specialized for the Low and Mid telescope variants, and additionally tailored for use with either Emulator or Production deployments. .. _cspwrapper-responsibilities: Responsibilities ^^^^^^^^^^^^^^^^ - Ensures a single entry point to all CSP sub-systems. - Provides property-based access to the individual sub-system wrappers. - Enforces that sub-systems are initialized via `set_up()` before usage. - Supports test infrastructure setup and teardown consistency. Singleton Pattern ^^^^^^^^^^^^^^^^^ The Singleton pattern prevents the accidental creation of multiple `CSPWrapper` instances. The `__new__` method ensures the class reuses an existing instance when available. .. _cspwrapper-usage-example: Usage Example ^^^^^^^^^^^^^ To initialise and access the CSP sub-systems: .. code-block:: python from ska_csp_lmc_common.testing.k8s_test.wrappers import CSPWrapper, PSSWrapper, PSTWrapper # Set up the CSPWrapper csp = CSPWrapper() csp.set_up(lmc_wrapper, cbf_wrapper, pss_wrapper, pst_wrapper) # Accessing sub-system devices pst_devices = csp.pst.devices cbf_devices = csp.cbf.devices To tear down the test structure: .. code-block:: python CSPWrapper().tear_down() # Reset the singleton's internal state Wrappers for the CSP sub-systems ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following wrappers classes are used to represent the CSP subsystems at a technical level. BaseCSPWrapper ~~~~~~~~~~~~~~ Base class for CBF, PST and CSP.LMC wrappers, providing shared functionality such as device group access, initialization, and teardown. CBFWrapper ~~~~~~~~~~ Currently, the CBF subsystem is handled via the generic BaseCSPWrapper. This approach allows interaction with the devices during testing, providing common functionality such as basic state checks and device lifecycle management. In the Mid and Low instances of the CSP, BaseCSPWrapper is extended to provide specialized CBFWrapper implementations tailored to each deployment. PSSWrapper ~~~~~~~~~~ The PSSWrapper is a placeholder wrapper for the Pulsar Search Subsystem (PSS). At present, it only supports logging functions, as the PSS integration into CSP is still pending. Once the subsystem is fully integrated, this wrapper will be extended to support full test interactions, including initialization, teardown, and health/status monitoring operations. PSTWrapper ~~~~~~~~~~ The `PSTWrapper` is a technical representation of the Pulsar Timing Subsystem (PST) within the CSP Test Harness. It inherits from `BaseCSPWrapper` and is responsible for interacting with PST beam devices. It abstracts the internal logic necessary for configuring, resetting, and verifying the state of the PST subsystem in both emulated and production environments. The wrapper plays a key role in enabling test Actions to interact with PST in a structured and decoupled way. .. _pstwrapper-responsibilities: Responsibilities ^^^^^^^^^^^^^^^^ - Initialises a set of PST beam devices using Tango `DeviceProxy` instances. - Validates the initial state of each PST beam via `is_beam_in_initial_status()`, ensuring the devices are: - in the `DevState.OFF` state, - in `AdminMode.ONLINE`, - with `HealthState.OK`, and - in `ObsState.IDLE`. - Supports reinitialization of devices via `reinit_all_devices()` with a specific timeout. - Logs detailed information about devices not in the expected initial state. .. _pstwrapper-usage-example: Usage Example ^^^^^^^^^^^^^ To check if a beam is ready for testing: .. code-block:: python pst_wrapper = PSTWrapper(names={"0": "pst/beam/01"}) if pst_wrapper.is_beam_in_initial_status(beam_id=1): print("Beam 1 is in the expected initial state.") API documentation ----------------- CSPFacade API ~~~~~~~~~~~~~ .. toctree:: CSPFacade CSP Wrappers API ~~~~~~~~~~~~~~~~ .. toctree:: CSPWrapper BaseCSPWrapper PSTWrapper