using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.FOCAS;
using ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Wire;
namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Tests;
///
/// #740 / R07:H14 — the capability matrix admits macro numbers up to 99999 (30i/31i/32i) and parameters up
/// to 29999 (Unknown: anything), and the FOCAS/2 request block carries 32-bit arguments, but the adapter
/// cast every number to short: MACRO:99999 asked the CNC for #-31073 and published
/// that variable Good under the authored tag. Numbers now travel as int end to end.
///
[Trait("Category", "Unit")]
public sealed class FocasWideNumberTests
{
/// The macro request carries the full number in both 32-bit argument slots.
[Theory]
[InlineData(500)]
[InlineData(32767)]
[InlineData(32768)]
[InlineData(99999)]
public void Macro_request_carries_the_unnarrowed_number(int number)
{
var block = FocasWireClient.MacroRequest(number, pathId: 1);
block.Command.ShouldBe((ushort)0x0015);
block.Arg1.ShouldBe(number);
block.Arg2.ShouldBe(number);
}
///
/// Positive control on the wire encoding: the request for #500 is byte-identical to the one the real
/// 31i-B answered in the ref-macro-500-0x0015 capture, so widening changed nothing below 32768.
///
[Fact]
public void Macro_request_for_500_matches_the_live_capture_bytes()
{
var body = FocasWireProtocol.BuildRequestBody([FocasWireClient.MacroRequest(500, pathId: 1)]);
Convert.ToHexString(body).ShouldBe("0001001C0001000100150000 01F4000001F4000000000000000000000000".Replace(" ", ""));
}
/// A global parameter puts its number in both arguments; an axis parameter puts the axis second.
[Theory]
[InlineData(6711, (short)0, 6711)]
[InlineData(40000, (short)0, 40000)]
[InlineData(40000, (short)2, 2)]
public void Parameter_request_carries_the_unnarrowed_number(int number, short axis, int expectedArg2)
{
var block = FocasWireClient.ParameterRequest(number, axis, pathId: 1);
block.Command.ShouldBe((ushort)0x000e);
block.Arg1.ShouldBe(number);
block.Arg2.ShouldBe(expectedArg2);
}
/// The decoded macro reports the number that was asked for, not a wrapped one.
[Fact]
public void Parsed_macro_keeps_a_number_above_short_range()
{
var payload = new byte[] { 0x05, 0xF5, 0xE1, 0x00, 0x00, 0x0A, 0x00, 0x08 };
var m = FocasWireClient.ParseMacro(99999, payload);
m.Number.ShouldBe(99999);
m.Scaled.ShouldBe(1.0);
}
///
/// pmc_rdpmcrng addresses are 16-bit on the wire; a PMC number whose slot runs past 65535 is refused
/// rather than wrapped onto a different address (Unknown series admits any number).
///
[Theory]
[InlineData(100, 1, true)]
[InlineData(65535, 1, true)]
[InlineData(65534, 2, true)]
[InlineData(65535, 2, false)]
[InlineData(70000, 1, false)]
public void Pmc_range_outside_16_bits_is_refused_not_wrapped(int number, int width, bool ok)
{
WireFocasClient.TryPmcRange(number, width, out var start, out var end).ShouldBe(ok);
if (ok)
{
((int)start).ShouldBe(number);
((int)end).ShouldBe(number + width - 1);
}
}
}