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; /// /// 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 docs/Driver.AbLegacy.Cli.md. /// Regression coverage for findings Driver.AbLegacy.Cli-002, -005, -006. /// [Trait("Category", "Unit")] public sealed class CommandMetadataTests { private static CommandOptionAttribute GetOption(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(); 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(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(); 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(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(nameof(SubscribeCommand.IntervalMs)); attr.Description.ShouldNotBeNull(); attr.Description!.ShouldContain("250", Case.Insensitive); } }