Merge hw5-660 (#660)
Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using Shouldly;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||
using Xunit;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Tests;
|
||||
@@ -147,4 +148,56 @@ public sealed class AbLegacyDriverProbeTests
|
||||
$"Expected 'timed out' or 'Connect failed' but got: {result.Message}");
|
||||
result.Latency.ShouldBeNull();
|
||||
}
|
||||
|
||||
// ---- #660: Test Connect normalises the probe address exactly like the driver's probe loop ----
|
||||
|
||||
private static async Task<(DriverProbeResult Result, string? SeenName)> ProbeWithFakeAsync(string family, string? probeAddress)
|
||||
{
|
||||
var listener = new TcpListener(IPAddress.Loopback, 0);
|
||||
listener.Start();
|
||||
try
|
||||
{
|
||||
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
|
||||
var factory = new FakeAbLegacyTagFactory();
|
||||
var probe = new AbLegacyDriverProbe(factory);
|
||||
var addr = probeAddress is null ? "" : $",\"probe\":{{\"probeAddress\":\"{probeAddress}\"}}";
|
||||
var json = $"{{\"devices\":[{{\"hostAddress\":\"ab://127.0.0.1:{port}/1,0\",\"plcFamily\":\"{family}\"}}]{addr}}}";
|
||||
var result = await probe.ProbeAsync(json, TimeSpan.FromSeconds(3), TestContext.Current.CancellationToken);
|
||||
return (result, factory.Tags.Keys.SingleOrDefault());
|
||||
}
|
||||
finally { listener.Stop(); }
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Plc5", "I:017", "I:15")]
|
||||
[InlineData("Plc5", "O:010/07", "O:8/7")]
|
||||
[InlineData("LogixPccc", "I:017", "I:17")]
|
||||
[InlineData("Slc500", "I:017", "I:17")]
|
||||
[InlineData("MicroLogix", "I:017", "I:17")]
|
||||
[InlineData("Slc500", "N7:0", "N7:0")]
|
||||
[InlineData("Slc500", null, "S:0")]
|
||||
public async Task Probe_address_reaches_the_factory_family_normalised(string family, string? configured, string expected)
|
||||
{
|
||||
var (result, seen) = await ProbeWithFakeAsync(family, configured);
|
||||
result.Ok.ShouldBeTrue(result.Message);
|
||||
seen.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Normalised_default_probe_then_composes_with_the_libplctag_translation()
|
||||
{
|
||||
var (_, seen) = await ProbeWithFakeAsync("Plc5", "I:017");
|
||||
LibplctagLegacyName.Translate(seen!).ShouldBe("I1:15");
|
||||
var (_, status) = await ProbeWithFakeAsync("Slc500", null);
|
||||
LibplctagLegacyName.Translate(status!).ShouldBe("S2:0");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Unparseable_probe_address_is_a_clean_failure_not_an_exception()
|
||||
{
|
||||
var (result, seen) = await ProbeWithFakeAsync("Slc500", "not-an-address");
|
||||
result.Ok.ShouldBeFalse();
|
||||
result.Message!.ShouldContain("not-an-address");
|
||||
seen.ShouldBeNull();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user