Files
lmxopcua/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests/ProbeCommandTests.cs
Joseph Doherty 80ef8806e0 fix(driver-modbus-cli): resolve Low code-review findings (Driver.Modbus.Cli-003,004,005,006,007,008)
- Driver.Modbus.Cli-003: ModbusCommandBase.ValidateEndpoint rejects
  --port outside 1..65535, non-positive --timeout-ms, and --unit-id
  outside 1..247.
- Driver.Modbus.Cli-004: wrapped SubscribeCommand's OnDataChange handler
  body in a try/catch (warn-and-swallow) and serialised the console
  write through a lock.
- Driver.Modbus.Cli-005: Probe / Read / Write now catch the
  cancellation-during-init OperationCanceledException and print
  'Cancelled.' instead of dumping a stack trace.
- Driver.Modbus.Cli-006: ProbeCommand.ComputeVerdict derives the headline
  from BOTH the driver state and the probe snapshot's OPC UA quality
  class so the headline can't disagree with the wire result.
- Driver.Modbus.Cli-007: docs/Driver.Modbus.Cli.md carries an explicit
  'CLI scope' callout — the address-string grammar is a DriverConfig
  JSON feature; the CLI takes the structured triple only.
- Driver.Modbus.Cli-008: pinned BuildOptions, ValidateEndpoint, the
  region-validation guards, ComputeVerdict, and the cancellation-during-
  initialize paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 08:35:05 -04:00

61 lines
2.3 KiB
C#

using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
using ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Commands;
namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Cli.Tests;
/// <summary>
/// Covers <see cref="ProbeCommand.ComputeVerdict"/> — the headline-string helper that
/// combines the driver-side <see cref="DriverState"/> with the probe snapshot's OPC UA
/// <see cref="DataValueSnapshot.StatusCode"/> so the operator never sees the previous
/// contradictory pair (`Health: Healthy` above a `Status: Bad...` snapshot line — see
/// Driver.Modbus.Cli-006).
/// </summary>
[Trait("Category", "Unit")]
public sealed class ProbeCommandTests
{
[Fact]
public void ComputeVerdict_returns_OK_when_state_is_Healthy_and_status_is_Good()
{
var verdict = ProbeCommand.ComputeVerdict(DriverState.Healthy, statusCode: 0x00000000u);
verdict.ShouldContain("OK");
}
[Theory]
[InlineData(DriverState.Faulted)]
[InlineData(DriverState.Reconnecting)]
[InlineData(DriverState.Unknown)]
public void ComputeVerdict_returns_FAIL_when_driver_state_is_not_Healthy(DriverState state)
{
var verdict = ProbeCommand.ComputeVerdict(state, statusCode: 0x00000000u);
verdict.ShouldContain("FAIL");
}
[Theory]
[InlineData(0x80050000u)] // BadCommunicationError
[InlineData(0x800A0000u)] // BadTimeout
[InlineData(0x80740000u)] // BadTypeMismatch
[InlineData(0x80000000u)] // generic Bad
public void ComputeVerdict_returns_FAIL_when_snapshot_status_is_Bad_even_if_driver_state_Healthy(uint statusCode)
{
// Driver.Modbus.Cli-006: a successful InitializeAsync sets DriverState.Healthy, but
// the FC03 probe read may still fail (snapshot.StatusCode != Good). Previously the
// headline reported Healthy while the snapshot line below showed Bad. The verdict
// must reflect the actual probe-read outcome.
var verdict = ProbeCommand.ComputeVerdict(DriverState.Healthy, statusCode);
verdict.ShouldContain("FAIL");
}
[Fact]
public void ComputeVerdict_returns_DEGRADED_for_uncertain_status_with_healthy_driver()
{
var verdict = ProbeCommand.ComputeVerdict(DriverState.Healthy, statusCode: 0x40000000u);
verdict.ShouldContain("DEGRADED");
}
}