97 lines
4.1 KiB
C#
97 lines
4.1 KiB
C#
using Shouldly;
|
|
using Xunit;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.S7.Tests;
|
|
|
|
/// <summary>
|
|
/// Config-time guard on the two span-read knobs. There is no <c>IValidateOptions</c> machinery
|
|
/// for S7 — <see cref="S7DriverFactoryExtensions.ParseOptions"/> is the single choke point every
|
|
/// deployed config passes through — so a nonsensical value used to be accepted at deploy time and
|
|
/// only misbehave later, in the read loop, on a driver that had already reported healthy.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The legal-value cases matter as much as the rejections: <c>-1</c> on the gap is the documented
|
|
/// escape hatch that disables grouping entirely (<c>S7Driver</c> enables spans on <c>>= 0</c>),
|
|
/// and <c>0</c> means "tolerate no gap at all", i.e. merge only strictly adjacent tags. A guard
|
|
/// written as <c>< 0</c> would break both.
|
|
/// </remarks>
|
|
public sealed class S7SpanOptionValidationTests
|
|
{
|
|
/// <summary>A driver-config blob carrying the given span knob, host included (it is required).</summary>
|
|
private static string Config(string knob, int value) =>
|
|
"{\"host\":\"10.0.0.1\",\"" + knob + "\":" + value.ToString(System.Globalization.CultureInfo.InvariantCulture) + "}";
|
|
|
|
/// <summary>A span cap below one can never admit a single planned block read, so it is rejected.</summary>
|
|
[Theory]
|
|
[InlineData(0)]
|
|
[InlineData(-1)]
|
|
[InlineData(-220)]
|
|
public void A_span_cap_below_one_is_rejected(int maxSpanBytes)
|
|
{
|
|
var ex = Should.Throw<InvalidOperationException>(() => S7DriverFactoryExtensions.ParseOptions(
|
|
"s7-cfg", Config("spanReadMaxSpanBytes", maxSpanBytes)));
|
|
|
|
ex.Message.ShouldContain("SpanReadMaxSpanBytes");
|
|
ex.Message.ShouldContain("s7-cfg");
|
|
}
|
|
|
|
/// <summary>A gap budget below the grouping-disabled sentinel is rejected.</summary>
|
|
[Theory]
|
|
[InlineData(-2)]
|
|
[InlineData(-16)]
|
|
public void A_gap_budget_below_minus_one_is_rejected(int maxGapBytes)
|
|
{
|
|
var ex = Should.Throw<InvalidOperationException>(() => S7DriverFactoryExtensions.ParseOptions(
|
|
"s7-cfg", Config("spanReadMaxGapBytes", maxGapBytes)));
|
|
|
|
ex.Message.ShouldContain("SpanReadMaxGapBytes");
|
|
ex.Message.ShouldContain("s7-cfg");
|
|
}
|
|
|
|
/// <summary>
|
|
/// The two legal edge values survive: <c>-1</c> (grouping disabled) and <c>0</c> (no gap
|
|
/// tolerated). Both are documented behaviour, not degenerate input.
|
|
/// </summary>
|
|
[Theory]
|
|
[InlineData(-1)]
|
|
[InlineData(0)]
|
|
public void The_documented_gap_edge_values_are_accepted(int maxGapBytes)
|
|
{
|
|
var parsed = S7DriverFactoryExtensions.ParseOptions("s7-cfg", Config("spanReadMaxGapBytes", maxGapBytes));
|
|
|
|
parsed.SpanReadMaxGapBytes.ShouldBe(maxGapBytes);
|
|
}
|
|
|
|
/// <summary>A one-byte span cap is the smallest legal cap and must not trip the guard.</summary>
|
|
[Fact]
|
|
public void The_smallest_legal_span_cap_is_accepted()
|
|
{
|
|
var parsed = S7DriverFactoryExtensions.ParseOptions("s7-cfg", Config("spanReadMaxSpanBytes", 1));
|
|
|
|
parsed.SpanReadMaxSpanBytes.ShouldBe(1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// An over-PDU span cap is legal — S7.Net transparently chunks an oversized <c>ReadBytes</c>
|
|
/// into several wire requests — so the guard must not invent an upper bound it cannot know
|
|
/// (the negotiated PDU size is opaque inside S7.Net).
|
|
/// </summary>
|
|
[Fact]
|
|
public void An_over_pdu_span_cap_is_accepted_because_S7Net_chunks_it()
|
|
{
|
|
var parsed = S7DriverFactoryExtensions.ParseOptions("s7-cfg", Config("spanReadMaxSpanBytes", 4096));
|
|
|
|
parsed.SpanReadMaxSpanBytes.ShouldBe(4096);
|
|
}
|
|
|
|
/// <summary>Omitting both knobs keeps the shipped defaults, which must themselves pass the guard.</summary>
|
|
[Fact]
|
|
public void The_shipped_defaults_pass_the_guard()
|
|
{
|
|
var parsed = S7DriverFactoryExtensions.ParseOptions("s7-cfg", "{\"host\":\"10.0.0.1\"}");
|
|
|
|
parsed.SpanReadMaxGapBytes.ShouldBe(S7DriverOptions.DefaultSpanReadMaxGapBytes);
|
|
parsed.SpanReadMaxSpanBytes.ShouldBe(S7DriverOptions.DefaultSpanReadMaxSpanBytes);
|
|
}
|
|
}
|