From 8b0dd3579c431f4c812bef9cda0bf63f0e99af91 Mon Sep 17 00:00:00 2001 From: jonsequitur Date: Fri, 3 Mar 2017 13:14:36 -0800 Subject: [PATCH] a couple of parser unit tests --- .../dotnet-complete/CompleteCommand.cs | 11 +- .../commands/ParserExtensions.cs | 11 ++ .../commands/{Create.cs => ParserFor.cs} | 132 ++++++++---------- src/dotnet/dotnet.csproj | 2 +- test/dotnet.Tests/ParseTests.cs | 54 +++++++ test/dotnet.Tests/dotnet.Tests.csproj | 1 + 6 files changed, 132 insertions(+), 79 deletions(-) create mode 100644 src/dotnet/dotnet-complete/commands/ParserExtensions.cs rename src/dotnet/dotnet-complete/commands/{Create.cs => ParserFor.cs} (89%) create mode 100644 test/dotnet.Tests/ParseTests.cs diff --git a/src/dotnet/commands/dotnet-complete/CompleteCommand.cs b/src/dotnet/commands/dotnet-complete/CompleteCommand.cs index ed05473af..0518df868 100644 --- a/src/dotnet/commands/dotnet-complete/CompleteCommand.cs +++ b/src/dotnet/commands/dotnet-complete/CompleteCommand.cs @@ -7,14 +7,11 @@ using System.Linq; using System.Text; using Microsoft.DotNet.Cli.CommandLine; using Microsoft.DotNet.Cli.Utils; -using Command = Microsoft.DotNet.Cli.CommandLine.Command; namespace Microsoft.DotNet.Tools.Complete { public class CompleteCommand { - private static readonly Command dotnetCommand = Create.DotnetCommand(); - public static int Run(string[] args) { DebugHelper.HandleDebugSwitch(ref args); @@ -22,7 +19,11 @@ namespace Microsoft.DotNet.Tools.Complete var log = new StringBuilder(); log.AppendLine($"args: {string.Join(" ", args.Select(a => $"\"{a}\""))}"); - var result = dotnetCommand["complete"].Parse(args); + // get the parser for the current subcommand + var completeCommandParser = ParserFor.DotnetCommand["complete"]; + + // parse the arguments + var result = completeCommandParser.Parse(args); log.AppendLine("diagram (1): " + result.Diagram()); @@ -57,7 +58,7 @@ namespace Microsoft.DotNet.Tools.Complete } } - var result = dotnetCommand.Parse(input); + var result = ParserFor.DotnetCommand.Parse(input); log.AppendLine("diagram (2): " + result.Diagram()); diff --git a/src/dotnet/dotnet-complete/commands/ParserExtensions.cs b/src/dotnet/dotnet-complete/commands/ParserExtensions.cs new file mode 100644 index 000000000..825a1067c --- /dev/null +++ b/src/dotnet/dotnet-complete/commands/ParserExtensions.cs @@ -0,0 +1,11 @@ +using System; +using Microsoft.DotNet.Cli.CommandLine; + +namespace Microsoft.DotNet.Tools +{ + public static class ParserExtensions + { + public static void ShowHelp(this ParseResult parseResult) => + Console.WriteLine(parseResult.Command().HelpView()); + } +} \ No newline at end of file diff --git a/src/dotnet/dotnet-complete/commands/Create.cs b/src/dotnet/dotnet-complete/commands/ParserFor.cs similarity index 89% rename from src/dotnet/dotnet-complete/commands/Create.cs rename to src/dotnet/dotnet-complete/commands/ParserFor.cs index 72be2e7be..cf64aa10f 100644 --- a/src/dotnet/dotnet-complete/commands/Create.cs +++ b/src/dotnet/dotnet-complete/commands/ParserFor.cs @@ -9,18 +9,18 @@ using System.Net.Http; using System.Threading; using Microsoft.Build.Evaluation; using Microsoft.DotNet.Cli.CommandLine; +using Microsoft.DotNet.Tools.Common; using Newtonsoft.Json.Linq; using static Microsoft.DotNet.Cli.CommandLine.Accept; using static Microsoft.DotNet.Cli.CommandLine.Create; using Command = Microsoft.DotNet.Cli.CommandLine.Command; -namespace Microsoft.DotNet.Tools.Complete +namespace Microsoft.DotNet.Tools { - public static class Create + public static class ParserFor { - public static Command DotnetCommand() => - Command("dotnet", - ".NET Command Line Tools (2.0.0-alpha-alpha-004866)", + private static readonly Command _dotnetCommand = Command("dotnet", + ".NET Command Line Tools", NoArguments, New(), Restore(), @@ -41,7 +41,45 @@ namespace Microsoft.DotNet.Tools.Complete Complete(), HelpOption(), Option("--info", ""), - VerbosityOption()); + VerbosityOption(), + Option("-d", "")); + + public static Command DotnetCommand { get; } = _dotnetCommand; + + private static Command Add() => + Command("add", + ".NET Add Command", + ExactlyOneArgument.DefaultToCurrentDirectory(), + Command("package", + ".NET Add Package reference Command", + ExactlyOneArgument + .WithSuggestionsFrom(QueryNuGet), + HelpOption(), + Option("-v|--version", + "Version for the package to be added.", + ExactlyOneArgument + .With(name: "VERSION")), + Option("-f|--framework", + "Add reference only when targetting a specific framework", + ExactlyOneArgument + .With(name: "FRAMEWORK")), + Option("-n|--no-restore ", + "Add reference without performing restore preview and compatibility check."), + Option("-s|--source", + "Use specific NuGet package sources to use during the restore."), + Option("--package-directory", + "Restore the packages to this Directory .", + ExactlyOneArgument + .With(name: "PACKAGE_DIRECTORY"))), + Command("reference", + "Command to add project to project reference", + OneOrMoreArguments, + HelpOption(), + Option("-f|--framework", + "Add reference only when targetting a specific framework", + AnyOneOf(TargetFrameworksFromProjectFile) + .With(name: "FRAMEWORK"))), + HelpOption()); private static Command Complete() => Command("complete", "", @@ -52,14 +90,6 @@ namespace Microsoft.DotNet.Tools.Complete .With(name: "command"), o => int.Parse(o.Arguments.Single()))); - private static Command Add() => - Command("add", - ".NET Add Command", - ExactlyOneArgument, - Package(), - Reference(), - HelpOption()); - private static Command Build() => Command("build", ".NET Builder", @@ -73,7 +103,7 @@ namespace Microsoft.DotNet.Tools.Complete AnyOneOf(TargetFrameworksFromProjectFile)), Option("-r|--runtime", "Target runtime to build for. The default is to build a portable application.", - WithSuggestionsFrom(_ => RunTimesFromProjectFile())), + AnyOneOf(RunTimesFromProjectFile)), Option("-c|--configuration", "Configuration to use for building the project. Default for most projects is \"Debug\".", ExactlyOneArgument @@ -106,10 +136,11 @@ namespace Microsoft.DotNet.Tools.Complete private static Command List() => Command("list", ".NET List Command", - ExactlyOneArgument + ZeroOrOneArgument .With(name: "PROJECT", description: - "The project file to operate on. If a file is not specified, the command will search the current directory for one."), + "The project file to operate on. If a file is not specified, the command will search the current directory for one.") + .DefaultToCurrentDirectory(), HelpOption(), Command("reference", "Command to list project to project references", ExactlyOneArgument @@ -252,31 +283,7 @@ namespace Microsoft.DotNet.Tools.Complete .With(name: "VERSION_SUFFIX")), Option("-s|--serviceable", "Set the serviceable flag in the package. For more information, please see https://aka.ms/nupkgservicing."), - VerbosityOption() - ); - - private static Command Package() => - Command("package", - ".NET Add Package reference Command", - ExactlyOneArgument - .WithSuggestionsFrom(QueryNuGet), - HelpOption(), - Option("-v|--version", - "Version for the package to be added.", - ExactlyOneArgument - .With(name: "VERSION")), - Option("-f|--framework", - "Add reference only when targetting a specific framework", - ExactlyOneArgument - .With(name: "FRAMEWORK")), - Option("-n|--no-restore ", - "Add reference without performing restore preview and compatibility check."), - Option("-s|--source", - "Use specific NuGet package sources to use during the restore."), - Option("--package-directory", - "Restore the packages to this Directory .", - ExactlyOneArgument - .With(name: "PACKAGE_DIRECTORY"))); + VerbosityOption()); private static Command Publish() => Command("publish", @@ -289,7 +296,7 @@ namespace Microsoft.DotNet.Tools.Complete .With(name: "FRAMEWORK")), Option("-r|--runtime", "Publish the project for a given runtime. This is used when creating self-contained deployment. Default is to publish a framework-dependent app.", - ExactlyOneArgument + AnyOneOf(RunTimesFromProjectFile) .With(name: "RUNTIME_IDENTIFIER")), Option("-o|--output", "Output directory in which to place the published artifacts.", @@ -307,32 +314,22 @@ namespace Microsoft.DotNet.Tools.Complete private static Command Remove() => Command("remove", ".NET Remove Command", + ZeroOrOneArgument + .With(name: "PROJECT") + .DefaultToCurrentDirectory(), HelpOption(), Command("package", "Command to remove package reference.", HelpOption()), Command("reference", "Command to remove project to project reference", - WithSuggestionsFrom(_ => ProjectReferencesFromProjectFile()), + AnyOneOf(ProjectReferencesFromProjectFile), HelpOption(), Option("-f|--framework", "Remove reference only when targetting a specific framework", ExactlyOneArgument .With(name: "FRAMEWORK")))); - private static Command Reference() => - Command("reference", - "Command to add project to project reference", - OneOrMoreArguments, - HelpOption(), - Option("-f|--framework", - "Add reference only when targetting a specific framework", - ExactlyOneArgument - .WithSuggestionsFrom( - _ => TargetFrameworksFromProjectFile().ToArray()) - // .With(name: "FRAMEWORK") - )); - private static Command Restore() => Command("restore", ".NET dependency restorer", @@ -343,7 +340,7 @@ namespace Microsoft.DotNet.Tools.Complete .With(name: "SOURCE")), Option("-r|--runtime", "Target runtime to restore packages for.", - WithSuggestionsFrom(_ => RunTimesFromProjectFile()) + AnyOneOf(RunTimesFromProjectFile) .With(name: "RUNTIME_IDENTIFIER")), Option("--packages", "Directory to install packages in.", @@ -381,6 +378,7 @@ namespace Microsoft.DotNet.Tools.Complete private static Command Sln() => Command("sln", ".NET modify solution file command", + HelpOption(), Command("add", ".NET Add project(s) to a solution file Command", @@ -441,6 +439,9 @@ namespace Microsoft.DotNet.Tools.Complete "Do not build project before testing."), VerbosityOption()); + private static ArgumentsRule DefaultToCurrentDirectory(this ArgumentsRule rule) => + rule.With(defaultValue: () => PathUtility.EnsureTrailingSlash(Directory.GetCurrentDirectory())); + private static Option HelpOption() => Option("-h|--help", "Show help information", @@ -455,21 +456,6 @@ namespace Microsoft.DotNet.Tools.Complete "n[ormal]", "d[etailed]")); - public static string[] KnownRuntimes = - { - "win10-x86", - "win10-x64", - "win10-arm64", - "osx.10.11-x64", - "centos.7-x64", - "debian.8-x64", - "linuxmint.17-x64", - "opensuse.13.2-x64", - "rhel.7.2-x64", - "ubuntu.14.04-x64", - "ubuntu.16.04-x64", - }; - private static IEnumerable QueryNuGet(string match) { var httpClient = new HttpClient(); diff --git a/src/dotnet/dotnet.csproj b/src/dotnet/dotnet.csproj index 01bf57817..4a6355cd3 100644 --- a/src/dotnet/dotnet.csproj +++ b/src/dotnet/dotnet.csproj @@ -39,7 +39,7 @@ - + diff --git a/test/dotnet.Tests/ParseTests.cs b/test/dotnet.Tests/ParseTests.cs new file mode 100644 index 000000000..b4b5d5c2b --- /dev/null +++ b/test/dotnet.Tests/ParseTests.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using FluentAssertions; +using System.Linq; +using Microsoft.DotNet.Cli.CommandLine; +using Microsoft.DotNet.Tools; +using Microsoft.DotNet.Tools.Common; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.DotNet.Tests +{ + public class AddReferenceParserTests + { + private readonly ITestOutputHelper output; + + public AddReferenceParserTests(ITestOutputHelper output) + { + this.output = output; + } + + [Fact] + public void dotnet_add_reference_has_default_argument_set_to_current_directory() + { + var command = ParserFor.DotnetCommand; + + var result = command.Parse("dotnet add reference my.csproj"); + + output.WriteLine(result.Diagram()); + + result["dotnet"]["add"] + .Arguments + .Should() + .BeEquivalentTo( + PathUtility.EnsureTrailingSlash(Directory.GetCurrentDirectory())); + } + + [Fact] + public void dotnet_add_reference_without_argument_results_in_an_error() + { + var command = ParserFor.DotnetCommand["add"]; + + var result = command.Parse("add reference"); + + output.WriteLine(result.Diagram()); + + result + .Errors + .Select(e => e.Message) + .Should() + .BeEquivalentTo("Required argument missing for command: reference"); + } + } +} \ No newline at end of file diff --git a/test/dotnet.Tests/dotnet.Tests.csproj b/test/dotnet.Tests/dotnet.Tests.csproj index d360368cf..6d62e4124 100644 --- a/test/dotnet.Tests/dotnet.Tests.csproj +++ b/test/dotnet.Tests/dotnet.Tests.csproj @@ -42,5 +42,6 @@ +