Files
lmxopcua/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.MTConnect.Tests/MTConnectBufferSizeWarningTests.cs
T
Joseph Doherty 8a6f0e3c84 fix(mtconnect): the Agent refuses count ABOVE bufferSize, not at it (#825)
Live gate against the cppagent 2.7 fixture: count=16384 with bufferSize
16384 streams; 16385 is OUT_OF_RANGE ('count' must be less than 16385).
Warn only when SampleCount > bufferSize, pin both sides of the edge
against the live Agent, and correct the #804 wording that said 'at or
above'.
2026-11-11 01:38:48 -05:00

130 lines
5.3 KiB
C#

using System.Net;
using System.Net.Http;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
namespace ZB.MOM.WW.OtOpcUa.Driver.MTConnect.Tests;
/// <summary>
/// lmxopcua#825 — a <c>SampleCount</c> above the Agent's <c>bufferSize</c> is refused <c>OUT_OF_RANGE</c> on
/// every <c>/sample</c> stream. The <c>/probe</c> header carries <c>bufferSize</c>, so Test Connect and the
/// driver's initialize (deploy) both warn instead of leaving it to surface as a Degraded stream.
/// </summary>
[Trait("Category", "Unit")]
public sealed class MTConnectBufferSizeWarningTests
{
private static string ProbeXml(string? bufferSizeAttribute) =>
$"""
<?xml version="1.0" encoding="UTF-8"?>
<MTConnectDevices xmlns="urn:mtconnect.org:MTConnectDevices:2.0">
<Header instanceId="1"{(bufferSizeAttribute is null ? "" : $" bufferSize=\"{bufferSizeAttribute}\"")}/>
<Devices>
<Device id="d" name="D">
<DataItems><DataItem id="d_avail" category="EVENT" type="AVAILABILITY"/></DataItems>
</Device>
</Devices>
</MTConnectDevices>
""";
[Theory]
[InlineData("16384", 16384L)]
[InlineData(null, null)]
[InlineData("0", null)]
[InlineData("-5", null)]
[InlineData("lots", null)]
public void The_probe_parser_reads_the_header_buffer_size_and_never_fails_on_it(string? attribute, long? expected) =>
MTConnectProbeParser.Parse(ProbeXml(attribute)).BufferSize.ShouldBe(expected);
[Theory]
[InlineData(16384, 16384L, false)] // live, cppagent 2.7: count == bufferSize is accepted
[InlineData(16385, 16384L, true)] // ... and bufferSize + 1 refused OUT_OF_RANGE
[InlineData(20000, 16384L, true)]
[InlineData(1_000_000, null, false)]
public void The_warning_fires_only_above_the_buffer_size(int sampleCount, long? bufferSize, bool warns)
{
var warning = MTConnectDriver.SampleCountBufferWarning(sampleCount, bufferSize);
(warning is not null).ShouldBe(warns);
if (warns) warning!.ShouldContain($"at most {bufferSize}");
}
[Fact]
public async Task Test_Connect_stays_ok_but_carries_the_warning_when_SampleCount_does_not_fit()
{
var probe = new MTConnectDriverProbe(new StubHandler(ProbeXml("16384")));
var r = await probe.ProbeAsync(
"{\"agentUri\":\"http://stub-agent:5000\",\"sampleCount\":16385}", TimeSpan.FromSeconds(3),
TestContext.Current.CancellationToken);
r.Ok.ShouldBeTrue("the Agent answered — reachability is not the problem");
r.Message!.ShouldContain("WARNING:");
r.Message!.ShouldContain("bufferSize 16384");
}
[Fact]
public async Task Test_Connect_checks_the_driver_default_when_SampleCount_is_absent()
{
// The default SampleCount is 1000 — an Agent with a tiny buffer refuses it too.
var probe = new MTConnectDriverProbe(new StubHandler(ProbeXml("512")));
var r = await probe.ProbeAsync(
"{\"agentUri\":\"http://stub-agent:5000\"}", TimeSpan.FromSeconds(3), TestContext.Current.CancellationToken);
r.Ok.ShouldBeTrue();
r.Message!.ShouldContain("SampleCount 1000 is above the Agent's bufferSize 512");
}
[Fact]
public async Task Test_Connect_message_is_unchanged_when_SampleCount_fits()
{
var probe = new MTConnectDriverProbe(new StubHandler(ProbeXml("16384")));
var r = await probe.ProbeAsync(
"{\"agentUri\":\"http://stub-agent:5000\",\"sampleCount\":16384}", TimeSpan.FromSeconds(3),
TestContext.Current.CancellationToken);
r.Ok.ShouldBeTrue();
r.Message!.ShouldNotContain("WARNING");
}
[Theory]
[InlineData(131073, true)]
[InlineData(131072, false)]
[InlineData(1000, false)]
public async Task Initialize_warns_and_surfaces_the_buffer_size_on_the_diagnostics_bag(int sampleCount, bool warns)
{
var client = CannedAgentClient.FromFixtures(); // Fixtures/probe.xml: bufferSize="131072"
client.Probe.BufferSize.ShouldBe(131072L);
var logger = new RecordingDriverLogger();
var driver = new MTConnectDriver(
new MTConnectDriverOptions
{
AgentUri = "http://fixture-agent:5000",
RequestTimeoutMs = 5000,
SampleCount = sampleCount,
Tags = [new MTConnectTagDefinition("dev1_pos", DriverDataType.Float64)],
},
"mt-825",
_ => client,
logger);
try
{
await driver.InitializeAsync("{}", TestContext.Current.CancellationToken);
logger.Warnings.Any(w => w.Contains("bufferSize", StringComparison.Ordinal)).ShouldBe(warns);
driver.GetDiagnostics()["agentBufferSize"].ShouldBe("131072");
}
finally
{
await driver.ShutdownAsync(TestContext.Current.CancellationToken);
}
}
private sealed class StubHandler(string probeXml) : HttpMessageHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken ct) =>
Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(probeXml, System.Text.Encoding.UTF8, "application/xml"),
});
}
}