diff --git a/src/ZB.MOM.WW.ScadaBridge.DelmiaNotifier/ArgParser.cs b/src/ZB.MOM.WW.ScadaBridge.DelmiaNotifier/ArgParser.cs new file mode 100644 index 00000000..e5d3ef72 --- /dev/null +++ b/src/ZB.MOM.WW.ScadaBridge.DelmiaNotifier/ArgParser.cs @@ -0,0 +1,73 @@ +namespace ZB.MOM.WW.ScadaBridge.DelmiaNotifier; + +/// Outcome of parsing the command line: success carries the payload, failure carries a human reason. +internal sealed record ParseResult(bool Ok, RecipeDownload? Payload, string? Error) +{ + public static ParseResult Success(RecipeDownload payload) => new(true, payload, null); + public static ParseResult Fail(string error) => new(false, null, error); +} + +/// +/// Hand-rolled, reflection-free parser for the legacy WWNotifier flags. Each flag takes one value +/// (short or long form). The four required flags must be present; the two optional flags may be omitted. +/// +internal static class ArgParser +{ + public static ParseResult Parse(string[] args) + { + var payload = new RecipeDownload(); + + for (var i = 0; i < args.Length; i++) + { + var flag = args[i]; + if (i + 1 >= args.Length) + { + return ParseResult.Fail($"missing value for flag '{flag}'"); + } + + var value = args[++i]; + switch (flag) + { + case "-m" or "--machine": + payload.MachineCode = value; + break; + case "-d" or "--downloadpath": + payload.DownloadPath = value; + break; + case "-w" or "--workorder": + payload.WorkOrderNumber = value; + break; + case "-p" or "--partnumber": + payload.PartNumber = value; + break; + case "-s" or "--seqop": + payload.JobStepNumber = value; + break; + case "-u" or "--username": + payload.Username = value; + break; + default: + return ParseResult.Fail($"unknown flag '{flag}'"); + } + } + + if (string.IsNullOrEmpty(payload.MachineCode)) + { + return ParseResult.Fail("missing required flag -m/--machine"); + } + if (string.IsNullOrEmpty(payload.DownloadPath)) + { + return ParseResult.Fail("missing required flag -d/--downloadpath"); + } + if (string.IsNullOrEmpty(payload.WorkOrderNumber)) + { + return ParseResult.Fail("missing required flag -w/--workorder"); + } + if (string.IsNullOrEmpty(payload.PartNumber)) + { + return ParseResult.Fail("missing required flag -p/--partnumber"); + } + + return ParseResult.Success(payload); + } +} diff --git a/tests/ZB.MOM.WW.ScadaBridge.DelmiaNotifier.Tests/ArgParserTests.cs b/tests/ZB.MOM.WW.ScadaBridge.DelmiaNotifier.Tests/ArgParserTests.cs new file mode 100644 index 00000000..b0c45be8 --- /dev/null +++ b/tests/ZB.MOM.WW.ScadaBridge.DelmiaNotifier.Tests/ArgParserTests.cs @@ -0,0 +1,59 @@ +using ZB.MOM.WW.ScadaBridge.DelmiaNotifier; + +namespace ZB.MOM.WW.ScadaBridge.DelmiaNotifier.Tests; + +public class ArgParserTests +{ + [Fact] + public void Parses_all_flags() + { + var r = ArgParser.Parse(new[] { "-m", "Z28061", "-d", @"C:\r.nc", "-w", "W1", "-p", "P1", "-s", "0100", "-u", "op" }); + Assert.True(r.Ok); + Assert.Equal("Z28061", r.Payload!.MachineCode); + Assert.Equal(@"C:\r.nc", r.Payload.DownloadPath); + Assert.Equal("W1", r.Payload.WorkOrderNumber); + Assert.Equal("P1", r.Payload.PartNumber); + Assert.Equal("0100", r.Payload.JobStepNumber); + Assert.Equal("op", r.Payload.Username); + } + + [Fact] + public void Parses_long_flags() + { + var r = ArgParser.Parse(new[] { "--machine", "Z", "--downloadpath", "x", "--workorder", "W", "--partnumber", "P" }); + Assert.True(r.Ok); + Assert.Equal("Z", r.Payload!.MachineCode); + Assert.Equal("x", r.Payload.DownloadPath); + } + + [Fact] + public void Missing_required_returns_error() + { + var r = ArgParser.Parse(new[] { "-m", "Z28061", "-d", @"C:\r.nc", "-w", "W1" }); // no -p + Assert.False(r.Ok); + Assert.Contains("partnumber", r.Error, System.StringComparison.OrdinalIgnoreCase); + } + + [Fact] + public void Optional_flags_may_be_omitted() + { + var r = ArgParser.Parse(new[] { "-m", "Z", "-d", "x", "-w", "W", "-p", "P" }); + Assert.True(r.Ok); + Assert.Null(r.Payload!.Username); + Assert.Null(r.Payload.JobStepNumber); + } + + [Fact] + public void Unknown_flag_returns_error() + { + var r = ArgParser.Parse(new[] { "-z", "x" }); + Assert.False(r.Ok); + } + + [Fact] + public void Flag_without_value_returns_error() + { + var r = ArgParser.Parse(new[] { "-m" }); + Assert.False(r.Ok); + } +}