Files
lmxopcua/tests/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli.Tests/CommandMetadataTests.cs
Joseph Doherty f46e126208 fix(driver-ablegacy-cli): resolve Low code-review findings (Driver.AbLegacy.Cli-002,003,004,005,006,007)
- Driver.AbLegacy.Cli-002: WriteCommand.Value description lists the full
  true/false, 1/0, on/off, yes/no alias set.
- Driver.AbLegacy.Cli-003: SubscribeCommand serialises every WriteLine
  via a per-execution consoleGate lock so the poll-thread OnDataChange
  handler can't interleave with the banner.
- Driver.AbLegacy.Cli-004: dropped 'await using var driver' in favour of
  a plain 'var driver' + explicit await ShutdownAsync in finally; the
  driver is no longer shut down twice.
- Driver.AbLegacy.Cli-005: SubscribeCommand.IntervalMs description
  carries the PollGroupEngine 250ms-floor caveat; docs/Driver.AbLegacy.Cli.md
  spells out the same.
- Driver.AbLegacy.Cli-006: ProbeCommand --type now carries the short
  alias 't' to match the other commands.
- Driver.AbLegacy.Cli-007: BuildOptionsTests cover the probe-disabled,
  device-shape, tag-passthrough, timeout-propagation, and empty-tag-list
  paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 08:34:32 -04:00

81 lines
3.4 KiB
C#

using System.Linq;
using System.Reflection;
using CliFx.Attributes;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli.Commands;
namespace ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli.Tests;
/// <summary>
/// Locks in the CLI command-option contract surface area — short aliases and
/// help-text wording — that the AbLegacy CLI is expected to keep in parity with
/// its sibling AbCip CLI and with <c>docs/Driver.AbLegacy.Cli.md</c>.
/// Regression coverage for findings Driver.AbLegacy.Cli-002, -005, -006.
/// </summary>
[Trait("Category", "Unit")]
public sealed class CommandMetadataTests
{
private static CommandOptionAttribute GetOption<TCommand>(string propertyName)
{
var prop = typeof(TCommand).GetProperty(
propertyName,
BindingFlags.Public | BindingFlags.Instance);
prop.ShouldNotBeNull($"property {propertyName} is missing from {typeof(TCommand).Name}");
var attr = prop!.GetCustomAttribute<CommandOptionAttribute>();
attr.ShouldNotBeNull(
$"property {propertyName} on {typeof(TCommand).Name} lacks [CommandOption]");
return attr!;
}
// ---------- Driver.AbLegacy.Cli-006 — ProbeCommand --type needs short alias 't' ----------
[Fact]
public void ProbeCommand_type_has_short_alias_t()
{
// Parity with read / write / subscribe: --type / -t works everywhere.
var attr = GetOption<ProbeCommand>(nameof(ProbeCommand.DataType));
attr.ShortName.ShouldBe('t');
}
[Theory]
[InlineData(typeof(ReadCommand), nameof(ReadCommand.DataType))]
[InlineData(typeof(WriteCommand), nameof(WriteCommand.DataType))]
[InlineData(typeof(SubscribeCommand), nameof(SubscribeCommand.DataType))]
public void Other_commands_keep_type_short_alias_t(System.Type commandType, string propName)
{
var prop = commandType.GetProperty(propName, BindingFlags.Public | BindingFlags.Instance);
prop.ShouldNotBeNull();
var attr = prop!.GetCustomAttribute<CommandOptionAttribute>();
attr.ShouldNotBeNull();
attr!.ShortName.ShouldBe('t');
}
// ---------- Driver.AbLegacy.Cli-002 — WriteCommand --value help lists full bool alias set ----------
[Fact]
public void WriteCommand_value_help_lists_full_boolean_alias_set()
{
// ParseBool accepts true/false, 1/0, on/off, yes/no — the help text must say so
// (DriverClis.md documents the full alias set as the shared CLI contract).
var attr = GetOption<WriteCommand>(nameof(WriteCommand.Value));
attr.Description.ShouldNotBeNull();
attr.Description!.ShouldContain("true/false", Case.Insensitive);
attr.Description!.ShouldContain("1/0");
attr.Description!.ShouldContain("on/off", Case.Insensitive);
attr.Description!.ShouldContain("yes/no", Case.Insensitive);
}
// ---------- Driver.AbLegacy.Cli-005 — SubscribeCommand --interval-ms help notes 250ms floor ----------
[Fact]
public void SubscribeCommand_interval_ms_help_notes_PollGroupEngine_floor()
{
// Parity with AbCip CLI: operators passing -i 100 deserve a heads-up that
// PollGroupEngine floors sub-250ms values.
var attr = GetOption<SubscribeCommand>(nameof(SubscribeCommand.IntervalMs));
attr.Description.ShouldNotBeNull();
attr.Description!.ShouldContain("250", Case.Insensitive);
}
}