diff --git a/src/Platform/Microsoft.Testing.Platform/CommandLine/Parser.cs b/src/Platform/Microsoft.Testing.Platform/CommandLine/Parser.cs index f8f6306d22..ac84f54e79 100644 --- a/src/Platform/Microsoft.Testing.Platform/CommandLine/Parser.cs +++ b/src/Platform/Microsoft.Testing.Platform/CommandLine/Parser.cs @@ -12,7 +12,7 @@ internal static class CommandLineParser /// Options parser support: /// * Only - and -- prefix for options https://learn.microsoft.com/dotnet/standard/commandline/syntax#options /// * Multiple option arguments https://learn.microsoft.com/dotnet/standard/commandline/syntax#multiple-arguments - /// * Use a space, '=', or ':' as the delimiter between an option name and its argument + /// * Use '=' or ':' as the delimiter between an option name and its argument. See https://learn.microsoft.com/dotnet/standard/commandline/syntax#option-argument-delimiters /// * escape with \ /// * surrounding with "" /// * surrounding with '' @@ -39,89 +39,65 @@ private static CommandLineParseResult Parse(List args, IEnvironment envi List errors = []; string? currentOption = null; - string? currentArg = null; string? toolName = null; List currentOptionArguments = []; + bool isFirstRealArgument = true; for (int i = 0; i < args.Count; i++) { - if (args[i].StartsWith('@') && ResponseFileHelper.TryReadResponseFile(args[i].Substring(1), errors, out string[]? newArguments)) + string? currentArg = args[i]; + + if (currentArg.StartsWith('@') && ResponseFileHelper.TryReadResponseFile(currentArg.Substring(1), errors, out string[]? newArguments)) { args.InsertRange(i + 1, newArguments); continue; } - bool argumentHandled = false; - currentArg = args[i]; + // If it's the first argument and it doesn't start with - then it's the tool name + // TODO: This won't work correctly if the first argument provided is a response file that contains the tool name. + if (isFirstRealArgument && currentArg[0] != '-') + { + toolName = currentArg; + isFirstRealArgument = false; + continue; + } - while (!argumentHandled) + isFirstRealArgument = false; + + // we accept as start for options -- and - all the rest are arguments to the previous option + if ((currentArg.Length > 1 && currentArg[0].Equals('-') && !currentArg[1].Equals('-')) || + (currentArg.Length > 2 && currentArg[0].Equals('-') && currentArg[1].Equals('-') && !currentArg[2].Equals('-'))) { - if (currentArg is null) + if (currentOption is not null) { - errors.Add(string.Format(CultureInfo.InvariantCulture, PlatformResources.CommandLineParserUnexpectedNullArgument, i)); - break; + options.Add(new(currentOption, [.. currentOptionArguments])); + currentOptionArguments.Clear(); } - // we accept as start for options -- and - all the rest are arguments to the previous option - if ((args[i].Length > 1 && currentArg[0].Equals('-') && !currentArg[1].Equals('-')) || - (args[i].Length > 2 && currentArg[0].Equals('-') && currentArg[1].Equals('-') && !currentArg[2].Equals('-'))) + ParseOptionAndSeparators(currentArg, out currentOption, out currentArg); + } + + if (currentArg is not null) + { + if (currentOption is null) { - if (currentOption is null) - { - ParseOptionAndSeparators(args[i], out currentOption, out currentArg); - argumentHandled = currentArg is null; - } - else - { - options.Add(new(currentOption, [.. currentOptionArguments])); - currentOptionArguments.Clear(); - ParseOptionAndSeparators(args[i], out currentOption, out currentArg); - argumentHandled = true; - } + errors.Add(string.Format(CultureInfo.InvariantCulture, PlatformResources.CommandLineParserUnexpectedArgument, args[i])); } else { - // If it's the first argument and it doesn't start with - then it's the tool name - if (i == 0 && !args[0][0].Equals('-')) - { - toolName = currentArg; - } - else if (currentOption is null) + if (TryUnescape(currentArg.Trim(), currentOption, environment, out string? unescapedArg, out string? error)) { - errors.Add(string.Format(CultureInfo.InvariantCulture, PlatformResources.CommandLineParserUnexpectedArgument, args[i])); + currentOptionArguments.Add(unescapedArg); } else { - if (TryUnescape(currentArg.Trim(), currentOption, environment, out string? unescapedArg, out string? error)) - { - currentOptionArguments.Add(unescapedArg); - } - else - { - errors.Add(error); - } - - currentArg = null; + errors.Add(error); } - - argumentHandled = true; } } } if (currentOption is not null) { - if (currentArg is not null) - { - if (TryUnescape(currentArg.Trim(), currentOption, environment, out string? unescapedArg, out string? error)) - { - currentOptionArguments.Add(unescapedArg); - } - else - { - errors.Add(error); - } - } - options.Add(new(currentOption, [.. currentOptionArguments])); } @@ -129,7 +105,7 @@ private static CommandLineParseResult Parse(List args, IEnvironment envi static void ParseOptionAndSeparators(string arg, out string? currentOption, out string? currentArg) { - (currentOption, currentArg) = arg.IndexOfAny([':', '=', ' ']) switch + (currentOption, currentArg) = arg.IndexOfAny([':', '=']) switch { -1 => (arg, null), var delimiterIndex => (arg[..delimiterIndex], arg[(delimiterIndex + 1)..]), diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx b/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx index 87f9857b19..036efd79e9 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx +++ b/src/Platform/Microsoft.Testing.Platform/Resources/PlatformResources.resx @@ -1,17 +1,17 @@  - @@ -319,9 +319,6 @@ Unexpected argument {0} - - Unexpected null argument at index {0} - Unexpected single quote in argument: {0} diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf index d69915357b..41efbbe3b5 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.cs.xlf @@ -142,11 +142,6 @@ Neočekávaný argument {0} - - Unexpected null argument at index {0} - Neočekávaný argument null v indexu {0} - - Unexpected single quote in argument: {0} Neočekávaná jednoduchá uvozovka v argumentu: {0} diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf index 80b922c3a3..6dafbd92ae 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.de.xlf @@ -142,11 +142,6 @@ Unerwartetes Argument {0} - - Unexpected null argument at index {0} - Unerwartetes NULL-Argument bei Index {0} - - Unexpected single quote in argument: {0} Unerwartetes einfaches Anführungszeichen im Argument: {0} diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf index 2b8f0aaaee..ca22203490 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.es.xlf @@ -142,11 +142,6 @@ Argumento inesperado {0} - - Unexpected null argument at index {0} - Argumento nulo inesperado en el índice {0} - - Unexpected single quote in argument: {0} Comilla simple inesperada en el argumento: {0} diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf index 4f6119a574..e341f04865 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.fr.xlf @@ -142,11 +142,6 @@ Arguments inattendue {0} - - Unexpected null argument at index {0} - Argument null inattendu à l’index de recherche{0} - - Unexpected single quote in argument: {0} Guillemet simple inattendu dans l’argument : {0} diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf index f1796f9a53..5a0fe9b87c 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.it.xlf @@ -142,11 +142,6 @@ Argomento imprevisto {0} - - Unexpected null argument at index {0} - Argomento Null imprevisto in corrispondenza dell'indice {0} - - Unexpected single quote in argument: {0} Virgolette singole impreviste nell'argomento: {0} diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf index 3c784e8746..6f402ad9c9 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ja.xlf @@ -142,11 +142,6 @@ 予期しない引数 {0} - - Unexpected null argument at index {0} - インデックス {0} に予期しない null 引数があります - - Unexpected single quote in argument: {0} 引数に予期しない単一引用符が含まれています: {0} diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf index fad6a7986d..519426f952 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ko.xlf @@ -142,11 +142,6 @@ 예기치 않은 인수 {0} - - Unexpected null argument at index {0} - 인덱스 {0}에 예기치 않은 null 인수가 있습니다. - - Unexpected single quote in argument: {0} 인수 {0}에 예기치 않은 작은따옴표가 있습니다. diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf index 875395e810..ec53ed7191 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pl.xlf @@ -142,11 +142,6 @@ Nieoczekiwany argument {0} - - Unexpected null argument at index {0} - Nieoczekiwany argument o wartości null przy indeksie {0} - - Unexpected single quote in argument: {0} Nieoczekiwany pojedynczy cudzysłów w argumencie: {0} diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf index bf2ef2a56f..5a2bc95a8f 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.pt-BR.xlf @@ -142,11 +142,6 @@ Argumento inesperado {0} - - Unexpected null argument at index {0} - Argumento nulo inesperado no índice {0} - - Unexpected single quote in argument: {0} Aspas simples inesperadas no argumento: {0} diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf index c702e2a59b..30201fcdff 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.ru.xlf @@ -142,11 +142,6 @@ Неожиданный аргумент {0} - - Unexpected null argument at index {0} - Неожиданный аргумент, имеющий значение NULL, с индексом {0} - - Unexpected single quote in argument: {0} Неожиданная одинарная кавычка в аргументе: {0} diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf index 93eb747fa8..36dc259dc6 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.tr.xlf @@ -142,11 +142,6 @@ {0} bağımsız değişkeni beklenmiyordu - - Unexpected null argument at index {0} - {0} dizinindeki null bağımsız değişken beklenmiyordu - - Unexpected single quote in argument: {0} {0} bağımsız değişkeninde tek alıntı beklenmiyor diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf index 98941bc5ab..08a9beb56e 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hans.xlf @@ -142,11 +142,6 @@ 意外的参数 {0} - - Unexpected null argument at index {0} - 索引 {0} 处出现意外 null 参数 - - Unexpected single quote in argument: {0} 参数中出现意外的单引号: {0} diff --git a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf index c015e72cf9..a35747c7cb 100644 --- a/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf +++ b/src/Platform/Microsoft.Testing.Platform/Resources/xlf/PlatformResources.zh-Hant.xlf @@ -142,11 +142,6 @@ 未預期的引數 {0} - - Unexpected null argument at index {0} - 索引 {0} 中有未預期的 Null 引數 - - Unexpected single quote in argument: {0} 引數 {0} 中有未預期的單引號 diff --git a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/ArgumentArityTests.cs b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/ArgumentArityTests.cs index c688a2062f..18d10a3281 100644 --- a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/ArgumentArityTests.cs +++ b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/ArgumentArityTests.cs @@ -27,7 +27,7 @@ public sealed class ArgumentArityTests public async Task ParseAndValidate_WhenOptionWithArityZeroIsCalledWithOneArgument_ReturnsFalse() { // Arrange - string[] args = ["--zeroArgumentsOption arg"]; + string[] args = ["--zeroArgumentsOption", "arg"]; CommandLineParseResult parseResult = CommandLineParser.Parse(args, new SystemEnvironment()); // Act @@ -43,7 +43,7 @@ public async Task ParseAndValidate_WhenOptionWithArityZeroIsCalledWithOneArgumen public async Task ParseAndValidate_WhenOptionWithArityExactlyOneIsCalledWithTwoArguments_ReturnsFalse() { // Arrange - string[] args = ["--exactlyOneArgumentsOption arg1", "arg2"]; + string[] args = ["--exactlyOneArgumentsOption", "arg1", "arg2"]; CommandLineParseResult parseResult = CommandLineParser.Parse(args, new SystemEnvironment()); // Act @@ -75,7 +75,7 @@ public async Task ParseAndValidate_WhenOptionWithArityExactlyOneIsCalledWithoutA public async Task ParseAndValidate_WhenOptionWithArityZeroOrOneIsCalledWithTwoArguments_ReturnsFalse() { // Arrange - string[] args = ["--zeroOrOneArgumentsOption arg1", "--zeroOrOneArgumentsOption arg2"]; + string[] args = ["--zeroOrOneArgumentsOption", "arg1", "--zeroOrOneArgumentsOption", "arg2"]; CommandLineParseResult parseResult = CommandLineParser.Parse(args, new SystemEnvironment()); // Act @@ -107,7 +107,7 @@ public async Task ParseAndValidate_WhenOptionWithArityOneOrMoreIsCalledWithoutAr public async Task ParseAndValidate_WhenOptionsGetsTheExpectedNumberOfArguments_ReturnsTrue() { // Arrange - string[] args = ["--zeroArgumentsOption", "--zeroOrOneArgumentsOption", "--zeroOrMoreArgumentsOption arg2", "--exactlyOneArgumentsOption arg1", "oneOrMoreArgumentsOption arg1"]; + string[] args = ["--zeroArgumentsOption", "--zeroOrOneArgumentsOption", "--zeroOrMoreArgumentsOption", "arg2", "--exactlyOneArgumentsOption", "arg1", "--oneOrMoreArgumentsOption", "arg1"]; CommandLineParseResult parseResult = CommandLineParser.Parse(args, new SystemEnvironment()); // Act @@ -115,8 +115,8 @@ public async Task ParseAndValidate_WhenOptionsGetsTheExpectedNumberOfArguments_R _extensionCommandLineOptionsProviders, new Mock().Object); // Assert - Assert.IsTrue(result.IsValid); Assert.IsNull(result.ErrorMessage); + Assert.IsTrue(result.IsValid); } private sealed class ExtensionCommandLineProviderMockOptionsWithDifferentArity : ICommandLineOptionsProvider diff --git a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/CommandLineHandlerTests.cs b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/CommandLineHandlerTests.cs index 2e82935009..37ecded06a 100644 --- a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/CommandLineHandlerTests.cs +++ b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/CommandLineHandlerTests.cs @@ -42,6 +42,66 @@ public async Task ParseAndValidateAsync_InvalidCommandLineArguments_ReturnsFalse Assert.Contains("Unexpected argument 'a'", result.ErrorMessage); } + [TestMethod] + public async Task ParseAndValidateAsync_ValidArgumentWithColonFollowedByValidArgumentWithoutColon_ReturnsTrue() + { + string[] args = ["--results-directory", "TestResults", "--timeout:60m", "--ignore-exit-code", "8"]; + CommandLineParseResult parseResult = CommandLineParser.Parse(args, new SystemEnvironment()); + + Assert.IsEmpty(parseResult.Errors); + Assert.IsFalse(parseResult.HasError); + + Assert.HasCount(3, parseResult.Options); + + Assert.AreEqual("results-directory", parseResult.Options[0].Name); + string resultsDirectory = Assert.ContainsSingle(parseResult.Options[0].Arguments); + Assert.AreEqual("TestResults", resultsDirectory); + + Assert.AreEqual("timeout", parseResult.Options[1].Name); + string timeout = Assert.ContainsSingle(parseResult.Options[1].Arguments); + Assert.AreEqual("60m", timeout); + + Assert.AreEqual("ignore-exit-code", parseResult.Options[2].Name); + string ignoreExitCode = Assert.ContainsSingle(parseResult.Options[2].Arguments); + Assert.AreEqual("8", ignoreExitCode); + + ValidationResult result = await CommandLineOptionsValidator.ValidateAsync(parseResult, _systemCommandLineOptionsProviders, + _extensionCommandLineOptionsProviders, new Mock().Object); + + Assert.IsNull(result.ErrorMessage); + Assert.IsTrue(result.IsValid); + } + + [TestMethod] + public async Task ParseAndValidateAsync_ValidArgumentWithColonValueIsShort_ReturnsTrue() + { + string[] args = ["--results-directory", "TestResults", "--ignore-exit-code:8", "--timeout", "60m"]; + CommandLineParseResult parseResult = CommandLineParser.Parse(args, new SystemEnvironment()); + + Assert.IsEmpty(parseResult.Errors); + Assert.IsFalse(parseResult.HasError); + + Assert.HasCount(3, parseResult.Options); + + Assert.AreEqual("results-directory", parseResult.Options[0].Name); + string resultsDirectory = Assert.ContainsSingle(parseResult.Options[0].Arguments); + Assert.AreEqual("TestResults", resultsDirectory); + + Assert.AreEqual("ignore-exit-code", parseResult.Options[1].Name); + string ignoreExitCode = Assert.ContainsSingle(parseResult.Options[1].Arguments); + Assert.AreEqual("8", ignoreExitCode); + + Assert.AreEqual("timeout", parseResult.Options[2].Name); + string timeout = Assert.ContainsSingle(parseResult.Options[2].Arguments); + Assert.AreEqual("60m", timeout); + + ValidationResult result = await CommandLineOptionsValidator.ValidateAsync(parseResult, _systemCommandLineOptionsProviders, + _extensionCommandLineOptionsProviders, new Mock().Object); + + Assert.IsNull(result.ErrorMessage); + Assert.IsTrue(result.IsValid); + } + [TestMethod] public async Task ParseAndValidateAsync_EmptyCommandLineArguments_ReturnsTrue() { @@ -98,7 +158,7 @@ public async Task ParseAndValidateAsync_InvalidOption_ReturnsFalse() public async Task ParseAndValidateAsync_InvalidArgumentArity_ReturnsFalse() { // Arrange - string[] args = ["--help arg"]; + string[] args = ["--help", "arg"]; CommandLineParseResult parseResult = CommandLineParser.Parse(args, new SystemEnvironment()); // Act diff --git a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/CommandLineTests.cs b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/CommandLineTests.cs index 74af4bf15c..ab0108e55c 100644 --- a/test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/CommandLineTests.cs +++ b/test/UnitTests/Microsoft.Testing.Platform.UnitTests/CommandLine/CommandLineTests.cs @@ -86,7 +86,7 @@ public static string ParserTestDataFormat(MethodInfo methodInfo, object?[]? data yield return (15, ["--option1:a"], null, new CommandLineParseResultWrapper(null, new List { new("option1", ["a"]) }.ToArray(), [])); yield return (16, ["--option1=a"], null, new CommandLineParseResultWrapper(null, new List { new("option1", ["a"]) }.ToArray(), [])); yield return (17, ["--option1=a", "--option1=b"], null, new CommandLineParseResultWrapper(null, new List { new("option1", ["a"]), new("option1", ["b"]) }.ToArray(), [])); - yield return (18, ["--option1=a", "--option1 b"], null, new CommandLineParseResultWrapper(null, new List { new("option1", ["a"]), new("option1", ["b"]) }.ToArray(), [])); + yield return (18, ["--option1=a", "--option1", "b"], null, new CommandLineParseResultWrapper(null, new List { new("option1", ["a"]), new("option1", ["b"]) }.ToArray(), [])); yield return (19, ["--option1=a=a"], null, new CommandLineParseResultWrapper(null, new List { new("option1", ["a=a"]) }.ToArray(), [])); yield return (20, ["--option1=a:a"], null, new CommandLineParseResultWrapper(null, new List { new("option1", ["a:a"]) }.ToArray(), [])); yield return (21, ["--option1:a=a"], null, new CommandLineParseResultWrapper(null, new List { new("option1", ["a=a"]) }.ToArray(), []));