refactor(modbus): extract ModbusSocketLifecycle from ModbusTcpTransport (behaviour-preserving)
Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
This commit is contained in:
+3
-3
@@ -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 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 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Pins the socket-lifecycle surface extracted from <see cref="ModbusTcpTransport"/> into the
|
||||
/// reusable <see cref="ModbusSocketLifecycle"/> (Task 3). The clamp helper moved with it, and a
|
||||
/// connect to a dead port must still surface the underlying socket failure.
|
||||
/// </summary>
|
||||
[Trait("Category", "Unit")]
|
||||
public sealed class ModbusSocketLifecycleTests
|
||||
{
|
||||
/// <summary>Verifies the whole-seconds clamp rounds sub-second/negative durations up to a minimum of one.</summary>
|
||||
/// <param name="seconds">The input duration in seconds.</param>
|
||||
/// <param name="expected">The expected clamped value in whole seconds.</param>
|
||||
[Theory]
|
||||
[InlineData(0.4, 1)] // sub-second rounds up to 1 (the int-cast truncation guard)
|
||||
[InlineData(2.0, 2)]
|
||||
[InlineData(-5.0, 1)] // negative clamps to 1
|
||||
public void ClampToWholeSeconds_rounds_up_min_one(double seconds, int expected)
|
||||
=> ModbusSocketLifecycle.ClampToWholeSeconds(TimeSpan.FromSeconds(seconds)).ShouldBe(expected);
|
||||
|
||||
/// <summary>Verifies a connect to a dead port surfaces the underlying socket failure.</summary>
|
||||
[Fact]
|
||||
public async Task Connect_to_dead_port_surfaces_socket_failure()
|
||||
{
|
||||
var life = new ModbusSocketLifecycle("127.0.0.1", 1, TimeSpan.FromMilliseconds(300),
|
||||
autoReconnect: false);
|
||||
await Should.ThrowAsync<System.Net.Sockets.SocketException>(
|
||||
life.ConnectAsync(TestContext.Current.CancellationToken));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user