--- source_files: - DataPRO/StateMachine.Tests/States/RealtimeShould.cs - DataPRO/StateMachine.Tests/States/ConfigureShould.cs - DataPRO/StateMachine.Tests/States/RealtimeStartShould.cs - DataPRO/StateMachine.Tests/States/DiagnoseShould.cs - DataPRO/StateMachine.Tests/States/HardwareDiscoveryStartShould.cs generated_at: "2026-04-16T04:24:35.181988+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "19e719e00bdf4549" --- # StateMachine Module Documentation ## 1. Purpose This module implements a finite state machine (FSM) for managing the operational states of a data acquisition system (DAS), with states such as `HardwareDiscovery`, `Configure`, `Diagnose`, `Realtime`, and their transition points (e.g., `RealtimeStart`, `HardwareDiscoveryStart`). It enables deterministic state transitions based on runtime status and configuration parameters, ensuring the system progresses through initialization, configuration, diagnostics, and real-time operation phases in a controlled manner. The tests validate the behavior of individual state classes and their `StateSelector()` logic, which determines the next state based on current status flags and parameters. ## 2. Public Interface The following classes are defined in the `DTS.DASLib.Service.StateMachine` namespace (inferred from test imports). Each class represents a state in the state machine and exposes a `StateSelector()` method to determine the next state. ### `Realtime` - **Constructor**: `Realtime()` Initializes the state; sets `State` property to `State.Realtime`. - **Property**: `State` → `State` Returns the current state identifier (`State.Realtime`). - **Method**: `StateSelector()` → `DASState` *(not tested directly, but implied by pattern)* *Behavior inferred from other states: returns the next state based on status/params. Not directly exercised in provided tests.* ### `Configure` - **Constructor**: `Configure()` Initializes the state. - **Method**: `StateSelector()` → `DASState` Returns a `DASState` with `State` set to `State.ConfigureStart`. ### `RealtimeStart` - **Constructor**: `RealtimeStart()` Initializes the state. - **Property**: `Status` → `Status` *(exposes `RealtimeStatus`)* Contains `RealtimeStatus.CouldNotStartRealtime` (boolean). - **Method**: `StateSelector()` → `DASState` - If `RealtimeStatus.CouldNotStartRealtime == true`, returns `State.RealtimeStart`. - If `RealtimeStatus.CouldNotStartRealtime == false`, returns `State.Realtime`. ### `Diagnose` - **Constructor**: `Diagnose()` Initializes the state. - **Property**: `Status` → `Status` *(exposes `DiagnoseParams`)* Contains: - `DiagnoseParams.ProceedToRealtimeWhenDone` (bool) - `DiagnoseParams.RequireAllUnitsPassDiagnostic` (bool) - `DiagnoseParams.AllUnitsPassedDiagnostic` (bool) - **Method**: `StateSelector()` → `DASState` Returns: - `State.RealtimeStart` if `ProceedToRealtimeWhenDone == true` **and** (`RequireAllUnitsPassDiagnostic == false` **or** `AllUnitsPassedDiagnostic == true`). - `State.Diagnose` otherwise (e.g., when `ProceedToRealtimeWhenDone == false`, or when `RequireAllUnitsPassDiagnostic == true` and `AllUnitsPassedDiagnostic == false`). ### `HardwareDiscoveryStart` - **Constructor**: `HardwareDiscoveryStart()` Initializes the state; sets `State` property to `State.HardwareDiscoveryStart`. - **Property**: `State` → `State` Returns `State.HardwareDiscoveryStart`. - **Property**: `Status` → `Status` *(exposes `HardwareDiscoveryParams` and `HardwareDiscoveryStatusInfo`)* Contains: - `HardwareDiscoveryParams.ProceedWhenDone` (bool) - `HardwareDiscoveryParams.RequireAllDASFound` (bool) - `HardwareDiscoveryParams.GoToDownload` (bool) - `HardwareDiscoveryStatusInfo.AllDASFound` (bool) - `HardwareDiscoveryStatusInfo.SomeUnitsInArmState` (bool) - **Method**: `StateSelector()` → `DASState` Returns the next state based on: - If `ProceedWhenDone == true`: - `State.Download` if `GoToDownload == true` and `AllDASFound == true` (and `RequireAllDASFound == true`). - `State.Configure` if `GoToDownload == false` and either `AllDASFound == true` or `RequireAllDASFound == false`. - `State.Arm` if `AllDASFound == false`, `RequireAllDASFound == true`, `GoToDownload == false`, and `SomeUnitsInArmState == true`. - `State.HardwareDiscovery` if `AllDASFound == false`, `RequireAllDASFound == true`, `GoToDownload == false`, and `SomeUnitsInArmState == false`. ## 3. Invariants - Each state class’s `State` property (where exposed) must return the corresponding `State` enum value (e.g., `Realtime.State == State.Realtime`). - `StateSelector()` must return a non-null `DASState` object with a valid `State` field. - Transitions are deterministic: given identical `Status` and parameter values, `StateSelector()` must return the same next state. - `HardwareDiscoveryStart.StateSelector()` only evaluates transitions when `ProceedWhenDone == true` (based on test arrangements); behavior when `ProceedWhenDone == false` is not specified in tests. ## 4. Dependencies - **Internal Dependencies**: - `DTS.DASLib.Service.StateMachine` namespace (contains state classes and `State` enum). - `Status` type (contains nested `RealtimeStatus`, `DiagnoseParams`, `HardwareDiscoveryParams`, `HardwareDiscoveryStatusInfo`). - `DASState` type (returned by `StateSelector()`). - `State` enum (defines state identifiers: `Realtime`, `ConfigureStart`, `RealtimeStart`, `Diagnose`, `HardwareDiscoveryStart`, `HardwareDiscovery`, `Arm`, `Download`, `Configure`). - **Test Dependencies**: - `NUnit` for test framework (`[TestFixture]`, `[Test]`, `Assert.That`). - `NSubstitute` (used in `HardwareDiscoveryStartShould` tests, though not instantiated in provided snippets). - **Inferred Consumers**: A higher-level state machine controller (not shown) likely instantiates these state classes and calls `StateSelector()` to drive transitions. ## 5. Gotchas - **Ambiguous `Status` Type**: The `Status` property’s full structure (e.g., `RealtimeStatus`, `DiagnoseParams`, `HardwareDiscoveryParams`) is inferred from test usage but not defined in the source. Its exact shape and default values are unknown. - **Missing `StateSelector()` Implementation Details**: The tests do not cover edge cases (e.g., `ProceedWhenDone == false` in `HardwareDiscoveryStart`, or invalid parameter combinations). Behavior in untested scenarios is unspecified. - **Redundant Test for `DiagnoseShould.State_ShouldBeRealtime`**: This test instantiates `new Realtime()` but asserts `sut.State == State.Realtime`, which is identical to `RealtimeShould.State_ShouldBeRealtime`. Likely a copy-paste error in tests. - **No Error Handling Tests**: No tests verify behavior when `Status` is null, or when parameters conflict (e.g., `RequireAllUnitsPassDiagnostic == true` and `AllUnitsPassedDiagnostic == true` but `ProceedToRealtimeWhenDone == false`—though this is covered in `DiagnoseShould`). - **State Names vs. Class Names**: The class `RealtimeStart` corresponds to `State.RealtimeStart`, but `Configure` class returns `State.ConfigureStart` (not `State.Configure`). This mismatch may cause confusion. None identified beyond the above.