157 lines
6.8 KiB
C#
157 lines
6.8 KiB
C#
using Shouldly;
|
|
using Xunit;
|
|
using ZB.MOM.WW.OtOpcUa.Driver.FOCAS;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.FOCAS.Tests;
|
|
|
|
/// <summary>
|
|
/// Version-matrix coverage for <see cref="FocasCapabilityMatrix"/>. Encodes the
|
|
/// documented Fanuc FOCAS Developer Kit support boundaries per CNC series so a
|
|
/// config-time change that widens or narrows a range without updating
|
|
/// <c>docs/v2/focas-version-matrix.md</c> fails a test. Every assertion cites the
|
|
/// specific matrix row it reflects.
|
|
/// </summary>
|
|
[Trait("Category", "Unit")]
|
|
public sealed class FocasCapabilityMatrixTests
|
|
{
|
|
// ---- Macro ranges ----
|
|
|
|
[Theory]
|
|
[InlineData(FocasCncSeries.Sixteen_i, 999, true)]
|
|
[InlineData(FocasCncSeries.Sixteen_i, 1000, false)] // above legacy ceiling
|
|
[InlineData(FocasCncSeries.Zero_i_D, 999, true)]
|
|
[InlineData(FocasCncSeries.Zero_i_D, 9999, false)] // 0i-D is still legacy-ceiling
|
|
[InlineData(FocasCncSeries.Zero_i_F, 9999, true)] // widened on 0i-F
|
|
[InlineData(FocasCncSeries.Zero_i_F, 10000, false)]
|
|
[InlineData(FocasCncSeries.Thirty_i, 99999, true)] // highest-end
|
|
[InlineData(FocasCncSeries.Thirty_i, 100000, false)]
|
|
[InlineData(FocasCncSeries.PowerMotion_i, 999, true)]
|
|
[InlineData(FocasCncSeries.PowerMotion_i, 1000, false)] // atypical coverage
|
|
public void Macro_range_matches_series(FocasCncSeries series, int number, bool accepted)
|
|
{
|
|
var address = new FocasAddress(FocasAreaKind.Macro, null, number, null);
|
|
var result = FocasCapabilityMatrix.Validate(series, address);
|
|
(result is null).ShouldBe(accepted,
|
|
$"Macro #{number} on {series}: expected {(accepted ? "accept" : "reject")}, got {(result ?? "accept")}");
|
|
}
|
|
|
|
// ---- Parameter ranges ----
|
|
|
|
[Theory]
|
|
[InlineData(FocasCncSeries.Sixteen_i, 9999, true)]
|
|
[InlineData(FocasCncSeries.Sixteen_i, 10000, false)] // 16i capped at 9999
|
|
[InlineData(FocasCncSeries.Zero_i_F, 14999, true)]
|
|
[InlineData(FocasCncSeries.Zero_i_F, 15000, false)]
|
|
[InlineData(FocasCncSeries.Thirty_i, 29999, true)]
|
|
[InlineData(FocasCncSeries.Thirty_i, 30000, false)]
|
|
public void Parameter_range_matches_series(FocasCncSeries series, int number, bool accepted)
|
|
{
|
|
var address = new FocasAddress(FocasAreaKind.Parameter, null, number, null);
|
|
var result = FocasCapabilityMatrix.Validate(series, address);
|
|
(result is null).ShouldBe(accepted);
|
|
}
|
|
|
|
// ---- PMC letters ----
|
|
|
|
[Theory]
|
|
[InlineData(FocasCncSeries.Sixteen_i, "X", true)]
|
|
[InlineData(FocasCncSeries.Sixteen_i, "Y", true)]
|
|
[InlineData(FocasCncSeries.Sixteen_i, "R", true)]
|
|
[InlineData(FocasCncSeries.Sixteen_i, "F", false)] // 16i has no F/G signal groups
|
|
[InlineData(FocasCncSeries.Sixteen_i, "G", false)]
|
|
[InlineData(FocasCncSeries.Sixteen_i, "K", false)]
|
|
[InlineData(FocasCncSeries.Zero_i_D, "E", true)] // widened since 0i-D
|
|
[InlineData(FocasCncSeries.Zero_i_D, "F", false)] // still no F on 0i-D
|
|
[InlineData(FocasCncSeries.Zero_i_F, "F", true)] // F/G added on 0i-F
|
|
[InlineData(FocasCncSeries.Zero_i_F, "K", false)] // K/T still 30i-only
|
|
[InlineData(FocasCncSeries.Thirty_i, "K", true)]
|
|
[InlineData(FocasCncSeries.Thirty_i, "T", true)]
|
|
[InlineData(FocasCncSeries.Thirty_i, "Q", false)] // unsupported even on 30i
|
|
public void Pmc_letter_matches_series(FocasCncSeries series, string letter, bool accepted)
|
|
{
|
|
var address = new FocasAddress(FocasAreaKind.Pmc, letter, 0, null);
|
|
var result = FocasCapabilityMatrix.Validate(series, address);
|
|
(result is null).ShouldBe(accepted,
|
|
$"PMC letter '{letter}' on {series}: expected {(accepted ? "accept" : "reject")}, got {(result ?? "accept")}");
|
|
}
|
|
|
|
// ---- PMC number ceiling ----
|
|
|
|
[Theory]
|
|
[InlineData(FocasCncSeries.Sixteen_i, "R", 999, true)]
|
|
[InlineData(FocasCncSeries.Sixteen_i, "R", 1000, false)]
|
|
[InlineData(FocasCncSeries.Zero_i_D, "R", 1999, true)]
|
|
[InlineData(FocasCncSeries.Zero_i_D, "R", 2000, false)]
|
|
[InlineData(FocasCncSeries.Zero_i_F, "R", 9999, true)]
|
|
[InlineData(FocasCncSeries.Zero_i_F, "R", 10000, false)]
|
|
[InlineData(FocasCncSeries.Thirty_i, "R", 59999, true)]
|
|
[InlineData(FocasCncSeries.Thirty_i, "R", 60000, false)]
|
|
public void Pmc_number_ceiling_matches_series(FocasCncSeries series, string letter, int number, bool accepted)
|
|
{
|
|
var address = new FocasAddress(FocasAreaKind.Pmc, letter, number, null);
|
|
var result = FocasCapabilityMatrix.Validate(series, address);
|
|
(result is null).ShouldBe(accepted);
|
|
}
|
|
|
|
// ---- Unknown series is permissive ----
|
|
|
|
[Theory]
|
|
[InlineData("Z", 999_999)] // absurd PMC address
|
|
[InlineData("Q", 0)] // non-existent letter
|
|
public void Unknown_series_accepts_any_PMC(string letter, int number)
|
|
{
|
|
var address = new FocasAddress(FocasAreaKind.Pmc, letter, number, null);
|
|
FocasCapabilityMatrix.Validate(FocasCncSeries.Unknown, address).ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void Unknown_series_accepts_any_macro_number()
|
|
{
|
|
var address = new FocasAddress(FocasAreaKind.Macro, null, 999_999, null);
|
|
FocasCapabilityMatrix.Validate(FocasCncSeries.Unknown, address).ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void Unknown_series_accepts_any_parameter_number()
|
|
{
|
|
var address = new FocasAddress(FocasAreaKind.Parameter, null, 999_999, null);
|
|
FocasCapabilityMatrix.Validate(FocasCncSeries.Unknown, address).ShouldBeNull();
|
|
}
|
|
|
|
// ---- Reason messages include enough context to diagnose ----
|
|
|
|
[Fact]
|
|
public void Rejection_message_names_series_and_limit()
|
|
{
|
|
var address = new FocasAddress(FocasAreaKind.Macro, null, 100_000, null);
|
|
var reason = FocasCapabilityMatrix.Validate(FocasCncSeries.Zero_i_F, address);
|
|
reason.ShouldNotBeNull();
|
|
reason.ShouldContain("100000");
|
|
reason.ShouldContain("Zero_i_F");
|
|
reason.ShouldContain("9999");
|
|
}
|
|
|
|
[Fact]
|
|
public void Pmc_rejection_lists_accepted_letters()
|
|
{
|
|
var address = new FocasAddress(FocasAreaKind.Pmc, "Q", 0, null);
|
|
var reason = FocasCapabilityMatrix.Validate(FocasCncSeries.Thirty_i, address);
|
|
reason.ShouldNotBeNull();
|
|
reason.ShouldContain("'Q'");
|
|
reason.ShouldContain("X"); // some accepted letter should appear
|
|
reason.ShouldContain("Y");
|
|
}
|
|
|
|
// ---- PMC address letter is case-insensitive ----
|
|
|
|
[Theory]
|
|
[InlineData("x")]
|
|
[InlineData("X")]
|
|
[InlineData("f")]
|
|
public void Pmc_letter_match_is_case_insensitive_on_30i(string letter)
|
|
{
|
|
var address = new FocasAddress(FocasAreaKind.Pmc, letter, 0, null);
|
|
FocasCapabilityMatrix.Validate(FocasCncSeries.Thirty_i, address).ShouldBeNull();
|
|
}
|
|
}
|