refactor(modbus): extract ModbusSocketLifecycle from ModbusTcpTransport (behaviour-preserving)

Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
Joseph Doherty
2026-07-24 13:47:18 -04:00
parent 20100c36ad
commit 2f38b5b285
4 changed files with 287 additions and 162 deletions
@@ -14,7 +14,7 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Tests;
/// (2) Sub-second <see cref="TimeSpan"/> values on <c>ModbusKeepAliveOptions.Time</c> /
/// <c>Interval</c> — the int-cast in <c>EnableKeepAlive</c> truncated <c>500&#160;ms</c> to
/// <c>0</c>, which most OSes interpret as "use the default", silently defeating the
/// configured timing. <c>ModbusTcpTransport.ClampToWholeSeconds</c> rounds up to a minimum
/// configured timing. <c>ModbusSocketLifecycle.ClampToWholeSeconds</c> rounds up to a minimum
/// of 1&#160;second.
/// </summary>
[Trait("Category", "Unit")]
@@ -70,7 +70,7 @@ public sealed class ModbusEdgeCaseValidationTests
[InlineData(60_000, 60)]
public void ClampToWholeSeconds_rounds_up_to_at_least_one_second(int ms, int expected)
{
ModbusTcpTransport.ClampToWholeSeconds(TimeSpan.FromMilliseconds(ms)).ShouldBe(expected);
ModbusSocketLifecycle.ClampToWholeSeconds(TimeSpan.FromMilliseconds(ms)).ShouldBe(expected);
}
/// <summary>Verifies that negative time spans are treated as one second.</summary>
@@ -80,6 +80,6 @@ public sealed class ModbusEdgeCaseValidationTests
// Defensive — operators occasionally configure a negative TimeSpan thinking it disables
// the feature. The OS would reject the negative int — clamping to 1 keeps the socket
// valid until the operator fixes the config.
ModbusTcpTransport.ClampToWholeSeconds(TimeSpan.FromSeconds(-5)).ShouldBe(1);
ModbusSocketLifecycle.ClampToWholeSeconds(TimeSpan.FromSeconds(-5)).ShouldBe(1);
}
}