fix(driver-modbus): probe parses the factory DTO shape — timeoutMs no longer silently dropped (R2-11, 05/CONV-2)

This commit is contained in:
Joseph Doherty
2026-07-13 11:07:44 -04:00
parent 24435efa8b
commit b2a56ebf3b
3 changed files with 91 additions and 13 deletions
@@ -0,0 +1,56 @@
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.Modbus;
namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Tests;
/// <summary>
/// R2-11 (05/CONV-2): the Modbus probe parses the SAME factory DTO shape the driver factory parses, so
/// <c>timeoutMs</c> binds identically instead of being silently dropped (it never bound to the runtime
/// <c>ModbusDriverOptions.Timeout</c> TimeSpan). The OpcUaClient probe/factory parse-parity rule.
/// </summary>
public sealed class ModbusDriverProbeParityTests
{
[Fact]
public void Config_timeoutMs_binds_as_the_effective_probe_timeout()
{
var (target, error) = ModbusDriverProbe.TryParseProbeTarget(
"{\"host\":\"10.0.0.5\",\"port\":502,\"unitId\":3,\"timeoutMs\":250}",
fallbackTimeout: TimeSpan.FromSeconds(5));
error.ShouldBeNull();
target.ShouldNotBeNull();
target!.Value.Host.ShouldBe("10.0.0.5");
target.Value.Port.ShouldBe(502);
target.Value.UnitId.ShouldBe((byte)3);
target.Value.Timeout.ShouldBe(TimeSpan.FromMilliseconds(250));
}
[Fact]
public void Absent_timeoutMs_falls_back_to_the_caller_timeout()
{
var (target, _) = ModbusDriverProbe.TryParseProbeTarget(
"{\"host\":\"10.0.0.5\",\"port\":502}", fallbackTimeout: TimeSpan.FromSeconds(5));
target!.Value.Timeout.ShouldBe(TimeSpan.FromSeconds(5));
target.Value.UnitId.ShouldBe((byte)1); // DTO default
}
[Fact]
public void Missing_host_is_an_error()
{
var (target, error) = ModbusDriverProbe.TryParseProbeTarget(
"{\"port\":0}", fallbackTimeout: TimeSpan.FromSeconds(5));
target.ShouldBeNull();
error.ShouldNotBeNull();
}
[Fact]
public void Invalid_json_is_an_error()
{
var (target, error) = ModbusDriverProbe.TryParseProbeTarget(
"not valid json {{", fallbackTimeout: TimeSpan.FromSeconds(5));
target.ShouldBeNull();
error.ShouldContain("invalid");
}
}