using ZB.MOM.WW.ScadaBridge.CLI.Commands; using ZB.MOM.WW.ScadaBridge.Commons.Messages.Management; namespace ZB.MOM.WW.ScadaBridge.CLI.Tests; /// /// Regression tests for CLI-005 — malformed --bindings / --overrides JSON /// previously threw unhandled exceptions instead of producing a clean validation error. /// public class InstanceArgumentParsingTests { [Fact] public void ParseBindings_ValidJson_ReturnsPairs() { var ok = InstanceCommands.TryParseBindings( "[[\"Speed\", 5], [\"Mode\", 7]]", out var bindings, out var error); Assert.True(ok); Assert.Null(error); Assert.Equal(2, bindings!.Count); Assert.Equal(new ConnectionBinding("Speed", 5), bindings[0]); Assert.Equal(new ConnectionBinding("Mode", 7), bindings[1]); } [Fact] public void ParseBindings_MalformedJson_ReturnsErrorNotException() { var ok = InstanceCommands.TryParseBindings("not json", out var bindings, out var error); Assert.False(ok); Assert.Null(bindings); Assert.NotNull(error); } [Fact] public void ParseBindings_ShortPair_ReturnsErrorNotException() { // A pair with fewer than two elements previously threw ArgumentOutOfRangeException. var ok = InstanceCommands.TryParseBindings("[[\"Speed\"]]", out var bindings, out var error); Assert.False(ok); Assert.Null(bindings); Assert.NotNull(error); } [Fact] public void ParseBindings_WrongElementTypes_ReturnsErrorNotException() { // A non-string name / non-int id previously threw InvalidOperationException. var ok = InstanceCommands.TryParseBindings("[[5, \"Speed\"]]", out var bindings, out var error); Assert.False(ok); Assert.Null(bindings); Assert.NotNull(error); } [Fact] public void ParseBindings_JsonNull_ReturnsErrorNotException() { var ok = InstanceCommands.TryParseBindings("null", out var bindings, out var error); Assert.False(ok); Assert.Null(bindings); Assert.NotNull(error); } [Fact] public void ParseBindings_ThreeElementForm_CapturesReferenceOverride() { // The optional 3rd element carries the per-instance data-source reference // override (followup #4) so the CLI can SET it instead of always wiping it. var ok = InstanceCommands.TryParseBindings( "[[\"Speed\", 5, \"ns=2;s=Spd\"], [\"Mode\", 7]]", out var bindings, out var error); Assert.True(ok); Assert.Null(error); Assert.Equal(2, bindings!.Count); Assert.Equal(new ConnectionBinding("Speed", 5, "ns=2;s=Spd"), bindings[0]); // A 2-element entry still leaves the override null (template default applies). Assert.Equal(new ConnectionBinding("Mode", 7, null), bindings[1]); Assert.Null(bindings[1].DataSourceReferenceOverride); } [Fact] public void ParseBindings_ThirdElementExplicitNull_LeavesOverrideUnset() { var ok = InstanceCommands.TryParseBindings( "[[\"Speed\", 5, null]]", out var bindings, out var error); Assert.True(ok); Assert.Null(error); Assert.Single(bindings!); Assert.Null(bindings![0].DataSourceReferenceOverride); } [Fact] public void ParseBindings_ThirdElementWrongType_ReturnsErrorNotException() { // A non-string, non-null 3rd element is rejected with a clean error. var ok = InstanceCommands.TryParseBindings( "[[\"Speed\", 5, 99]]", out var bindings, out var error); Assert.False(ok); Assert.Null(bindings); Assert.NotNull(error); } [Fact] public void ParseBindings_FourElements_ReturnsErrorNotException() { var ok = InstanceCommands.TryParseBindings( "[[\"Speed\", 5, \"ref\", \"extra\"]]", out var bindings, out var error); Assert.False(ok); Assert.Null(bindings); Assert.NotNull(error); } [Fact] public void ParseOverrides_ValidJson_ReturnsDictionary() { var ok = InstanceCommands.TryParseOverrides( "{\"Speed\": \"100\", \"Mode\": null}", out var overrides, out var error); Assert.True(ok); Assert.Null(error); Assert.Equal(2, overrides!.Count); Assert.Equal("100", overrides["Speed"]); Assert.Null(overrides["Mode"]); } [Fact] public void ParseOverrides_MalformedJson_ReturnsErrorNotException() { var ok = InstanceCommands.TryParseOverrides("{bad json", out var overrides, out var error); Assert.False(ok); Assert.Null(overrides); Assert.NotNull(error); } [Fact] public void ParseOverrides_JsonNull_ReturnsErrorNotException() { var ok = InstanceCommands.TryParseOverrides("null", out var overrides, out var error); Assert.False(ok); Assert.Null(overrides); Assert.NotNull(error); } }