From abdf04b54a0363d7cd1e04728117b91fbed37681 Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Thu, 15 Sep 2022 10:05:33 +0200 Subject: [PATCH 01/15] Initial implementation of the test command and API --- Microsoft.TemplateEngine.sln | 15 + .../Commands/Verify/VerifyCommand.cs | 170 +++++++++++ .../Commands/Verify/VerifyCommandArgs.cs | 132 +++++++++ ...rosoft.TemplateEngine.Authoring.CLI.csproj | 5 + .../Program.cs | 3 +- .../Globals.cs | 6 + .../LocalizableStrings.Designer.cs | 72 +++++ .../LocalizableStrings.resx | 124 ++++++++ ...teEngine.Authoring.TemplateVerifier.csproj | 42 +++ .../TemplateVerificationErrorCode.cs | 14 + .../TemplateVerificationException.cs | 29 ++ .../TemplateVerifierOptions.cs | 85 ++++++ .../VerificationEngine.cs | 266 ++++++++++++++++++ .../xlf/LocalizableStrings.cs.xlf | 12 + .../xlf/LocalizableStrings.de.xlf | 12 + .../xlf/LocalizableStrings.es.xlf | 12 + .../xlf/LocalizableStrings.fr.xlf | 12 + .../xlf/LocalizableStrings.it.xlf | 12 + .../xlf/LocalizableStrings.ja.xlf | 12 + .../xlf/LocalizableStrings.ko.xlf | 12 + .../xlf/LocalizableStrings.pl.xlf | 12 + .../xlf/LocalizableStrings.pt-BR.xlf | 12 + .../xlf/LocalizableStrings.ru.xlf | 12 + .../xlf/LocalizableStrings.tr.xlf | 12 + .../xlf/LocalizableStrings.zh-Hans.xlf | 12 + .../xlf/LocalizableStrings.zh-Hant.xlf | 12 + .../AsyncLazy.cs | 30 ++ .../PublicAPI.Unshipped.txt | 5 +- .../VerifyCommandArgsTests.cs | 25 ++ .../VerifyCommandTests.cs | 122 ++++++++ .../StringExtensions.cs | 13 + 31 files changed, 1312 insertions(+), 2 deletions(-) create mode 100644 src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Globals.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationException.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf create mode 100644 src/Microsoft.TemplateEngine.Utils/AsyncLazy.cs create mode 100644 test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandArgsTests.cs create mode 100644 test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs create mode 100644 test/Microsoft.TemplateEngine.TestHelper/StringExtensions.cs diff --git a/Microsoft.TemplateEngine.sln b/Microsoft.TemplateEngine.sln index 928a42175d..756283399d 100644 --- a/Microsoft.TemplateEngine.sln +++ b/Microsoft.TemplateEngine.sln @@ -66,6 +66,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{B794BF86-4185-4DCE-AC86-C27D5D966B9B}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier", "src\Microsoft.TemplateEngine.Authoring.TemplateVerifier\Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj", "{12764D81-61A7-437A-90B6-9F245E43F457}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -388,6 +390,18 @@ Global {2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE}.Release|x64.Build.0 = Release|Any CPU {2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE}.Release|x86.ActiveCfg = Release|Any CPU {2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE}.Release|x86.Build.0 = Release|Any CPU + {12764D81-61A7-437A-90B6-9F245E43F457}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {12764D81-61A7-437A-90B6-9F245E43F457}.Debug|Any CPU.Build.0 = Debug|Any CPU + {12764D81-61A7-437A-90B6-9F245E43F457}.Debug|x64.ActiveCfg = Debug|Any CPU + {12764D81-61A7-437A-90B6-9F245E43F457}.Debug|x64.Build.0 = Debug|Any CPU + {12764D81-61A7-437A-90B6-9F245E43F457}.Debug|x86.ActiveCfg = Debug|Any CPU + {12764D81-61A7-437A-90B6-9F245E43F457}.Debug|x86.Build.0 = Debug|Any CPU + {12764D81-61A7-437A-90B6-9F245E43F457}.Release|Any CPU.ActiveCfg = Release|Any CPU + {12764D81-61A7-437A-90B6-9F245E43F457}.Release|Any CPU.Build.0 = Release|Any CPU + {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x64.ActiveCfg = Release|Any CPU + {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x64.Build.0 = Release|Any CPU + {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x86.ActiveCfg = Release|Any CPU + {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -419,6 +433,7 @@ Global {B0330A2C-3F10-4C46-97DF-13D187564F70} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} {BD758B10-A47F-4159-B9A1-997723AF7349} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B} {2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} + {12764D81-61A7-437A-90B6-9F245E43F457} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6EA1A508-6033-4538-BF98-7F71B4E297AD} diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs new file mode 100644 index 0000000000..c16e21340a --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs @@ -0,0 +1,170 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.CommandLine; +using System.CommandLine.Binding; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.Extensions.Logging; +using Microsoft.TemplateEngine.Authoring.TemplateVerifier; + +namespace Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify +{ + internal class VerifyCommand : ExecutableCommand + { + private const string CommandName = "verify"; + + private readonly Argument _templateNameArgument = new("-n") + { + Name = "template-short-name", + //TODO: localize + Description = "Name of already installed template to be verified.", + // 0 for case where only path is specified + Arity = new ArgumentArity(1, 1) + }; + + private readonly Option _remainingArguments = new Option("--template-args") + { + Description = "Template specific arguments - all joined into single enquoted string. Any needed quotations of actual arguments has to be escaped.", + Arity = new ArgumentArity(0, 1) + }; + + private readonly Option _templatePathOption = new("-p") + { + Name = "--template-path", + //TODO: localize + Description = "Specifies path to the directory with template to be verified.", + }; + + private readonly Option _newCommandPathOption = new("--new-command-assembly") + { + //TODO: localize + Description = "Specifies path to custom assembly implementing the new command.", + //TODO: do we have better way of distinguishing options that might rarely be needed? + // if not - we should probably add a link to more detailed help in the command description (mentioning that online help has additional options) + IsHidden = true + }; + + private readonly Option _templateOutputPathOption = new("-o") + { + Name = "--output", + //TODO: localize + Description = "Specifies path to target directory to output the generated template.", + }; + + private readonly Option _expectationsDirectoryOption = new("-d") + { + Name = "--expectations-directory", + //TODO: localize + Description = "Specifies path to directory with expectation files.", + }; + + private readonly Option _disableDiffToolOption = new("--disable-diff-tool") + { + //TODO: localize + Description = "If set to true - the diff tool won't be automatically started by the Verifier on verification failures.", + }; + + private readonly Option _disableDefaultExcludePatternsOption = new("--disable-default-exclude-patterns") + { + //TODO: localize + Description = "If set to true - all template output files will be verified, unless --exclude-pattern option is used.", + }; + + private readonly Option> _excludePatternOption = new("--exclude-pattern") + { + //TODO: localize + Description = "Specifies pattern(s) defining files to be excluded from verification.", + Arity = new ArgumentArity(0, 999) + }; + + private readonly Option _verifyCommandOutputOption = new("--verify-std") + { + //TODO: localize + Description = "If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.", + }; + + private readonly Option _isCommandExpectedToFailOption = new("--fail-expected") + { + //TODO: localize + Description = "If set to true - 'dotnet new' command is expected to return nonzero return code.", + }; + + public VerifyCommand(ILoggerFactory loggerFactory) + : base(CommandName, "Runs the template with specified arguments and compares the result with expectations files (or creates those if yet don't exist).", loggerFactory) + { + AddArgument(_templateNameArgument); + AddOption(_remainingArguments); + AddOption(_templatePathOption); + AddOption(_newCommandPathOption); + AddOption(_templateOutputPathOption); + AddOption(_expectationsDirectoryOption); + AddOption(_disableDefaultExcludePatternsOption); + AddOption(_excludePatternOption); + AddOption(_verifyCommandOutputOption); + AddOption(_isCommandExpectedToFailOption); + } + + protected override async Task ExecuteAsync(VerifyCommandArgs args, CancellationToken cancellationToken = default) + { + Logger.LogInformation("Running the verification of {templateName}.", args.TemplateName); + + try + { + VerificationEngine engine = new VerificationEngine( + new TemplateVerifierOptions() + { + TemplateName = args.TemplateName, + TemplatePath = args.TemplatePath, + TemplateSpecificArgs = args.TemplateSpecificArgs, + DisableDiffTool = args.DisableDiffTool, + DisableDefaultVerificationExcludePatterns = args.DisableDefaultVerificationExcludePatterns, + VerificationExcludePatterns = args.VerificationExcludePatterns, + DotnetNewCommandAssemblyPath = args.DotnetNewCommandAssemblyPath, + ExpectationsDirectory = args.ExpectationsDirectory, + OutputDirectory = args.OutputDirectory, + VerifyCommandOutput = args.VerifyCommandOutput, + IsCommandExpectedToFail = args.IsCommandExpectedToFail + }, + Logger + ); + await engine.Execute(cancellationToken).ConfigureAwait(false); + return 0; + } + catch (Exception e) + { + Reporter.Error.WriteLine("Verification Failed."); + Logger.LogError(e.Message); + TemplateVerificationException? ex = e as TemplateVerificationException; + return (int)(ex?.TemplateVerificationErrorCode ?? TemplateVerificationErrorCode.InternalError); + } + } + + protected override BinderBase GetModelBinder() => new VerifyModelBinder(this); + + private class VerifyModelBinder : BinderBase + { + private readonly VerifyCommand _verifyCommand; + + internal VerifyModelBinder(VerifyCommand verifyCommand) + { + _verifyCommand = verifyCommand; + } + + protected override VerifyCommandArgs GetBoundValue(BindingContext bindingContext) + { + return new VerifyCommandArgs( + templateName: bindingContext.ParseResult.GetValueForArgument(_verifyCommand._templateNameArgument), + templateSpecificArgs: bindingContext.ParseResult.GetValueForOption(_verifyCommand._remainingArguments), + templatePath: bindingContext.ParseResult.GetValueForOption(_verifyCommand._templatePathOption), + dotnetNewCommandAssemblyPath: bindingContext.ParseResult.GetValueForOption(_verifyCommand._newCommandPathOption), + expectationsDirectory: bindingContext.ParseResult.GetValueForOption(_verifyCommand._expectationsDirectoryOption), + outputDirectory: bindingContext.ParseResult.GetValueForOption(_verifyCommand._templateOutputPathOption), + disableDiffTool: bindingContext.ParseResult.GetValueForOption(_verifyCommand._disableDiffToolOption), + disableDefaultVerificationExcludePatterns: bindingContext.ParseResult.GetValueForOption(_verifyCommand._disableDefaultExcludePatternsOption), + verificationExcludePatterns: bindingContext.ParseResult.GetValueForOption(_verifyCommand._excludePatternOption), + verifyCommandOutput: bindingContext.ParseResult.GetValueForOption(_verifyCommand._verifyCommandOutputOption), + isCommandExpectedToFail: bindingContext.ParseResult.GetValueForOption(_verifyCommand._isCommandExpectedToFailOption)); + } + } + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs new file mode 100644 index 0000000000..45b87ec13d --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs @@ -0,0 +1,132 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text.RegularExpressions; + +namespace Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify +{ + /// + /// Model class representing the arguments of . + /// + internal sealed class VerifyCommandArgs + { + public VerifyCommandArgs( + string? templateName, + string? templatePath, + string? templateSpecificArgs, + string? dotnetNewCommandAssemblyPath, + string? expectationsDirectory, + string? outputDirectory, + bool? disableDiffTool, + bool? disableDefaultVerificationExcludePatterns, + IEnumerable? verificationExcludePatterns, + bool? verifyCommandOutput, + bool isCommandExpectedToFail) + { + TemplateName = templateName; + TemplatePath = templatePath; + TemplateSpecificArgs = TokenizeJoinedArgs(templateSpecificArgs); + DotnetNewCommandAssemblyPath = dotnetNewCommandAssemblyPath; + ExpectationsDirectory = expectationsDirectory; + OutputDirectory = outputDirectory; + DisableDiffTool = disableDiffTool; + DisableDefaultVerificationExcludePatterns = disableDefaultVerificationExcludePatterns; + VerificationExcludePatterns = verificationExcludePatterns; + VerifyCommandOutput = verifyCommandOutput; + IsCommandExpectedToFail = isCommandExpectedToFail; + } + + /// + /// Gets the name of locally installed template. + /// + public string? TemplateName { get; init; } + + /// + /// Gets the path to template.json file or containing directory. + /// + public string? TemplatePath { get; init; } + + /// + /// Gets the path to custom assembly implementing the new command. + /// + public string? DotnetNewCommandAssemblyPath { get; init; } + + /// + /// Gets the template specific arguments. + /// + public IEnumerable TemplateSpecificArgs { get; init; } + + /// + /// Gets the directory with expectation files. + /// + public string? ExpectationsDirectory { get; init; } + + /// + /// Gets the target directory to output the generated template. + /// + public string? OutputDirectory { get; init; } + + /// + /// If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + /// + public bool? DisableDiffTool { get; init; } + + /// + /// If set to true - all template output files will be verified, unless are specified. + /// Otherwise a default exclusions (to be documented - mostly binaries etc.). + /// + public bool? DisableDefaultVerificationExcludePatterns { get; init; } + + /// + /// Set of patterns defining files to be excluded from verification. + /// + public IEnumerable? VerificationExcludePatterns { get; init; } + + /// + /// If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + /// + public bool? VerifyCommandOutput { get; init; } + + /// + /// If set to true - 'dotnet new' command is expected to return nonzero return code. + /// Otherwise a zero error code and no error output is expected. + /// + public bool IsCommandExpectedToFail { get; init; } + + public static IEnumerable TokenizeJoinedArgs(string? joinedArgs) + { + if (string.IsNullOrEmpty(joinedArgs)) + { + return Enumerable.Empty(); + } + + if (!joinedArgs.Contains('"') && !joinedArgs.Contains('\'')) + { + return joinedArgs.Split().Where(s => !string.IsNullOrWhiteSpace(s)); + } + + return Regex.Matches(joinedArgs, @"[\""'].+?[\""']|[^ ]+") + .Cast() + .Select(m => m.Value) + .Select(RemoveEnclosingQuotation) + .Where(s => !string.IsNullOrWhiteSpace(s)); + } + + private static string RemoveEnclosingQuotation(string input) + { + int indexOfLast = input.Length - 1; + + if ( + indexOfLast >= 1 && + (input[0] == '"' && input[indexOfLast] == '"' || input[0] == '\'' && input[indexOfLast] == '\'') + ) + { + return input.Substring(1, indexOfLast - 1); + } + else + { + return input; + } + } + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj b/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj index e7cb35a7e3..77eb733358 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj @@ -16,10 +16,15 @@ + + + + + diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Program.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Program.cs index a64ee1f98f..f9867cfe16 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Program.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Program.cs @@ -4,6 +4,7 @@ using System.CommandLine; using Microsoft.Extensions.Logging; using Microsoft.TemplateEngine.Authoring.CLI.Commands; +using Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify; namespace Microsoft.TemplateEngine.Authoring.CLI { @@ -12,10 +13,10 @@ internal sealed class Program internal static async Task Main(string[] args) { using ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); - ILogger logger = loggerFactory.CreateLogger(); RootCommand rootCommand = new("dotnet-template-authoring"); rootCommand.AddCommand(new LocalizeCommand(loggerFactory)); + rootCommand.AddCommand(new VerifyCommand(loggerFactory)); return await rootCommand.InvokeAsync(args).ConfigureAwait(false); } diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Globals.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Globals.cs new file mode 100644 index 0000000000..66de30e624 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Globals.cs @@ -0,0 +1,6 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs new file mode 100644 index 0000000000..7ea58c6cc0 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class LocalizableStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal LocalizableStrings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.TemplateEngine.Authoring.TemplateVerifier.LocalizableStrings", typeof(LocalizableStrings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to aaa. + /// + internal static string aaa { + get { + return ResourceManager.GetString("aaa", resourceCulture); + } + } + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx new file mode 100644 index 0000000000..b29c2adf72 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + aaa + To be deleted + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj new file mode 100644 index 0000000000..9d450ce684 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj @@ -0,0 +1,42 @@ + + + + Library + $(NETCoreTargetFramework) + A dotnet templating verification engine. + true + enable + enable + + true + + + + + + + + + + + + + + + + + + + True + True + LocalizableStrings.resx + + + + + + ResXFileCodeGenerator + LocalizableStrings.Designer.cs + + + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs new file mode 100644 index 0000000000..cc3e3c816f --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier +{ + public enum TemplateVerificationErrorCode + { + WorkingDirectoryExists = 1, + TemplateDoesNotExist = 1, + InstantiationFailed = 1, + VerificationFailed = 1, + InternalError = 1, + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationException.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationException.cs new file mode 100644 index 0000000000..77bc6a33f1 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationException.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.Serialization; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier +{ + [Serializable] + public class TemplateVerificationException : Exception + { + public TemplateVerificationException(string message, TemplateVerificationErrorCode templateVerificationErrorCode) : base(message) + { + TemplateVerificationErrorCode = templateVerificationErrorCode; + } + + public TemplateVerificationException(string message, TemplateVerificationErrorCode templateVerificationErrorCode, Exception inner) : base(message, inner) + { + TemplateVerificationErrorCode = templateVerificationErrorCode; + } + + protected TemplateVerificationException( + SerializationInfo info, + StreamingContext context) : base(info, context) + { + } + + public TemplateVerificationErrorCode TemplateVerificationErrorCode { get; init; } + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs new file mode 100644 index 0000000000..0f1b8d4435 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs @@ -0,0 +1,85 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text; +using Microsoft.Extensions.Options; +using Microsoft.TemplateEngine.Utils; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier +{ + public delegate void ScrubTemplateFileContent(string filename, StringBuilder content); + + public delegate Task VerifyFileContent(string filename, AsyncLazy content, Task defaultVarifierAction); + + public class TemplateVerifierOptions : IOptions + { + /// + /// Gets the name of locally installed template. + /// + public string? TemplateName { get; init; } + + /// + /// Gets the path to template.json file or containing directory. + /// + public string? TemplatePath { get; init; } + + /// + /// Gets the path to custom assembly implementing the new command. + /// + public string? DotnetNewCommandAssemblyPath { get; init; } + + /// + /// Gets the template specific arguments. + /// + public IEnumerable? TemplateSpecificArgs { get; init; } + + /// + /// Gets the directory with expectation files. + /// + public string? ExpectationsDirectory { get; init; } + + /// + /// If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + /// + public bool? VerifyCommandOutput { get; init; } + + /// + /// If set to true - 'dotnet new' command is expected to return nonzero return code. + /// Otherwise a zero error code and no error output is expected. + /// + public bool? IsCommandExpectedToFail { get; init; } + + /// + /// If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + /// + public bool? DisableDiffTool { get; init; } + + /// + /// If set to true - all template output files will be verified, unless are specified. + /// Otherwise a default exclusions (to be documented - mostly binaries etc.). + /// + public bool? DisableDefaultVerificationExcludePatterns { get; init; } + + /// + /// Set of patterns defining files to be excluded from verification. + /// + public IEnumerable? VerificationExcludePatterns { get; init; } + + /// + /// Gets the target directory to output the generated template. + /// + public string? OutputDirectory { get; init; } + + /// + /// Gets the delegate that performs custom scrubbing of template output contents before verifications. + /// + public ScrubTemplateFileContent? CustomScrubber { get; init; } + + /// + /// Gets the delegate that performs custom verification of template output contents. + /// + public VerifyFileContent? CustomVerifier { get; init; } + + TemplateVerifierOptions IOptions.Value => this; + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs new file mode 100644 index 0000000000..520cca6464 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs @@ -0,0 +1,266 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Reflection; +using System.Text; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Microsoft.TemplateEngine.TestHelper.Commands; +using Microsoft.TemplateEngine.Utils; +using Xunit.Abstractions; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier +{ + public class VerificationEngine + { + private static readonly IReadOnlyList _defaultVerificationExcludePatterns = new List() + { + @"obj/*", + @"obj\*", + @"bin/*", + @"bin\*", + "*.exe", + "*.dll", + "*.", + "*.exe", + }; + + private readonly TemplateVerifierOptions _options; + private readonly /*ILogger*/ILogger _logger; + + public VerificationEngine(IOptions optionsAccessor, ILogger logger) + { + if (optionsAccessor == null) + { + throw new ArgumentNullException(nameof(optionsAccessor)); + } + + _options = optionsAccessor.Value; + _logger = logger; + } + + public async Task Execute(CancellationToken cancellationToken = default) + { + if (!string.IsNullOrEmpty(_options.TemplatePath)) + { + throw new TemplateVerificationException("Custom template path not yet supported.", TemplateVerificationErrorCode.InternalError); + } + + if (string.IsNullOrEmpty(_options.TemplateName)) + { + throw new TemplateVerificationException("Template name not supplied - but custom template path is not yet supported.", TemplateVerificationErrorCode.InternalError); + } + + // Create temp folder and instantiate there + string workingDir = _options.OutputDirectory ?? Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + if (Directory.Exists(workingDir) && Directory.EnumerateFileSystemEntries(workingDir).Any()) + { + throw new TemplateVerificationException("Working directory already exists and is not empty.", TemplateVerificationErrorCode.WorkingDirectoryExists); + } + + Directory.CreateDirectory(workingDir); + + List cmdArgs = new(); + if (!string.IsNullOrEmpty(_options.DotnetNewCommandAssemblyPath)) + { + cmdArgs.Add(_options.DotnetNewCommandAssemblyPath); + } + cmdArgs.Add("new"); + cmdArgs.Add(_options.TemplateName); + if (_options.TemplateSpecificArgs != null) + { + cmdArgs.AddRange(_options.TemplateSpecificArgs); + } + cmdArgs.Add("--debug:ephemeral-hive"); + // let's make sure the template outputs are named deterministically + cmdArgs.Add("-n"); + cmdArgs.Add(_options.TemplateName); + + // TODO: export and use impl from sdk + CommandResult commandResult = + new DotnetCommand(new LoggerProxy(_logger), "dotnet", cmdArgs.ToArray()) + .WithWorkingDirectory(workingDir) + .Execute(); + + if (_options.IsCommandExpectedToFail ?? false) + { + commandResult.Should().Fail(); + } + else + { + var assertion = commandResult.Should().Pass(); + // We do not expect stderr in passing command. + // However if verification of stdout and stderr is opted-in - we will let that verification validate the stderr content + if (!(_options.VerifyCommandOutput ?? false)) + { + assertion.And.NotHaveStdErr(); + } + } + + await VerifyResult(_options, commandResult).ConfigureAwait(false); + } + + private static void DummyMethod() + { } + + private async Task VerifyResult(TemplateVerifierOptions args, CommandResult commandResult) + { + // Customize diff output of verifier + VerifyDiffPlex.Initialize(OutputType.Compact); + + UsesVerifyAttribute a = new UsesVerifyAttribute(); + // https://github.com/VerifyTests/Verify/blob/d8cbe38f527d6788ecadd6205c82803bec3cdfa6/src/Verify.Xunit/Verifier.cs#L10 + // need to simulate execution from tests + var v = DummyMethod; + MethodInfo mi = v.Method; + a.Before(mi); + + List exclusionsList = (args.DisableDefaultVerificationExcludePatterns ?? false) + ? new() + : new(_defaultVerificationExcludePatterns); + + if (args.VerificationExcludePatterns != null) + { + exclusionsList.AddRange(args.VerificationExcludePatterns); + } + + List globs = exclusionsList.Select(pattern => Glob.Parse(pattern)).ToList(); + + IEnumerable filesToVerify = + Directory.EnumerateFiles(commandResult.StartInfo.WorkingDirectory, "*", SearchOption.AllDirectories); + if (_options.VerifyCommandOutput ?? false) + { + filesToVerify = filesToVerify.Concat(SpecialFiles.FileNames); + } + + List verificationErrors = new List(); + + // run verification + foreach (string filePath in filesToVerify) + { + if (globs.Any(g => g.IsMatch(filePath))) + { + continue; + } + + //TODO: this wont be needed + VerifierSettings.DerivePathInfo( + (sourceFile, projectDirectory, type, method) => new( + directory: args.ExpectationsDirectory ?? "VerifyExpectations", + typeName: args.TemplateName, + //TODO: would this actually be needed - then we'd need to encode relative path to file here as well + // (as single template can have multiple files with same name) + methodName: Path.GetFileName(filePath))); + try + { + SettingsTask defaultVerifyTask; + + if (SpecialFiles.IsSpecialFile(filePath)) + { + defaultVerifyTask = Verifier.Verify(SpecialFiles.IsStdOut(filePath) ? commandResult.StdOut : commandResult.StdErr); + } + else + { + defaultVerifyTask = Verifier.VerifyFile(filePath); + } + + if (_options.CustomScrubber != null) + { + defaultVerifyTask = defaultVerifyTask.AddScrubber(sb => _options.CustomScrubber(filePath, sb)); + } + + if (_options.DisableDiffTool ?? false) + { + defaultVerifyTask = defaultVerifyTask.DisableDiff(); + } + + Task verifyTask = _options.CustomVerifier != null + ? _options.CustomVerifier(filePath, GetVerificationContent(filePath, commandResult), defaultVerifyTask) + : defaultVerifyTask; + + await verifyTask.ConfigureAwait(false); + } + //TODO: VerifyException is not public now - so either use reflection or get the Verify package updated + //catch (VerifyException e) + //{ + // throw; + //} + catch (Exception e) + { + if (e.GetType().Name == "VerifyException") + { + verificationErrors.Add(e.Message); + } + else + { + _logger.LogError(e, "Error encountered"); + throw; + } + } + } + + if (verificationErrors.Any()) + { + string doubleNewLine = Environment.NewLine + Environment.NewLine; + throw new TemplateVerificationException( + "Verification Failed." + doubleNewLine + string.Join(doubleNewLine, verificationErrors), + TemplateVerificationErrorCode.VerificationFailed); + } + } + + private AsyncLazy GetVerificationContent(string filePath, CommandResult commandResult) + { + return new AsyncLazy(async () => + { + string content; + if (SpecialFiles.IsSpecialFile(filePath)) + { + content = SpecialFiles.IsStdOut(filePath) ? commandResult.StdOut : commandResult.StdErr; + } + else + { + content = await File.ReadAllTextAsync(filePath).ConfigureAwait(false); + } + + if (_options.CustomScrubber != null) + { + StringBuilder sb = new StringBuilder(content); + _options.CustomScrubber(filePath, sb); + content = sb.ToString(); + } + + return content; + }); + } + + private static class SpecialFiles + { + public static readonly string[] FileNames = { StdOut, StdErr }; + + private const string StdOut = "StdOut"; + private const string StdErr = "StdErr"; + + public static bool IsSpecialFile(string filePath) + { + return FileNames.Contains(filePath, StringComparer.OrdinalIgnoreCase); + } + + public static bool IsStdOut(string filePath) => filePath.Equals(StdOut, StringComparison.OrdinalIgnoreCase); + + public static bool IsStdErr(string filePath) => filePath.Equals(StdErr, StringComparison.OrdinalIgnoreCase); + } + + private class LoggerProxy : ITestOutputHelper + { + private readonly ILogger _logger; + + public LoggerProxy(ILogger logger) => _logger = logger; + + public void WriteLine(string message) => _logger.LogInformation(message); + + public void WriteLine(string format, params object[] args) => _logger.LogInformation(format, args); + } + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf new file mode 100644 index 0000000000..75e9fc84e1 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf new file mode 100644 index 0000000000..2fb061101d --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf new file mode 100644 index 0000000000..a75a48f232 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf new file mode 100644 index 0000000000..f84204ab79 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf new file mode 100644 index 0000000000..1dbc1db926 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf new file mode 100644 index 0000000000..ec93a33d40 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf new file mode 100644 index 0000000000..cd44dca432 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf new file mode 100644 index 0000000000..a7d351cab0 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf new file mode 100644 index 0000000000..b6731553c6 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf new file mode 100644 index 0000000000..32811f1201 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf new file mode 100644 index 0000000000..956b2b4538 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf new file mode 100644 index 0000000000..29f8e5c3ec --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf new file mode 100644 index 0000000000..872d00dd57 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf @@ -0,0 +1,12 @@ + + + + + + aaa + aaa + To be deleted + + + + \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Utils/AsyncLazy.cs b/src/Microsoft.TemplateEngine.Utils/AsyncLazy.cs new file mode 100644 index 0000000000..7616ff17f3 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Utils/AsyncLazy.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.TemplateEngine.Utils +{ + /// + /// Provides support for asynchronous lazy initialization. + /// + /// The type to be lazily initialized. + public class AsyncLazy : Lazy> + { + // inspired by https://devblogs.microsoft.com/pfxteam/asynclazyt/ + public AsyncLazy(Func valueFactory) + : base(() => Task.Factory.StartNew(valueFactory, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default)) + { } + + public AsyncLazy(Func> taskFactory) + : base(() => Task.Factory.StartNew( + () => taskFactory(), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default) + .Unwrap()) + { } + + public TaskAwaiter GetAwaiter() { return Value.GetAwaiter(); } + } +} diff --git a/src/Microsoft.TemplateEngine.Utils/PublicAPI.Unshipped.txt b/src/Microsoft.TemplateEngine.Utils/PublicAPI.Unshipped.txt index 5f282702bb..14d64ba4ce 100644 --- a/src/Microsoft.TemplateEngine.Utils/PublicAPI.Unshipped.txt +++ b/src/Microsoft.TemplateEngine.Utils/PublicAPI.Unshipped.txt @@ -1 +1,4 @@ - \ No newline at end of file +Microsoft.TemplateEngine.Utils.AsyncLazy +Microsoft.TemplateEngine.Utils.AsyncLazy.AsyncLazy(System.Func!>! taskFactory) -> void +Microsoft.TemplateEngine.Utils.AsyncLazy.AsyncLazy(System.Func! valueFactory) -> void +Microsoft.TemplateEngine.Utils.AsyncLazy.GetAwaiter() -> System.Runtime.CompilerServices.TaskAwaiter \ No newline at end of file diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandArgsTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandArgsTests.cs new file mode 100644 index 0000000000..9cdd0aa879 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandArgsTests.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using FluentAssertions; +using Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify; + +namespace Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests +{ + public class VerifyCommandArgsTests + { + [Theory] + [InlineData(null, new string[] { })] + [InlineData(" ", new string[] { })] + [InlineData(" a b c", new string[] { "a", "b", "c" })] + [InlineData(" abc ", new string[] { "abc" })] + [InlineData("a \"b c \" d ", new string[] { "a", "b c ", "d" })] + [InlineData("aa \" bb cc \"dd", new string[] { "aa", " bb cc ", "dd" })] + [InlineData("aa q= 'bb cc'dd", new string[] { "aa", "q=", "bb cc", "dd" })] + public void OnTokenizeJoinedArgsResultIsExpected(string? input, IEnumerable expectedOutput) + { + var result = VerifyCommandArgs.TokenizeJoinedArgs(input); + result.Should().BeEquivalentTo(expectedOutput, options => options.WithStrictOrdering()); + } + } +} diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs new file mode 100644 index 0000000000..5be340b8f2 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs @@ -0,0 +1,122 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using FluentAssertions; +using Microsoft.TemplateEngine.Authoring.TemplateVerifier; +using Microsoft.TemplateEngine.TestHelper; +using Microsoft.TemplateEngine.TestHelper.Commands; +using Xunit.Abstractions; + +namespace Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests +{ + [UsesVerify] + public class VerifyCommandTests + { + private readonly ITestOutputHelper _log; + + public VerifyCommandTests(ITestOutputHelper log) + { + _log = log; + } + + [Fact] + public void VerifyCommandFullDevLoop() + { + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + string templateDir = "path with spaces"; + + var cmd = new BasicCommand( + _log, + "dotnet", + Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"), + "verify", + "console", + "--template-args", + "--use-program-main -o \"" + templateDir + "\" --no-restore", + "--verify-std", + "-o", + workingDir, + "--expectations-directory", + expectationsDir); + + cmd.Execute() + .Should() + .ExitWith((int)TemplateVerificationErrorCode.VerificationFailed) + //.And.HaveStdOutContaining("Run the verification work.") + //.And.NotHaveStdErr(); + .And.HaveStdErrContaining("Verification Failed."); + + // Assert template created + Directory.Exists(Path.Combine(workingDir, templateDir)).Should().BeTrue(); + File.Exists(Path.Combine(workingDir, templateDir, "console.csproj")).Should().BeTrue(); + File.Exists(Path.Combine(workingDir, templateDir, "Program.cs")).Should().BeTrue(); + + // Assert verification files created + Directory.Exists(expectationsDir).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "console.console.csproj.received.csproj")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "console.Program.cs.received.cs")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "console.StdOut.received.txt")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "console.StdErr.received.txt")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeTrue(); + Directory.GetFiles(expectationsDir).Length.Should().Be(8); + + File.ReadAllText(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeEmpty(); + File.ReadAllText(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeEmpty(); + File.ReadAllText(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeEmpty(); + File.ReadAllText(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeEmpty(); + File.ReadAllText(Path.Combine(expectationsDir, "console.console.csproj.received.csproj").UnixifyLineBreaks()).Should() + .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "console.csproj")).UnixifyLineBreaks()); + File.ReadAllText(Path.Combine(expectationsDir, "console.Program.cs.received.cs").UnixifyLineBreaks()).Should() + .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "Program.cs")).UnixifyLineBreaks()); + + // Accept changes + File.Delete(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")); + File.Delete(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")); + File.Delete(Path.Combine(expectationsDir, "console.StdOut.verified.txt")); + File.Delete(Path.Combine(expectationsDir, "console.StdErr.verified.txt")); + File.Move( + Path.Combine(expectationsDir, "console.console.csproj.received.csproj"), + Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")); + File.Move( + Path.Combine(expectationsDir, "console.Program.cs.received.cs"), + Path.Combine(expectationsDir, "console.Program.cs.verified.cs")); + File.Move( + Path.Combine(expectationsDir, "console.StdOut.received.txt"), + Path.Combine(expectationsDir, "console.StdOut.verified.txt")); + File.Move( + Path.Combine(expectationsDir, "console.StdErr.received.txt"), + Path.Combine(expectationsDir, "console.StdErr.verified.txt")); + + // And run again same scenario - verification should succeed now + string workingDir2 = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + var cmd2 = new BasicCommand( + _log, + "dotnet", + Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"), + "verify", + "console", + "--template-args", + "--use-program-main -o \"" + templateDir + "\" --no-restore", + "--verify-std", + "-o", + workingDir2, + "--expectations-directory", + expectationsDir); + + cmd2.Execute() + .Should() + .Pass() + .And.HaveStdOutContaining("Running the verification of console.") + .And.NotHaveStdErr(); + + Directory.Delete(workingDir, true); + Directory.Delete(workingDir2, true); + Directory.Delete(expectationsDir, true); + } + } +} diff --git a/test/Microsoft.TemplateEngine.TestHelper/StringExtensions.cs b/test/Microsoft.TemplateEngine.TestHelper/StringExtensions.cs new file mode 100644 index 0000000000..3111049d14 --- /dev/null +++ b/test/Microsoft.TemplateEngine.TestHelper/StringExtensions.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.TemplateEngine.TestHelper +{ + public static class StringExtensions + { + public static string UnixifyLineBreaks(this string input) + { + return input.Replace("\r\n", "\n"); + } + } +} From 8d398fe2dafc8619f80940a4402bb59b2556996b Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Thu, 15 Sep 2022 15:22:17 +0200 Subject: [PATCH 02/15] Disable diff tool in CI --- .../Commands/Verify/VerifyCommand.cs | 1 + .../VerifyCommandTests.cs | 25 ++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs index c16e21340a..28d205bf3c 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs @@ -98,6 +98,7 @@ public VerifyCommand(ILoggerFactory loggerFactory) AddOption(_newCommandPathOption); AddOption(_templateOutputPathOption); AddOption(_expectationsDirectoryOption); + AddOption(_disableDiffToolOption); AddOption(_disableDefaultExcludePatternsOption); AddOption(_excludePatternOption); AddOption(_verifyCommandOutputOption); diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs index 5be340b8f2..fe0048775e 100644 --- a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs @@ -39,13 +39,12 @@ public void VerifyCommandFullDevLoop() "-o", workingDir, "--expectations-directory", - expectationsDir); + expectationsDir, + "--disable-diff-tool"); cmd.Execute() .Should() .ExitWith((int)TemplateVerificationErrorCode.VerificationFailed) - //.And.HaveStdOutContaining("Run the verification work.") - //.And.NotHaveStdErr(); .And.HaveStdErrContaining("Verification Failed."); // Assert template created @@ -56,19 +55,21 @@ public void VerifyCommandFullDevLoop() // Assert verification files created Directory.Exists(expectationsDir).Should().BeTrue(); File.Exists(Path.Combine(expectationsDir, "console.console.csproj.received.csproj")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeTrue(); File.Exists(Path.Combine(expectationsDir, "console.Program.cs.received.cs")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeTrue(); File.Exists(Path.Combine(expectationsDir, "console.StdOut.received.txt")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeTrue(); File.Exists(Path.Combine(expectationsDir, "console.StdErr.received.txt")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeTrue(); - Directory.GetFiles(expectationsDir).Length.Should().Be(8); + // .verified files are only created when diff tool is used - that is however turned off in CI + //File.Exists(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeTrue(); + //File.Exists(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeTrue(); + //File.Exists(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeTrue(); + //File.Exists(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeTrue(); + Directory.GetFiles(expectationsDir).Length.Should().Be(4); - File.ReadAllText(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeEmpty(); - File.ReadAllText(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeEmpty(); - File.ReadAllText(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeEmpty(); - File.ReadAllText(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeEmpty(); + // .verified files are only created when diff tool is used - that is however turned off in CI + //File.ReadAllText(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeEmpty(); + //File.ReadAllText(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeEmpty(); + //File.ReadAllText(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeEmpty(); + //File.ReadAllText(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeEmpty(); File.ReadAllText(Path.Combine(expectationsDir, "console.console.csproj.received.csproj").UnixifyLineBreaks()).Should() .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "console.csproj")).UnixifyLineBreaks()); File.ReadAllText(Path.Combine(expectationsDir, "console.Program.cs.received.cs").UnixifyLineBreaks()).Should() From 48320b70410ce5837dbe806afadbaf0dd92be057 Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Thu, 22 Sep 2022 18:24:54 +0200 Subject: [PATCH 03/15] Use new Verifier, Add verification options --- eng/dependabot/Packages.props | 2 +- .../Commands/Verify/VerifyCommand.cs | 44 ++++- .../Commands/Verify/VerifyCommandArgs.cs | 27 ++- ...teEngine.Authoring.TemplateVerifier.csproj | 2 +- .../TemplateVerifierOptions.cs | 40 +++- .../UniqueForOption.cs | 17 ++ .../VerificationEngine.cs | 179 ++++++++++-------- .../VerifyCommandTests.cs | 58 +++--- .../VerifySettingsFixture.cs | 5 +- 9 files changed, 253 insertions(+), 121 deletions(-) create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/UniqueForOption.cs diff --git a/eng/dependabot/Packages.props b/eng/dependabot/Packages.props index a1d7c6cd52..00b8c1f170 100644 --- a/eng/dependabot/Packages.props +++ b/eng/dependabot/Packages.props @@ -31,7 +31,7 @@ - + diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs index 28d205bf3c..cbd9ca3659 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs @@ -3,6 +3,7 @@ using System.CommandLine; using System.CommandLine.Binding; +using System.CommandLine.Parsing; using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Logging; using Microsoft.TemplateEngine.Authoring.TemplateVerifier; @@ -89,6 +90,14 @@ internal class VerifyCommand : ExecutableCommand Description = "If set to true - 'dotnet new' command is expected to return nonzero return code.", }; + private readonly Option> _uniqueForOption = new("--unique-for") + { + //TODO: localize + Description = "Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated.", + Arity = new ArgumentArity(0, 999), + AllowMultipleArgumentsPerToken = true, + }; + public VerifyCommand(ILoggerFactory loggerFactory) : base(CommandName, "Runs the template with specified arguments and compares the result with expectations files (or creates those if yet don't exist).", loggerFactory) { @@ -103,6 +112,12 @@ public VerifyCommand(ILoggerFactory loggerFactory) AddOption(_excludePatternOption); AddOption(_verifyCommandOutputOption); AddOption(_isCommandExpectedToFailOption); + FromAmongCaseInsensitive( + _uniqueForOption, + System.Enum.GetNames(typeof(UniqueForOption)) + .Where(v => !v.Equals(UniqueForOption.None.ToString(), StringComparison.OrdinalIgnoreCase)) + .ToArray()); + AddOption(_uniqueForOption); } protected override async Task ExecuteAsync(VerifyCommandArgs args, CancellationToken cancellationToken = default) @@ -124,7 +139,8 @@ protected override async Task ExecuteAsync(VerifyCommandArgs args, Cancella ExpectationsDirectory = args.ExpectationsDirectory, OutputDirectory = args.OutputDirectory, VerifyCommandOutput = args.VerifyCommandOutput, - IsCommandExpectedToFail = args.IsCommandExpectedToFail + IsCommandExpectedToFail = args.IsCommandExpectedToFail, + UniqueFor = args.UniqueFor, }, Logger ); @@ -142,6 +158,29 @@ protected override async Task ExecuteAsync(VerifyCommandArgs args, Cancella protected override BinderBase GetModelBinder() => new VerifyModelBinder(this); + /// + /// Case insensitive version for . + /// + private static void FromAmongCaseInsensitive(Option> option, string[]? allowedValues = null, string? allowedHiddenValue = null) + { + allowedValues ??= Array.Empty(); + option.AddValidator(optionResult => ValidateAllowedValues(optionResult, allowedValues, allowedHiddenValue)); + option.AddCompletions(allowedValues); + } + + private static void ValidateAllowedValues(OptionResult optionResult, string[] allowedValues, string? allowedHiddenValue = null) + { + var invalidArguments = optionResult.Tokens.Where(token => !allowedValues.Append(allowedHiddenValue).Contains(token.Value, StringComparer.OrdinalIgnoreCase)).ToList(); + if (invalidArguments.Any()) + { + //TODO: localize + optionResult.ErrorMessage = string.Format( + "Argument(s) {0} are not recognized. Must be one of: {1}.", + string.Join(", ", invalidArguments.Select(arg => $"'{arg.Value}'")), + string.Join(", ", allowedValues.Select(allowedValue => $"'{allowedValue}'"))); + } + } + private class VerifyModelBinder : BinderBase { private readonly VerifyCommand _verifyCommand; @@ -164,7 +203,8 @@ protected override VerifyCommandArgs GetBoundValue(BindingContext bindingContext disableDefaultVerificationExcludePatterns: bindingContext.ParseResult.GetValueForOption(_verifyCommand._disableDefaultExcludePatternsOption), verificationExcludePatterns: bindingContext.ParseResult.GetValueForOption(_verifyCommand._excludePatternOption), verifyCommandOutput: bindingContext.ParseResult.GetValueForOption(_verifyCommand._verifyCommandOutputOption), - isCommandExpectedToFail: bindingContext.ParseResult.GetValueForOption(_verifyCommand._isCommandExpectedToFailOption)); + isCommandExpectedToFail: bindingContext.ParseResult.GetValueForOption(_verifyCommand._isCommandExpectedToFailOption), + uniqueForOptions: bindingContext.ParseResult.GetValueForOption(_verifyCommand._uniqueForOption)); } } } diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs index 45b87ec13d..e5d1407451 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Text.RegularExpressions; +using Microsoft.TemplateEngine.Authoring.TemplateVerifier; namespace Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify { @@ -21,7 +22,8 @@ public VerifyCommandArgs( bool? disableDefaultVerificationExcludePatterns, IEnumerable? verificationExcludePatterns, bool? verifyCommandOutput, - bool isCommandExpectedToFail) + bool isCommandExpectedToFail, + IEnumerable? uniqueForOptions) { TemplateName = templateName; TemplatePath = templatePath; @@ -34,6 +36,7 @@ public VerifyCommandArgs( VerificationExcludePatterns = verificationExcludePatterns; VerifyCommandOutput = verifyCommandOutput; IsCommandExpectedToFail = isCommandExpectedToFail; + UniqueFor = FromOptionTokens(uniqueForOptions); } /// @@ -93,6 +96,11 @@ public VerifyCommandArgs( /// public bool IsCommandExpectedToFail { get; init; } + /// + /// Gets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + /// + public UniqueForOption? UniqueFor { get; init; } + public static IEnumerable TokenizeJoinedArgs(string? joinedArgs) { if (string.IsNullOrEmpty(joinedArgs)) @@ -128,5 +136,22 @@ private static string RemoveEnclosingQuotation(string input) return input; } } + + private static UniqueForOption? FromOptionTokens(IEnumerable? tokens) + { + if (tokens == null) + { + return null; + } + + UniqueForOption result = UniqueForOption.None; + + foreach (string token in tokens) + { + result |= Enum.Parse(token, true); + } + + return result; + } } } diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj index 9d450ce684..c86162bdd3 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj @@ -15,7 +15,7 @@ - + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs index 0f1b8d4435..b9d58f1b8f 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs @@ -3,13 +3,34 @@ using System.Text; using Microsoft.Extensions.Options; -using Microsoft.TemplateEngine.Utils; namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier { - public delegate void ScrubTemplateFileContent(string filename, StringBuilder content); - - public delegate Task VerifyFileContent(string filename, AsyncLazy content, Task defaultVarifierAction); + public class ScrubbersDefinition + { + public ScrubbersDefinition() { } + + public ScrubbersDefinition(Action scrubber, string? extension = null) + { + this.AddScrubber(scrubber, extension); + } + + public Dictionary> ScrubersByExtension { get; private set; } = new Dictionary>(); + + public Action? GeneralScrubber { get; private set; } + + public void AddScrubber(Action scrubber, string? extension = null) + { + if (extension == null) + { + GeneralScrubber += scrubber; + } + else + { + ScrubersByExtension[extension] = scrubber; + } + } + } public class TemplateVerifierOptions : IOptions { @@ -71,14 +92,19 @@ public class TemplateVerifierOptions : IOptions public string? OutputDirectory { get; init; } /// - /// Gets the delegate that performs custom scrubbing of template output contents before verifications. + /// Gets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + /// + public UniqueForOption? UniqueFor { get; init; } + + /// + /// Gets the delegates that perform custom scrubbing of template output contents before verifications. /// - public ScrubTemplateFileContent? CustomScrubber { get; init; } + public ScrubbersDefinition? CustomScrubbers { get; init; } /// /// Gets the delegate that performs custom verification of template output contents. /// - public VerifyFileContent? CustomVerifier { get; init; } + public Func? CustomVerifyDirectory { get; init; } TemplateVerifierOptions IOptions.Value => this; } diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/UniqueForOption.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/UniqueForOption.cs new file mode 100644 index 0000000000..d6788bb4ac --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/UniqueForOption.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier +{ + [Flags] + public enum UniqueForOption + { + None = 0, + Architecture = 1, + OsPlatform = 2, + Runtime = 4, + RuntimeAndVersion = 8, + TargetFramework = 16, + TargetFrameworkAndVersion = 32 + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs index 520cca6464..8c4834be6e 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System.Reflection; -using System.Text; +using System.Text.RegularExpressions; using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -102,6 +102,17 @@ public async Task Execute(CancellationToken cancellationToken = default) await VerifyResult(_options, commandResult).ConfigureAwait(false); } + private static string EncodeArgsAsPath(IEnumerable? args) + { + if (args == null || !args.Any()) + { + return string.Empty; + } + + Regex r = new Regex(string.Format("[{0}]", Regex.Escape(new string(Path.GetInvalidFileNameChars())))); + return r.Replace(string.Join('#', args), string.Empty); + } + private static void DummyMethod() { } @@ -128,120 +139,126 @@ private async Task VerifyResult(TemplateVerifierOptions args, CommandResult comm List globs = exclusionsList.Select(pattern => Glob.Parse(pattern)).ToList(); - IEnumerable filesToVerify = - Directory.EnumerateFiles(commandResult.StartInfo.WorkingDirectory, "*", SearchOption.AllDirectories); if (_options.VerifyCommandOutput ?? false) { - filesToVerify = filesToVerify.Concat(SpecialFiles.FileNames); + if (Directory.Exists(Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir))) + { + throw new TemplateVerificationException( + string.Format( + "Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case", + SpecialFiles.StandardStreamsDir), + TemplateVerificationErrorCode.InternalError); + } + + Directory.CreateDirectory(Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir)); + + await File.WriteAllTextAsync( + Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdOut), + commandResult.StdOut) + .ConfigureAwait(false); + + await File.WriteAllTextAsync( + Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdErr), + commandResult.StdErr) + .ConfigureAwait(false); } - List verificationErrors = new List(); + Verifier.DerivePathInfo( + (sourceFile, projectDirectory, type, method) => new( + directory: args.ExpectationsDirectory ?? "VerifyExpectations", + typeName: args.TemplateName, + methodName: EncodeArgsAsPath(args.TemplateSpecificArgs))); - // run verification - foreach (string filePath in filesToVerify) + try { - if (globs.Any(g => g.IsMatch(filePath))) - { - continue; - } + SettingsTask defaultVerifyTask = Verifier.VerifyDirectory( + commandResult.StartInfo.WorkingDirectory, + (filePath) => !globs.Any(g => g.IsMatch(filePath))); - //TODO: this wont be needed - VerifierSettings.DerivePathInfo( - (sourceFile, projectDirectory, type, method) => new( - directory: args.ExpectationsDirectory ?? "VerifyExpectations", - typeName: args.TemplateName, - //TODO: would this actually be needed - then we'd need to encode relative path to file here as well - // (as single template can have multiple files with same name) - methodName: Path.GetFileName(filePath))); - try + if (_options.CustomScrubbers != null) { - SettingsTask defaultVerifyTask; - - if (SpecialFiles.IsSpecialFile(filePath)) + if (_options.CustomScrubbers.GeneralScrubber != null) { - defaultVerifyTask = Verifier.Verify(SpecialFiles.IsStdOut(filePath) ? commandResult.StdOut : commandResult.StdErr); - } - else - { - defaultVerifyTask = Verifier.VerifyFile(filePath); + defaultVerifyTask = defaultVerifyTask.AddScrubber(_options.CustomScrubbers.GeneralScrubber); } - if (_options.CustomScrubber != null) + foreach (var pair in _options.CustomScrubbers.ScrubersByExtension) { - defaultVerifyTask = defaultVerifyTask.AddScrubber(sb => _options.CustomScrubber(filePath, sb)); + defaultVerifyTask = defaultVerifyTask.AddScrubber(pair.Key, pair.Value); } + } - if (_options.DisableDiffTool ?? false) + if ((_options.UniqueFor ?? UniqueForOption.None) != UniqueForOption.None) + { + foreach (UniqueForOption value in Enum.GetValues(typeof(UniqueForOption))) { - defaultVerifyTask = defaultVerifyTask.DisableDiff(); + if ((_options.UniqueFor & value) == value) + { + switch (value) + { + case UniqueForOption.None: + break; + case UniqueForOption.Architecture: + defaultVerifyTask = defaultVerifyTask.UniqueForArchitecture(); + break; + case UniqueForOption.OsPlatform: + defaultVerifyTask = defaultVerifyTask.UniqueForOSPlatform(); + break; + case UniqueForOption.Runtime: + defaultVerifyTask = defaultVerifyTask.UniqueForRuntime(); + break; + case UniqueForOption.RuntimeAndVersion: + defaultVerifyTask = defaultVerifyTask.UniqueForRuntimeAndVersion(); + break; + case UniqueForOption.TargetFramework: + defaultVerifyTask = defaultVerifyTask.UniqueForTargetFramework(); + break; + case UniqueForOption.TargetFrameworkAndVersion: + defaultVerifyTask = defaultVerifyTask.UniqueForTargetFrameworkAndVersion(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } } - - Task verifyTask = _options.CustomVerifier != null - ? _options.CustomVerifier(filePath, GetVerificationContent(filePath, commandResult), defaultVerifyTask) - : defaultVerifyTask; - - await verifyTask.ConfigureAwait(false); } - //TODO: VerifyException is not public now - so either use reflection or get the Verify package updated - //catch (VerifyException e) - //{ - // throw; - //} - catch (Exception e) + + if (_options.DisableDiffTool ?? false) { - if (e.GetType().Name == "VerifyException") - { - verificationErrors.Add(e.Message); - } - else - { - _logger.LogError(e, "Error encountered"); - throw; - } + defaultVerifyTask = defaultVerifyTask.DisableDiff(); } - } - if (verificationErrors.Any()) - { - string doubleNewLine = Environment.NewLine + Environment.NewLine; - throw new TemplateVerificationException( - "Verification Failed." + doubleNewLine + string.Join(doubleNewLine, verificationErrors), - TemplateVerificationErrorCode.VerificationFailed); - } - } + Task verifyTask = _options.CustomVerifyDirectory != null + ? _options.CustomVerifyDirectory(commandResult.StartInfo.WorkingDirectory) + : defaultVerifyTask; - private AsyncLazy GetVerificationContent(string filePath, CommandResult commandResult) - { - return new AsyncLazy(async () => + await verifyTask.ConfigureAwait(false); + } + catch (Exception e) { - string content; - if (SpecialFiles.IsSpecialFile(filePath)) + if (e is TemplateVerificationException) { - content = SpecialFiles.IsStdOut(filePath) ? commandResult.StdOut : commandResult.StdErr; + throw; } - else + if (e.GetType().Name == "VerifyException") { - content = await File.ReadAllTextAsync(filePath).ConfigureAwait(false); + throw new TemplateVerificationException(e.Message, TemplateVerificationErrorCode.VerificationFailed); } - - if (_options.CustomScrubber != null) + else { - StringBuilder sb = new StringBuilder(content); - _options.CustomScrubber(filePath, sb); - content = sb.ToString(); + _logger.LogError(e, "Unexpected error encountered"); + throw; } - - return content; - }); + } } private static class SpecialFiles { + public const string StandardStreamsDir = "std-streams"; + public const string StdOut = "stdout.txt"; + public const string StdErr = "stderr.txt"; public static readonly string[] FileNames = { StdOut, StdErr }; - private const string StdOut = "StdOut"; - private const string StdErr = "StdErr"; - public static bool IsSpecialFile(string filePath) { return FileNames.Contains(filePath, StringComparer.OrdinalIgnoreCase); diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs index fe0048775e..fb9977ceca 100644 --- a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using FluentAssertions; using Microsoft.TemplateEngine.Authoring.TemplateVerifier; using Microsoft.TemplateEngine.TestHelper; @@ -23,8 +22,9 @@ public VerifyCommandTests(ITestOutputHelper log) [Fact] public void VerifyCommandFullDevLoop() { - string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + // dots issue https://github.com/VerifyTests/Verify/issues/658 + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); string templateDir = "path with spaces"; var cmd = new BasicCommand( @@ -40,7 +40,11 @@ public void VerifyCommandFullDevLoop() workingDir, "--expectations-directory", expectationsDir, - "--disable-diff-tool"); + "--disable-diff-tool", + "--unique-for", + "architecture", + "--unique-for", + "RuntimeAndVersion"); cmd.Execute() .Should() @@ -54,44 +58,46 @@ public void VerifyCommandFullDevLoop() // Assert verification files created Directory.Exists(expectationsDir).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "console.console.csproj.received.csproj")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "console.Program.cs.received.cs")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "console.StdOut.received.txt")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "console.StdErr.received.txt")).Should().BeTrue(); + Directory.GetDirectories(expectationsDir).Length.Should().Be(1); + //for simplicity move to the created dir + expectationsDir = Directory.GetDirectories(expectationsDir).Single(); + File.Exists(Path.Combine(expectationsDir, templateDir, "console.received.csproj")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, templateDir, "Program.received.cs")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "std-streams", "stdout.received.txt")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "std-streams", "stderr.received.txt")).Should().BeTrue(); // .verified files are only created when diff tool is used - that is however turned off in CI //File.Exists(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeTrue(); //File.Exists(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeTrue(); //File.Exists(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeTrue(); //File.Exists(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeTrue(); - Directory.GetFiles(expectationsDir).Length.Should().Be(4); + Directory.GetFiles(expectationsDir, "*", SearchOption.AllDirectories).Length.Should().Be(4); // .verified files are only created when diff tool is used - that is however turned off in CI //File.ReadAllText(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeEmpty(); //File.ReadAllText(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeEmpty(); //File.ReadAllText(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeEmpty(); //File.ReadAllText(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeEmpty(); - File.ReadAllText(Path.Combine(expectationsDir, "console.console.csproj.received.csproj").UnixifyLineBreaks()).Should() + File.ReadAllText(Path.Combine(expectationsDir, templateDir, "console.received.csproj").UnixifyLineBreaks()).Should() .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "console.csproj")).UnixifyLineBreaks()); - File.ReadAllText(Path.Combine(expectationsDir, "console.Program.cs.received.cs").UnixifyLineBreaks()).Should() + File.ReadAllText(Path.Combine(expectationsDir, templateDir, "Program.received.cs").UnixifyLineBreaks()).Should() .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "Program.cs")).UnixifyLineBreaks()); // Accept changes - File.Delete(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")); - File.Delete(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")); - File.Delete(Path.Combine(expectationsDir, "console.StdOut.verified.txt")); - File.Delete(Path.Combine(expectationsDir, "console.StdErr.verified.txt")); File.Move( - Path.Combine(expectationsDir, "console.console.csproj.received.csproj"), - Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")); + Path.Combine(expectationsDir, templateDir, "console.received.csproj"), + Path.Combine(expectationsDir, templateDir, "console.verified.csproj")); File.Move( - Path.Combine(expectationsDir, "console.Program.cs.received.cs"), - Path.Combine(expectationsDir, "console.Program.cs.verified.cs")); + Path.Combine(expectationsDir, templateDir, "Program.received.cs"), + Path.Combine(expectationsDir, templateDir, "Program.verified.cs")); File.Move( - Path.Combine(expectationsDir, "console.StdOut.received.txt"), - Path.Combine(expectationsDir, "console.StdOut.verified.txt")); + Path.Combine(expectationsDir, "std-streams", "stdout.received.txt"), + Path.Combine(expectationsDir, "std-streams", "stdout.verified.txt")); File.Move( - Path.Combine(expectationsDir, "console.StdErr.received.txt"), - Path.Combine(expectationsDir, "console.StdErr.verified.txt")); + Path.Combine(expectationsDir, "std-streams", "stderr.received.txt"), + Path.Combine(expectationsDir, "std-streams", "stderr.verified.txt")); + + //reset the expectations dir to where it was before previous run + expectationsDir = Path.GetDirectoryName(expectationsDir)!; // And run again same scenario - verification should succeed now string workingDir2 = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); @@ -107,7 +113,11 @@ public void VerifyCommandFullDevLoop() "-o", workingDir2, "--expectations-directory", - expectationsDir); + expectationsDir, + "--unique-for", + "architecture", + "--unique-for", + "RuntimeAndVersion"); cmd2.Execute() .Should() diff --git a/test/Microsoft.TemplateEngine.IDE.IntegrationTests/VerifySettingsFixture.cs b/test/Microsoft.TemplateEngine.IDE.IntegrationTests/VerifySettingsFixture.cs index ea381535fc..4f9e09652d 100644 --- a/test/Microsoft.TemplateEngine.IDE.IntegrationTests/VerifySettingsFixture.cs +++ b/test/Microsoft.TemplateEngine.IDE.IntegrationTests/VerifySettingsFixture.cs @@ -1,16 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; -using VerifyTests; - namespace Microsoft.TemplateEngine.IDE.IntegrationTests { public class VerifySettingsFixture : IDisposable { public VerifySettingsFixture() { - VerifierSettings.DerivePathInfo( + Verifier.DerivePathInfo( (_, _, type, method) => new( directory: "Approvals", typeName: type.Name, From 1fde346f61288b046fbe1f9718c99ac697a2970a Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Thu, 22 Sep 2022 20:19:30 +0200 Subject: [PATCH 04/15] Add 3rd party signing info --- eng/Signing.props | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/eng/Signing.props b/eng/Signing.props index 586fe4875a..f233f020f2 100644 --- a/eng/Signing.props +++ b/eng/Signing.props @@ -2,4 +2,20 @@ true + + + + + + + + + + + + + From fe2f6b2e7162a96abf697a4ba60f3bbefc47950f Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Fri, 23 Sep 2022 10:23:44 +0200 Subject: [PATCH 05/15] Remove dependency on test project --- ...rosoft.TemplateEngine.Authoring.CLI.csproj | 1 - .../Assertions/CommandResultAssertions.cs | 186 ++++++++++++++++++ .../Assertions/CommandResultExtensions.cs | 18 ++ .../Commands/BasicCommand.cs | 33 ++++ .../Commands/DotnetCommand.cs | 47 +++++ .../Commands/SdkCommandSpec.cs | 65 ++++++ .../Commands/TestCommand.cs | 125 ++++++++++++ ...teEngine.Authoring.TemplateVerifier.csproj | 7 +- .../VerificationEngine.cs | 3 +- 9 files changed, 480 insertions(+), 5 deletions(-) create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultAssertions.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultExtensions.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/BasicCommand.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/DotnetCommand.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/SdkCommandSpec.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj b/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj index 77eb733358..c75590eee5 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj @@ -22,7 +22,6 @@ - diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultAssertions.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultAssertions.cs new file mode 100644 index 0000000000..591edc0145 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultAssertions.cs @@ -0,0 +1,186 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if NET + +using System.Text.RegularExpressions; +using FluentAssertions; +using FluentAssertions.Execution; +using Microsoft.DotNet.Cli.Utils; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands +{ + public class CommandResultAssertions + { + private CommandResult _commandResult; + + public CommandResultAssertions(CommandResult commandResult) + { + _commandResult = commandResult; + } + + public AndConstraint ExitWith(int expectedExitCode) + { + Execute.Assertion.ForCondition(_commandResult.ExitCode == expectedExitCode) + .FailWith(AppendDiagnosticsTo($"Expected command to exit with {expectedExitCode} but it did not.")); + return new AndConstraint(this); + } + + public AndConstraint Pass() + { + Execute.Assertion.ForCondition(_commandResult.ExitCode == 0) + .FailWith(AppendDiagnosticsTo($"Expected command to pass but it did not.")); + return new AndConstraint(this); + } + + public AndConstraint Fail() + { + Execute.Assertion.ForCondition(_commandResult.ExitCode != 0) + .FailWith(AppendDiagnosticsTo($"Expected command to fail but it did not.")); + return new AndConstraint(this); + } + + public AndConstraint HaveStdOut() + { + Execute.Assertion.ForCondition(!string.IsNullOrEmpty(_commandResult.StdOut)) + .FailWith(AppendDiagnosticsTo("Command did not output anything to stdout")); + return new AndConstraint(this); + } + + public AndConstraint HaveStdOut(string expectedOutput) + { + Execute.Assertion.ForCondition(_commandResult.StdOut.Equals(expectedOutput, StringComparison.Ordinal)) + .FailWith(AppendDiagnosticsTo($"Command did not output with Expected Output. Expected: {expectedOutput}")); + return new AndConstraint(this); + } + + public AndConstraint HaveStdOutContaining(string pattern) + { + Execute.Assertion.ForCondition(_commandResult.StdOut.Contains(pattern)) + .FailWith(AppendDiagnosticsTo($"The command output did not contain expected result: {pattern}{Environment.NewLine}")); + return new AndConstraint(this); + } + + public AndConstraint HaveStdOutContaining(Func predicate, string description = "") + { + Execute.Assertion.ForCondition(predicate(_commandResult.StdOut)) + .FailWith(AppendDiagnosticsTo($"The command output did not contain expected result: {description} {Environment.NewLine}")); + return new AndConstraint(this); + } + + public AndConstraint NotHaveStdOutContaining(string pattern) + { + Execute.Assertion.ForCondition(!_commandResult.StdOut.Contains(pattern)) + .FailWith(AppendDiagnosticsTo($"The command output contained a result it should not have contained: {pattern}{Environment.NewLine}")); + return new AndConstraint(this); + } + + public AndConstraint HaveStdOutContainingIgnoreSpaces(string pattern) + { + string commandResultNoSpaces = _commandResult.StdOut.Replace(" ", ""); + + Execute.Assertion + .ForCondition(commandResultNoSpaces.Contains(pattern)) + .FailWith(AppendDiagnosticsTo($"The command output did not contain expected result: {pattern}{Environment.NewLine}")); + + return new AndConstraint(this); + } + + public AndConstraint HaveStdOutContainingIgnoreCase(string pattern) + { + Execute.Assertion.ForCondition(_commandResult.StdOut.Contains(pattern, StringComparison.OrdinalIgnoreCase)) + .FailWith(AppendDiagnosticsTo($"The command output did not contain expected result (ignoring case): {pattern}{Environment.NewLine}")); + return new AndConstraint(this); + } + + public AndConstraint HaveStdOutMatching(string pattern, RegexOptions options = RegexOptions.None) + { + Execute.Assertion.ForCondition(Regex.Match(_commandResult.StdOut, pattern, options).Success) + .FailWith(AppendDiagnosticsTo($"Matching the command output failed. Pattern: {pattern}{Environment.NewLine}")); + return new AndConstraint(this); + } + + public AndConstraint NotHaveStdOutMatching(string pattern, RegexOptions options = RegexOptions.None) + { + Execute.Assertion.ForCondition(!Regex.Match(_commandResult.StdOut, pattern, options).Success) + .FailWith(AppendDiagnosticsTo($"The command output matched a pattern it should not have. Pattern: {pattern}{Environment.NewLine}")); + return new AndConstraint(this); + } + + public AndConstraint HaveStdErr() + { + Execute.Assertion.ForCondition(!string.IsNullOrEmpty(_commandResult.StdErr)) + .FailWith(AppendDiagnosticsTo("Command did not output anything to StdErr.")); + return new AndConstraint(this); + } + + public AndConstraint HaveStdErr(string expectedOutput) + { + Execute.Assertion.ForCondition(_commandResult.StdErr.Equals(expectedOutput, StringComparison.Ordinal)) + .FailWith(AppendDiagnosticsTo($"Command did not output the expected output to StdErr.{Environment.NewLine}Expected: {expectedOutput}{Environment.NewLine}Actual: {_commandResult.StdErr}")); + return new AndConstraint(this); + } + + public AndConstraint HaveStdErrContaining(string pattern) + { + Execute.Assertion.ForCondition(_commandResult.StdErr.Contains(pattern)) + .FailWith(AppendDiagnosticsTo($"The command error output did not contain expected result: {pattern}{Environment.NewLine}")); + return new AndConstraint(this); + } + + public AndConstraint NotHaveStdErrContaining(string pattern) + { + Execute.Assertion.ForCondition(!_commandResult.StdErr.Contains(pattern)) + .FailWith(AppendDiagnosticsTo($"The command error output contained a result it should not have contained: {pattern}{Environment.NewLine}")); + return new AndConstraint(this); + } + + public AndConstraint HaveStdErrMatching(string pattern, RegexOptions options = RegexOptions.None) + { + Execute.Assertion.ForCondition(Regex.Match(_commandResult.StdErr, pattern, options).Success) + .FailWith(AppendDiagnosticsTo($"Matching the command error output failed. Pattern: {pattern}{Environment.NewLine}")); + return new AndConstraint(this); + } + + public AndConstraint NotHaveStdOut() + { + Execute.Assertion.ForCondition(string.IsNullOrEmpty(_commandResult.StdOut)) + .FailWith(AppendDiagnosticsTo($"Expected command to not output to stdout but it was not:")); + return new AndConstraint(this); + } + + public AndConstraint NotHaveStdErr() + { + Execute.Assertion.ForCondition(string.IsNullOrEmpty(_commandResult.StdErr)) + .FailWith(AppendDiagnosticsTo("Expected command to not output to stderr but it was not:")); + return new AndConstraint(this); + } + + public AndConstraint HaveSkippedProjectCompilation(string skippedProject, string frameworkFullName) + { + _commandResult.StdOut.Should().Contain($"Project {skippedProject} ({frameworkFullName}) was previously compiled. Skipping compilation."); + + return new AndConstraint(this); + } + + public AndConstraint HaveCompiledProject(string compiledProject, string frameworkFullName) + { + _commandResult.StdOut.Should().Contain($"Project {compiledProject} ({frameworkFullName}) will be compiled"); + + return new AndConstraint(this); + } + + private string AppendDiagnosticsTo(string s) + { + return (s + $"{Environment.NewLine}" + + $"File Name: {_commandResult.StartInfo.FileName}{Environment.NewLine}" + + $"Arguments: {_commandResult.StartInfo.Arguments}{Environment.NewLine}" + + $"Exit Code: {_commandResult.ExitCode}{Environment.NewLine}" + + $"StdOut:{Environment.NewLine}{_commandResult.StdOut}{Environment.NewLine}" + + $"StdErr:{Environment.NewLine}{_commandResult.StdErr}{Environment.NewLine}") + //escape curly braces for String.Format + .Replace("{", "{{").Replace("}", "}}"); + } + } +} +#endif diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultExtensions.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultExtensions.cs new file mode 100644 index 0000000000..88c2e13344 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultExtensions.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if NET + +using Microsoft.DotNet.Cli.Utils; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands +{ + public static class CommandResultExtensions + { + public static CommandResultAssertions Should(this CommandResult commandResult) + { + return new CommandResultAssertions(commandResult); + } + } +} +#endif diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/BasicCommand.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/BasicCommand.cs new file mode 100644 index 0000000000..7554f494b1 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/BasicCommand.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if NET +using System.Collections.Generic; +using System.Linq; +using Xunit.Abstractions; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands +{ + public class BasicCommand : TestCommand + { + private readonly string _processName; + + public BasicCommand(ITestOutputHelper log, string processName, params string[] args) : base(log) + { + _processName = processName; + Arguments.AddRange(args.Where(a => !string.IsNullOrWhiteSpace(a))); + } + + protected override SdkCommandSpec CreateCommand(IEnumerable args) + { + var sdkCommandSpec = new SdkCommandSpec() + { + FileName = _processName, + Arguments = args.ToList(), + WorkingDirectory = WorkingDirectory + }; + return sdkCommandSpec; + } + } +} +#endif diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/DotnetCommand.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/DotnetCommand.cs new file mode 100644 index 0000000000..e18fb00c05 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/DotnetCommand.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if NET +using Xunit.Abstractions; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands +{ + public class DotnetCommand : TestCommand + { + private readonly string commandName; + + public DotnetCommand(ITestOutputHelper log, string commandName, params string[] args) : base(log) + { + Arguments.Add(commandName); + Arguments.AddRange(args); + this.commandName = commandName; + } + + public DotnetCommand WithCustomHive(string? path = null) + { + path ??= CreateTemporaryFolder(); + Arguments.Add("--debug:custom-hive"); + Arguments.Add(path); + return this; + } + + protected override SdkCommandSpec CreateCommand(IEnumerable args) + { + var sdkCommandSpec = new SdkCommandSpec() + { + FileName = "dotnet", + Arguments = args.ToList(), + WorkingDirectory = WorkingDirectory + }; + return sdkCommandSpec; + } + + private static string CreateTemporaryFolder(string name = "") + { + string workingDir = Path.Combine(Path.GetTempPath(), "TemplateEngine.Tests", Guid.NewGuid().ToString(), name); + Directory.CreateDirectory(workingDir); + return workingDir; + } + } +} +#endif diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/SdkCommandSpec.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/SdkCommandSpec.cs new file mode 100644 index 0000000000..8cdb500cc0 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/SdkCommandSpec.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if NET + +using System.Collections.Generic; +using System.Diagnostics; +using Microsoft.DotNet.Cli.Utils; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands +{ + public class SdkCommandSpec + { + public string? FileName { get; set; } + + public List Arguments { get; set; } = new List(); + + public Dictionary Environment { get; set; } = new Dictionary(); + + public List EnvironmentToRemove { get; } = new List(); + + public string? WorkingDirectory { get; set; } + + public Command ToCommand() + { + var process = new Process() + { + StartInfo = ToProcessStartInfo() + }; + var ret = new Command(process, trimtrailingNewlines: true); + return ret; + } + + public ProcessStartInfo ToProcessStartInfo() + { + var ret = new ProcessStartInfo(); + ret.FileName = FileName; + ret.Arguments = EscapeArgs(); + ret.UseShellExecute = false; + foreach (var kvp in Environment) + { + ret.Environment[kvp.Key] = kvp.Value; + } + foreach (var envToRemove in EnvironmentToRemove) + { + ret.Environment.Remove(envToRemove); + } + + if (WorkingDirectory != null) + { + ret.WorkingDirectory = WorkingDirectory; + } + + return ret; + } + + private string EscapeArgs() + { + // Note: this doesn't handle invoking .cmd files via "cmd /c" on Windows, which probably won't be necessary here + // If it is, refer to the code in WindowsExePreferredCommandSpecFactory in Microsoft.DotNet.Cli.Utils + return ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(Arguments); + } + } +} +#endif diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs new file mode 100644 index 0000000000..fb54e8975b --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs @@ -0,0 +1,125 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#if NET + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Microsoft.DotNet.Cli.Utils; +using Xunit.Abstractions; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands +{ + public abstract class TestCommand + { + protected TestCommand(ITestOutputHelper log) + { + Log = log; + } + + public ITestOutputHelper Log { get; } + + public string? WorkingDirectory { get; set; } + + public List Arguments { get; set; } = new List(); + + public List EnvironmentToRemove { get; } = new List(); + + // These only work via Execute(), not when using GetProcessStartInfo() + public Action? CommandOutputHandler { get; set; } + + public Action? ProcessStartedHandler { get; set; } + + protected Dictionary Environment { get; set; } = new Dictionary(); + + public TestCommand WithEnvironmentVariable(string name, string value) + { + Environment[name] = value; + return this; + } + + public TestCommand WithWorkingDirectory(string workingDirectory) + { + WorkingDirectory = workingDirectory; + return this; + } + + public ProcessStartInfo GetProcessStartInfo(params string[] args) + { + var commandSpec = CreateCommandSpec(args); + + var psi = commandSpec.ToProcessStartInfo(); + + return psi; + } + + public CommandResult Execute(params string[] args) + { + IEnumerable enumerableArgs = args; + return Execute(enumerableArgs); + } + + public virtual CommandResult Execute(IEnumerable args) + { + var command = CreateCommandSpec(args) + .ToCommand() + .CaptureStdOut() + .CaptureStdErr(); + + if (CommandOutputHandler != null) + { + command.OnOutputLine(CommandOutputHandler); + } + + var result = ((Command)command).Execute(ProcessStartedHandler); + + Log.WriteLine($"> {result.StartInfo.FileName} {result.StartInfo.Arguments}"); + Log.WriteLine(result.StdOut); + + if (!string.IsNullOrEmpty(result.StdErr)) + { + Log.WriteLine(""); + Log.WriteLine("StdErr:"); + Log.WriteLine(result.StdErr); + } + + if (result.ExitCode != 0) + { + Log.WriteLine($"Exit Code: {result.ExitCode}"); + } + + return result; + } + + protected abstract SdkCommandSpec CreateCommand(IEnumerable args); + + private SdkCommandSpec CreateCommandSpec(IEnumerable args) + { + var commandSpec = CreateCommand(args); + foreach (var kvp in Environment) + { + commandSpec.Environment[kvp.Key] = kvp.Value; + } + + foreach (var envToRemove in EnvironmentToRemove) + { + commandSpec.EnvironmentToRemove.Add(envToRemove); + } + + if (WorkingDirectory != null) + { + commandSpec.WorkingDirectory = WorkingDirectory; + } + + if (Arguments.Any()) + { + commandSpec.Arguments = Arguments.Concat(commandSpec.Arguments).ToList(); + } + + return commandSpec; + } + } +} +#endif diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj index c86162bdd3..f1842c44f7 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj @@ -17,11 +17,14 @@ + + + + + - - diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs index 8c4834be6e..937b1ab58f 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs @@ -1,13 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using System.Reflection; using System.Text.RegularExpressions; using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Microsoft.TemplateEngine.TestHelper.Commands; +using Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands; using Microsoft.TemplateEngine.Utils; using Xunit.Abstractions; From b993d786286b62529dc5789eaba1a2fba833216a Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Mon, 26 Sep 2022 16:23:52 +0200 Subject: [PATCH 06/15] Use custom exceptions for exit expectations failed --- .../VerificationEngine.cs | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs index 937b1ab58f..8f6e3685df 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs @@ -85,16 +85,32 @@ public async Task Execute(CancellationToken cancellationToken = default) if (_options.IsCommandExpectedToFail ?? false) { - commandResult.Should().Fail(); + if (commandResult.ExitCode == 0) + { + throw new TemplateVerificationException( + "Template instantiation expected to fail but it passed.", + TemplateVerificationErrorCode.VerificationFailed); + } } else { - var assertion = commandResult.Should().Pass(); + if (commandResult.ExitCode != 0) + { + throw new TemplateVerificationException( + string.Format("Template instantiation expected to pass but it had exit code {0}.", commandResult.ExitCode), + TemplateVerificationErrorCode.VerificationFailed); + } + // We do not expect stderr in passing command. // However if verification of stdout and stderr is opted-in - we will let that verification validate the stderr content - if (!(_options.VerifyCommandOutput ?? false)) + if (!(_options.VerifyCommandOutput ?? false) && !string.IsNullOrEmpty(commandResult.StdErr)) { - assertion.And.NotHaveStdErr(); + throw new TemplateVerificationException( + string.Format( + "Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}", + Environment.NewLine, + commandResult.StdErr), + TemplateVerificationErrorCode.VerificationFailed); } } From d8c79d12e5e19fd9c10db42f04662090ef23c314 Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Mon, 26 Sep 2022 18:38:06 +0200 Subject: [PATCH 07/15] Improve engine API, add API tests --- Microsoft.TemplateEngine.sln | 15 ++ .../TemplateVerifierOptions.cs | 55 ++++- .../VerificationEngine.cs | 216 ++++++++++-------- ...ne.Authoring.TemplateVerifier.Tests.csproj | 19 ++ .../VerificationEngineTests.cs | 169 ++++++++++++++ 5 files changed, 381 insertions(+), 93 deletions(-) create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/VerificationEngineTests.cs diff --git a/Microsoft.TemplateEngine.sln b/Microsoft.TemplateEngine.sln index 756283399d..b96016faca 100644 --- a/Microsoft.TemplateEngine.sln +++ b/Microsoft.TemplateEngine.sln @@ -68,6 +68,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{B794BF86 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier", "src\Microsoft.TemplateEngine.Authoring.TemplateVerifier\Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj", "{12764D81-61A7-437A-90B6-9F245E43F457}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests", "test\Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests\Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj", "{DFB18A1E-4C70-48D3-B57A-FA81B405EA04}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -402,6 +404,18 @@ Global {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x64.Build.0 = Release|Any CPU {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x86.ActiveCfg = Release|Any CPU {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x86.Build.0 = Release|Any CPU + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Debug|x64.ActiveCfg = Debug|Any CPU + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Debug|x64.Build.0 = Debug|Any CPU + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Debug|x86.ActiveCfg = Debug|Any CPU + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Debug|x86.Build.0 = Debug|Any CPU + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|Any CPU.Build.0 = Release|Any CPU + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|x64.ActiveCfg = Release|Any CPU + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|x64.Build.0 = Release|Any CPU + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|x86.ActiveCfg = Release|Any CPU + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -434,6 +448,7 @@ Global {BD758B10-A47F-4159-B9A1-997723AF7349} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B} {2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} {12764D81-61A7-437A-90B6-9F245E43F457} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B} + {DFB18A1E-4C70-48D3-B57A-FA81B405EA04} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6EA1A508-6033-4538-BF98-7F71B4E297AD} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs index b9d58f1b8f..3e184dce58 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs @@ -6,8 +6,21 @@ namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier { + /// + /// Delegate signature for performing custom directory content verifications. + /// Expectable verification failures should be signaled with . + /// API provider can either perform content enumeration, skipping and scrubbing by themselves (then the second argument can be ignored) + /// or the can be awaited to get the content of files - filtered by exclusion patterns and scrubbed by scrubbers. + /// + /// + /// + /// + public delegate Task VerifyDirectory(string contentDirectory, Lazy> contentFetcher); + public class ScrubbersDefinition { + public static readonly ScrubbersDefinition Empty = new(); + public ScrubbersDefinition() { } public ScrubbersDefinition(Action scrubber, string? extension = null) @@ -19,8 +32,13 @@ public ScrubbersDefinition(Action scrubber, string? extension = n public Action? GeneralScrubber { get; private set; } - public void AddScrubber(Action scrubber, string? extension = null) + public ScrubbersDefinition AddScrubber(Action scrubber, string? extension = null) { + if (object.ReferenceEquals(this, Empty)) + { + return new ScrubbersDefinition().AddScrubber(scrubber, extension); + } + if (extension == null) { GeneralScrubber += scrubber; @@ -29,6 +47,8 @@ public void AddScrubber(Action scrubber, string? extension = null { ScrubersByExtension[extension] = scrubber; } + + return this; } } @@ -99,13 +119,42 @@ public class TemplateVerifierOptions : IOptions /// /// Gets the delegates that perform custom scrubbing of template output contents before verifications. /// - public ScrubbersDefinition? CustomScrubbers { get; init; } + public ScrubbersDefinition? CustomScrubbers { get; private set; } /// /// Gets the delegate that performs custom verification of template output contents. /// - public Func? CustomVerifyDirectory { get; init; } + public VerifyDirectory? CustomDirectoryVerifier { get; private set; } + + /// + /// Gets the extension of autogeneratedfiles with stdout and stderr content. + /// + public string? StandardOutputFileExtension { get; init; } TemplateVerifierOptions IOptions.Value => this; + + /// + /// Adds a custom scrubber definition. + /// The scrubber definition can alter the template content (globally or based on the file extension), before the verifications occur. + /// + /// + /// + public TemplateVerifierOptions WithCustomScrubbers(ScrubbersDefinition scrubbers) + { + this.CustomScrubbers = scrubbers; + return this; + } + + /// + /// Adds on optional custom verifier implementation. + /// If custom verifier is provided, no default verifications of content will be performed - the caller is responsible for performing the verifications. + /// + /// + /// + public TemplateVerifierOptions WithCustomDirectoryVerifier(VerifyDirectory verifier) + { + this.CustomDirectoryVerifier = verifier; + return this; + } } } diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs index 8f6e3685df..1a2bed2a4c 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Reflection; +using System.Text; using System.Text.RegularExpressions; using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Logging; @@ -131,6 +132,125 @@ private static string EncodeArgsAsPath(IEnumerable? args) private static void DummyMethod() { } + private static async IAsyncEnumerable<(string FilePath, string ScrubbedContent)> GetVerificationContent(string contentDir, List globs, ScrubbersDefinition? scrubbers) + { + foreach (string filePath in Directory.EnumerateFiles(contentDir, "*", SearchOption.AllDirectories)) + { + if (globs.Any(g => g.IsMatch(filePath))) + { + continue; + } + + string content = await File.ReadAllTextAsync(filePath).ConfigureAwait(false); + + if (scrubbers != null) + { + string extension = Path.GetExtension(filePath); + + if (string.IsNullOrEmpty(extension) || !scrubbers.ScrubersByExtension.TryGetValue(extension, out Action? scrubber)) + { + scrubber = scrubbers.GeneralScrubber; + } + + if (scrubber != null) + { + var sb = new StringBuilder(content); + scrubber(sb); + content = sb.ToString(); + } + } + + yield return new(filePath, content); + } + } + + private static Task CreateVerificationTask(string contentDir, TemplateVerifierOptions options) + { + List exclusionsList = (options.DisableDefaultVerificationExcludePatterns ?? false) + ? new() + : new(_defaultVerificationExcludePatterns); + + if (options.VerificationExcludePatterns != null) + { + exclusionsList.AddRange(options.VerificationExcludePatterns); + } + + List globs = exclusionsList.Select(pattern => Glob.Parse(pattern)).ToList(); + + SettingsTask defaultVerifyTask = Verifier.VerifyDirectory( + contentDir, + (filePath) => !globs.Any(g => g.IsMatch(filePath))); + + if (options.CustomScrubbers != null) + { + if (options.CustomScrubbers.GeneralScrubber != null) + { + defaultVerifyTask = defaultVerifyTask.AddScrubber(options.CustomScrubbers.GeneralScrubber); + } + + foreach (var pair in options.CustomScrubbers.ScrubersByExtension) + { + defaultVerifyTask = defaultVerifyTask.AddScrubber(pair.Key, pair.Value); + } + } + + if (options.CustomDirectoryVerifier != null) + { + return options.CustomDirectoryVerifier( + contentDir, + new Lazy>( + GetVerificationContent(contentDir, globs, options.CustomScrubbers))); + } + + Verifier.DerivePathInfo( + (sourceFile, projectDirectory, type, method) => new( + directory: options.ExpectationsDirectory ?? "VerifyExpectations", + typeName: options.TemplateName, + methodName: EncodeArgsAsPath(options.TemplateSpecificArgs))); + + if ((options.UniqueFor ?? UniqueForOption.None) != UniqueForOption.None) + { + foreach (UniqueForOption value in Enum.GetValues(typeof(UniqueForOption))) + { + if ((options.UniqueFor & value) == value) + { + switch (value) + { + case UniqueForOption.None: + break; + case UniqueForOption.Architecture: + defaultVerifyTask = defaultVerifyTask.UniqueForArchitecture(); + break; + case UniqueForOption.OsPlatform: + defaultVerifyTask = defaultVerifyTask.UniqueForOSPlatform(); + break; + case UniqueForOption.Runtime: + defaultVerifyTask = defaultVerifyTask.UniqueForRuntime(); + break; + case UniqueForOption.RuntimeAndVersion: + defaultVerifyTask = defaultVerifyTask.UniqueForRuntimeAndVersion(); + break; + case UniqueForOption.TargetFramework: + defaultVerifyTask = defaultVerifyTask.UniqueForTargetFramework(); + break; + case UniqueForOption.TargetFrameworkAndVersion: + defaultVerifyTask = defaultVerifyTask.UniqueForTargetFrameworkAndVersion(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + } + } + + if (options.DisableDiffTool ?? false) + { + defaultVerifyTask = defaultVerifyTask.DisableDiff(); + } + + return defaultVerifyTask; + } + private async Task VerifyResult(TemplateVerifierOptions args, CommandResult commandResult) { // Customize diff output of verifier @@ -143,17 +263,6 @@ private async Task VerifyResult(TemplateVerifierOptions args, CommandResult comm MethodInfo mi = v.Method; a.Before(mi); - List exclusionsList = (args.DisableDefaultVerificationExcludePatterns ?? false) - ? new() - : new(_defaultVerificationExcludePatterns); - - if (args.VerificationExcludePatterns != null) - { - exclusionsList.AddRange(args.VerificationExcludePatterns); - } - - List globs = exclusionsList.Select(pattern => Glob.Parse(pattern)).ToList(); - if (_options.VerifyCommandOutput ?? false) { if (Directory.Exists(Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir))) @@ -168,85 +277,20 @@ private async Task VerifyResult(TemplateVerifierOptions args, CommandResult comm Directory.CreateDirectory(Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir)); await File.WriteAllTextAsync( - Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdOut), + Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdOut + (_options.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)), commandResult.StdOut) .ConfigureAwait(false); await File.WriteAllTextAsync( - Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdErr), + Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdErr + (_options.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)), commandResult.StdErr) .ConfigureAwait(false); } - Verifier.DerivePathInfo( - (sourceFile, projectDirectory, type, method) => new( - directory: args.ExpectationsDirectory ?? "VerifyExpectations", - typeName: args.TemplateName, - methodName: EncodeArgsAsPath(args.TemplateSpecificArgs))); + Task verifyTask = CreateVerificationTask(commandResult.StartInfo.WorkingDirectory, args); try { - SettingsTask defaultVerifyTask = Verifier.VerifyDirectory( - commandResult.StartInfo.WorkingDirectory, - (filePath) => !globs.Any(g => g.IsMatch(filePath))); - - if (_options.CustomScrubbers != null) - { - if (_options.CustomScrubbers.GeneralScrubber != null) - { - defaultVerifyTask = defaultVerifyTask.AddScrubber(_options.CustomScrubbers.GeneralScrubber); - } - - foreach (var pair in _options.CustomScrubbers.ScrubersByExtension) - { - defaultVerifyTask = defaultVerifyTask.AddScrubber(pair.Key, pair.Value); - } - } - - if ((_options.UniqueFor ?? UniqueForOption.None) != UniqueForOption.None) - { - foreach (UniqueForOption value in Enum.GetValues(typeof(UniqueForOption))) - { - if ((_options.UniqueFor & value) == value) - { - switch (value) - { - case UniqueForOption.None: - break; - case UniqueForOption.Architecture: - defaultVerifyTask = defaultVerifyTask.UniqueForArchitecture(); - break; - case UniqueForOption.OsPlatform: - defaultVerifyTask = defaultVerifyTask.UniqueForOSPlatform(); - break; - case UniqueForOption.Runtime: - defaultVerifyTask = defaultVerifyTask.UniqueForRuntime(); - break; - case UniqueForOption.RuntimeAndVersion: - defaultVerifyTask = defaultVerifyTask.UniqueForRuntimeAndVersion(); - break; - case UniqueForOption.TargetFramework: - defaultVerifyTask = defaultVerifyTask.UniqueForTargetFramework(); - break; - case UniqueForOption.TargetFrameworkAndVersion: - defaultVerifyTask = defaultVerifyTask.UniqueForTargetFrameworkAndVersion(); - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - } - } - - if (_options.DisableDiffTool ?? false) - { - defaultVerifyTask = defaultVerifyTask.DisableDiff(); - } - - Task verifyTask = _options.CustomVerifyDirectory != null - ? _options.CustomVerifyDirectory(commandResult.StartInfo.WorkingDirectory) - : defaultVerifyTask; - await verifyTask.ConfigureAwait(false); } catch (Exception e) @@ -270,18 +314,10 @@ await File.WriteAllTextAsync( private static class SpecialFiles { public const string StandardStreamsDir = "std-streams"; - public const string StdOut = "stdout.txt"; - public const string StdErr = "stderr.txt"; + public const string StdOut = "stdout"; + public const string StdErr = "stderr"; + public const string DefaultExtension = ".txt"; public static readonly string[] FileNames = { StdOut, StdErr }; - - public static bool IsSpecialFile(string filePath) - { - return FileNames.Contains(filePath, StringComparer.OrdinalIgnoreCase); - } - - public static bool IsStdOut(string filePath) => filePath.Equals(StdOut, StringComparison.OrdinalIgnoreCase); - - public static bool IsStdErr(string filePath) => filePath.Equals(StdErr, StringComparison.OrdinalIgnoreCase); } private class LoggerProxy : ITestOutputHelper diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj new file mode 100644 index 0000000000..ded7a847e5 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj @@ -0,0 +1,19 @@ + + + $(NETCoreTargetFramework) + enable + enable + + + + Always + + + + + + + + + + diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/VerificationEngineTests.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/VerificationEngineTests.cs new file mode 100644 index 0000000000..689fd0f06f --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/VerificationEngineTests.cs @@ -0,0 +1,169 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +//using FluentAssertions; +//using Microsoft.TemplateEngine.Authoring.TemplateVerifier; +//using Microsoft.TemplateEngine.TestHelper; +//using Microsoft.TemplateEngine.TestHelper.Commands; +//using Xunit.Abstractions; + +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Microsoft.TemplateEngine.TestHelper; +using Xunit.Abstractions; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests +{ + public class VerificationEngineTests + { + private readonly ILogger _log; + + public VerificationEngineTests(ITestOutputHelper log) + { + _log = new XunitLoggerProvider(log).CreateLogger("TestRun"); + } + + [Fact] + public async void VerificationEngineFullDevLoop() + { + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string templateDir = "path with spaces"; + + TemplateVerifierOptions options = new TemplateVerifierOptions() + { + TemplateName = "console", + TemplateSpecificArgs = new string[] { "--use-program-main", "-o", templateDir, "--no-restore" }, + DisableDiffTool = true, + ExpectationsDirectory = expectationsDir, + OutputDirectory = workingDir, + VerifyCommandOutput = true, + UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, + }; + + VerificationEngine engine = new VerificationEngine(options, _log); + Func executeTask = () => engine.Execute(); + await executeTask + .Should() + .ThrowAsync() + .Where(e => e.TemplateVerificationErrorCode == TemplateVerificationErrorCode.VerificationFailed); + + // Assert template created + Directory.Exists(Path.Combine(workingDir, templateDir)).Should().BeTrue(); + File.Exists(Path.Combine(workingDir, templateDir, "console.csproj")).Should().BeTrue(); + File.Exists(Path.Combine(workingDir, templateDir, "Program.cs")).Should().BeTrue(); + + // Assert verification files created + Directory.Exists(expectationsDir).Should().BeTrue(); + Directory.GetDirectories(expectationsDir).Length.Should().Be(1); + //for simplicity move to the created dir + expectationsDir = Directory.GetDirectories(expectationsDir).Single(); + File.Exists(Path.Combine(expectationsDir, templateDir, "console.received.csproj")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, templateDir, "Program.received.cs")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "std-streams", "stdout.received.txt")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "std-streams", "stderr.received.txt")).Should().BeTrue(); + Directory.GetFiles(expectationsDir, "*", SearchOption.AllDirectories).Length.Should().Be(4); + + File.ReadAllText(Path.Combine(expectationsDir, templateDir, "console.received.csproj").UnixifyLineBreaks()).Should() + .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "console.csproj")).UnixifyLineBreaks()); + File.ReadAllText(Path.Combine(expectationsDir, templateDir, "Program.received.cs").UnixifyLineBreaks()).Should() + .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "Program.cs")).UnixifyLineBreaks()); + + // Accept changes + File.Move( + Path.Combine(expectationsDir, templateDir, "console.received.csproj"), + Path.Combine(expectationsDir, templateDir, "console.verified.csproj")); + File.Move( + Path.Combine(expectationsDir, templateDir, "Program.received.cs"), + Path.Combine(expectationsDir, templateDir, "Program.verified.cs")); + File.Move( + Path.Combine(expectationsDir, "std-streams", "stdout.received.txt"), + Path.Combine(expectationsDir, "std-streams", "stdout.verified.txt")); + File.Move( + Path.Combine(expectationsDir, "std-streams", "stderr.received.txt"), + Path.Combine(expectationsDir, "std-streams", "stderr.verified.txt")); + + //reset the expectations dir to where it was before previous run + expectationsDir = Path.GetDirectoryName(expectationsDir)!; + + // And run again same scenario - verification should succeed now + string workingDir2 = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + + TemplateVerifierOptions options2 = new TemplateVerifierOptions() + { + TemplateName = "console", + TemplateSpecificArgs = new string[] { "--use-program-main", "-o", templateDir, "--no-restore" }, + DisableDiffTool = true, + ExpectationsDirectory = expectationsDir, + OutputDirectory = workingDir2, + VerifyCommandOutput = true, + UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, + }; + + VerificationEngine engine2 = new VerificationEngine(options2, _log); + Func executeTask2 = () => engine2.Execute(); + await executeTask2 + .Should() + .NotThrowAsync(); + + Directory.Delete(workingDir, true); + Directory.Delete(workingDir2, true); + Directory.Delete(expectationsDir, true); + } + + [Fact] + public async void VerificationEngineCustomVerifier() + { + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string templateDir = "path with spaces"; + + TemplateVerifierOptions options = new TemplateVerifierOptions() + { + TemplateName = "console", + TemplateSpecificArgs = new string[] { "--use-program-main", "-o", templateDir, "--no-restore" }, + DisableDiffTool = true, + OutputDirectory = workingDir, + VerificationExcludePatterns = new[] { "*.cs" }, + VerifyCommandOutput = true, + UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, + } + .WithCustomScrubbers( + ScrubbersDefinition.Empty + .AddScrubber(sb => sb.Replace("Donut", "Veggies"), ".txt") + .AddScrubber(sb => sb.Replace(DateTime.UtcNow.ToString("yyyy-MM-dd"), "2000-01-01")) + ) + .WithCustomDirectoryVerifier( + async (content, contentFetcher) => + { + await foreach (var file in contentFetcher.Value) + { + if (Path.GetExtension(file.FilePath).Equals(".cs")) + { + throw new Exception(".cs files should be excluded per VerificationExcludePatterns"); + } + + if (Path.GetFileName(file.FilePath).Equals("stdout.txt", StringComparison.OrdinalIgnoreCase) + && !file.ScrubbedContent.Contains("Console")) + { + throw new Exception("stdout should contain 'Console'"); + } + + if (Path.GetExtension(file.FilePath).Equals(".csproj") + && !file.ScrubbedContent.Contains("enable")) + { + throw new Exception("Implicit usings should be used"); + } + } + } + ); + + VerificationEngine engine = new VerificationEngine(options, _log); + Func executeTask = () => engine.Execute(); + await executeTask + .Should() + .NotThrowAsync(); + + Directory.Delete(workingDir, true); + } + } +} From ba252cd1095399a583a7f3c86e0a3fe467ad5a4a Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Tue, 27 Sep 2022 10:43:48 +0200 Subject: [PATCH 08/15] Add localizations, move types --- .../Commands/Verify/VerifyCommand.cs | 40 ++---- .../LocalizableStrings.Designer.cs | 126 ++++++++++++++++++ .../LocalizableStrings.resx | 44 ++++++ .../xlf/LocalizableStrings.cs.xlf | 70 ++++++++++ .../xlf/LocalizableStrings.de.xlf | 70 ++++++++++ .../xlf/LocalizableStrings.es.xlf | 70 ++++++++++ .../xlf/LocalizableStrings.fr.xlf | 70 ++++++++++ .../xlf/LocalizableStrings.it.xlf | 70 ++++++++++ .../xlf/LocalizableStrings.ja.xlf | 70 ++++++++++ .../xlf/LocalizableStrings.ko.xlf | 70 ++++++++++ .../xlf/LocalizableStrings.pl.xlf | 70 ++++++++++ .../xlf/LocalizableStrings.pt-BR.xlf | 70 ++++++++++ .../xlf/LocalizableStrings.ru.xlf | 70 ++++++++++ .../xlf/LocalizableStrings.tr.xlf | 70 ++++++++++ .../xlf/LocalizableStrings.zh-Hans.xlf | 70 ++++++++++ .../xlf/LocalizableStrings.zh-Hant.xlf | 70 ++++++++++ .../LocalizableStrings.Designer.cs | 60 ++++++++- .../LocalizableStrings.resx | 26 +++- .../ScrubbersDefinition.cs | 41 ++++++ .../TemplateVerifierOptions.cs | 46 +------ .../VerificationEngine.cs | 21 +-- .../VerifyDirectory.cs | 15 +++ .../xlf/LocalizableStrings.cs.xlf | 38 +++++- .../xlf/LocalizableStrings.de.xlf | 38 +++++- .../xlf/LocalizableStrings.es.xlf | 38 +++++- .../xlf/LocalizableStrings.fr.xlf | 38 +++++- .../xlf/LocalizableStrings.it.xlf | 38 +++++- .../xlf/LocalizableStrings.ja.xlf | 38 +++++- .../xlf/LocalizableStrings.ko.xlf | 38 +++++- .../xlf/LocalizableStrings.pl.xlf | 38 +++++- .../xlf/LocalizableStrings.pt-BR.xlf | 38 +++++- .../xlf/LocalizableStrings.ru.xlf | 38 +++++- .../xlf/LocalizableStrings.tr.xlf | 38 +++++- .../xlf/LocalizableStrings.zh-Hans.xlf | 38 +++++- .../xlf/LocalizableStrings.zh-Hant.xlf | 38 +++++- 35 files changed, 1684 insertions(+), 139 deletions(-) create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/ScrubbersDefinition.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerifyDirectory.cs diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs index cbd9ca3659..46a89b0c83 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs @@ -17,8 +17,7 @@ internal class VerifyCommand : ExecutableCommand private readonly Argument _templateNameArgument = new("-n") { Name = "template-short-name", - //TODO: localize - Description = "Name of already installed template to be verified.", + Description = LocalizableStrings.command_verify_help_templateName_description, // 0 for case where only path is specified Arity = new ArgumentArity(1, 1) }; @@ -32,14 +31,12 @@ internal class VerifyCommand : ExecutableCommand private readonly Option _templatePathOption = new("-p") { Name = "--template-path", - //TODO: localize - Description = "Specifies path to the directory with template to be verified.", + Description = LocalizableStrings.command_verify_help_templatePath_description, }; private readonly Option _newCommandPathOption = new("--new-command-assembly") { - //TODO: localize - Description = "Specifies path to custom assembly implementing the new command.", + Description = LocalizableStrings.command_verify_help_newCommandPath_description, //TODO: do we have better way of distinguishing options that might rarely be needed? // if not - we should probably add a link to more detailed help in the command description (mentioning that online help has additional options) IsHidden = true @@ -48,58 +45,50 @@ internal class VerifyCommand : ExecutableCommand private readonly Option _templateOutputPathOption = new("-o") { Name = "--output", - //TODO: localize - Description = "Specifies path to target directory to output the generated template.", + Description = LocalizableStrings.command_verify_help_outputPath_description, }; private readonly Option _expectationsDirectoryOption = new("-d") { Name = "--expectations-directory", - //TODO: localize - Description = "Specifies path to directory with expectation files.", + Description = LocalizableStrings.command_verify_help_expectationsDirPath_description, }; private readonly Option _disableDiffToolOption = new("--disable-diff-tool") { - //TODO: localize - Description = "If set to true - the diff tool won't be automatically started by the Verifier on verification failures.", + Description = LocalizableStrings.command_verify_help_disableDiffTool_description, }; private readonly Option _disableDefaultExcludePatternsOption = new("--disable-default-exclude-patterns") { - //TODO: localize - Description = "If set to true - all template output files will be verified, unless --exclude-pattern option is used.", + Description = LocalizableStrings.command_verify_help_disableDefaultExcludes_description, }; private readonly Option> _excludePatternOption = new("--exclude-pattern") { - //TODO: localize - Description = "Specifies pattern(s) defining files to be excluded from verification.", + Description = LocalizableStrings.command_verify_help_customExcludes_description, Arity = new ArgumentArity(0, 999) }; private readonly Option _verifyCommandOutputOption = new("--verify-std") { - //TODO: localize - Description = "If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.", + Description = LocalizableStrings.command_verify_help_verifyOutputs_description, }; private readonly Option _isCommandExpectedToFailOption = new("--fail-expected") { - //TODO: localize - Description = "If set to true - 'dotnet new' command is expected to return nonzero return code.", + Description = LocalizableStrings.command_verify_help_expectFailure_description, }; private readonly Option> _uniqueForOption = new("--unique-for") { - //TODO: localize - Description = "Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated.", + Description = LocalizableStrings.command_verify_help_uniqueFor_description, Arity = new ArgumentArity(0, 999), AllowMultipleArgumentsPerToken = true, }; public VerifyCommand(ILoggerFactory loggerFactory) - : base(CommandName, "Runs the template with specified arguments and compares the result with expectations files (or creates those if yet don't exist).", loggerFactory) + : base(CommandName, LocalizableStrings.command_verify_help_description, loggerFactory) { AddArgument(_templateNameArgument); AddOption(_remainingArguments); @@ -149,7 +138,7 @@ protected override async Task ExecuteAsync(VerifyCommandArgs args, Cancella } catch (Exception e) { - Reporter.Error.WriteLine("Verification Failed."); + Reporter.Error.WriteLine(LocalizableStrings.command_verify_error_failed); Logger.LogError(e.Message); TemplateVerificationException? ex = e as TemplateVerificationException; return (int)(ex?.TemplateVerificationErrorCode ?? TemplateVerificationErrorCode.InternalError); @@ -173,9 +162,8 @@ private static void ValidateAllowedValues(OptionResult optionResult, string[] al var invalidArguments = optionResult.Tokens.Where(token => !allowedValues.Append(allowedHiddenValue).Contains(token.Value, StringComparer.OrdinalIgnoreCase)).ToList(); if (invalidArguments.Any()) { - //TODO: localize optionResult.ErrorMessage = string.Format( - "Argument(s) {0} are not recognized. Must be one of: {1}.", + LocalizableStrings.command_verify_error_unrecognizedArguments, string.Join(", ", invalidArguments.Select(arg => $"'{arg.Value}'")), string.Join(", ", allowedValues.Select(allowedValue => $"'{allowedValue}'"))); } diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.Designer.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.Designer.cs index 7aab621e7c..8213e129dc 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.Designer.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.Designer.cs @@ -161,6 +161,132 @@ internal static string command_export_log_templateJsonNotFound { } } + /// + /// Looks up a localized string similar to Verification Failed.. + /// + internal static string command_verify_error_failed { + get { + return ResourceManager.GetString("command_verify_error_failed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Argument(s) {0} are not recognized. Must be one of: {1}.. + /// + internal static string command_verify_error_unrecognizedArguments { + get { + return ResourceManager.GetString("command_verify_error_unrecognizedArguments", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specifies pattern(s) defining files to be excluded from verification.. + /// + internal static string command_verify_help_customExcludes_description { + get { + return ResourceManager.GetString("command_verify_help_customExcludes_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions).. + /// + internal static string command_verify_help_description { + get { + return ResourceManager.GetString("command_verify_help_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If set to true - all template output files will be verified, unless --exclude-pattern option is used.. + /// + internal static string command_verify_help_disableDefaultExcludes_description { + get { + return ResourceManager.GetString("command_verify_help_disableDefaultExcludes_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If set to true - the diff tool won't be automatically started by the Verifier on verification failures.. + /// + internal static string command_verify_help_disableDiffTool_description { + get { + return ResourceManager.GetString("command_verify_help_disableDiffTool_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specifies path to directory with expectation files.. + /// + internal static string command_verify_help_expectationsDirPath_description { + get { + return ResourceManager.GetString("command_verify_help_expectationsDirPath_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If set to true - 'dotnet new' command is expected to return nonzero return code.. + /// + internal static string command_verify_help_expectFailure_description { + get { + return ResourceManager.GetString("command_verify_help_expectFailure_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specifies path to custom assembly implementing the new command.. + /// + internal static string command_verify_help_newCommandPath_description { + get { + return ResourceManager.GetString("command_verify_help_newCommandPath_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specifies path to target directory to output the generated template.. + /// + internal static string command_verify_help_outputPath_description { + get { + return ResourceManager.GetString("command_verify_help_outputPath_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option.. + /// + internal static string command_verify_help_templateName_description { + get { + return ResourceManager.GetString("command_verify_help_templateName_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specifies path to the directory with template to be verified.. + /// + internal static string command_verify_help_templatePath_description { + get { + return ResourceManager.GetString("command_verify_help_templatePath_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated.. + /// + internal static string command_verify_help_uniqueFor_description { + get { + return ResourceManager.GetString("command_verify_help_uniqueFor_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files.. + /// + internal static string command_verify_help_verifyOutputs_description { + get { + return ResourceManager.GetString("command_verify_help_verifyOutputs_description", resourceCulture); + } + } + /// /// Looks up a localized string similar to "{0}" command has encountered an error. See the logs for more details.. /// diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.resx b/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.resx index e4212abebc..8e240a7042 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.resx +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.resx @@ -161,6 +161,50 @@ Do not localize: "template.json" Failed to find "template.json" file under the path "{0}". Do not localize: "template.json" + + Verification Failed. + + + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + Specifies path to directory with expectation files. + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + Specifies path to custom assembly implementing the new command. + + + Specifies path to target directory to output the generated template. + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + "{0}" command has encountered an error. See the logs for more details. {0} will be replaced by the command name. Such as: "export" command has encountered an error. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.cs.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.cs.xlf index d5883f51b8..959f2037b5 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.cs.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.cs.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" Soubor „template.json“ se v cestě „{0}“ nepodařilo najít. Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. V příkazu {0} došlo k chybě. Další podrobnosti najdete v protokolech. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.de.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.de.xlf index f33dfac5c3..6690b4fe19 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.de.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.de.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" Die Datei "template.json" konnte unter dem Pfad "{0}" nicht gefunden werden. Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. Fehler beim Ausführen des Befehls "{0}". Weitere Informationen finden Sie in den Protokollen. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.es.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.es.xlf index d44b1edd42..18d5c5749b 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.es.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.es.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" No se pudo encontrar el archivo "template.json" bajo la ruta "{0}". Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. El comando "{0}" ha encontrado un error. Vea los registros para obtener más información. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.fr.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.fr.xlf index cd188c2870..71058efe03 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.fr.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.fr.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" Échec de la recherche du fichier « template.jssur » sous le chemin d’accès «0{0} ». Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. La commande « {0} » a rencontré une erreur. Pour plus d’informations, consultez les journaux. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.it.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.it.xlf index 5ebaf4a8f5..dff9c7e6cb 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.it.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.it.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" Non è stato possibile trovare il file "template.json" nel percorso "{0}". Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. Si è verificato un errore durante il comando "{0}". Per altri dettagli, vedere i log. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ja.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ja.xlf index bd5aff2f55..7e1d96bdd8 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ja.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ja.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" パス "{0}" の下に "template.json" ファイルが見つかりません。 Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. "{0}" コマンドでエラーが発生しました。詳細については、ログを参照してください。 diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ko.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ko.xlf index 86c86d09ef..d0bcf3d756 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ko.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ko.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" "{0}” 경로에서 "template.json" 파일을 찾지 못했습니다. Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. "{0}" 명령에 오류가 발생했습니다. 자세한 내용은 로그를 참조하세요. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pl.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pl.xlf index e9896887dd..f2887a6fc8 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pl.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pl.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" Nie można odnaleźć pliku „template.json” pod ścieżką „{0}”. Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. Wystąpił błąd przy poleceniu „{0}”. Zobacz dzienniki, aby uzyskać więcej szczegółów. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pt-BR.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pt-BR.xlf index b21e7dd7f7..fc387e4275 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pt-BR.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" Falhou em localizar o arquivo "template.json" no o caminho "{0}". Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. O comando "{0}" encontrou um erro. Veja os logs para mais detalhes. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ru.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ru.xlf index f8eb22b87e..51c1c492d1 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ru.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ru.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" Не удалось найти файл template.json в пути "{0}". Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. Команда "{0}" обнаружила ошибку. Дополнительные сведения см. в журналах. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.tr.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.tr.xlf index 463d3f5789..6310ff13ea 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.tr.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.tr.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" "{0}" yolunda "template.json" dosyası bulunamadı. Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. "{0}" komutu bir hatayla karşılaştı. Daha fazla ayrıntı için günlüklere bakın. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hans.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hans.xlf index b14e82f316..a6b7ff70a6 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hans.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" 在路径“{0}”下未找到“template.json”文件。 Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. “{0}”命令遇到错误。如需了解详细信息,请参阅日志。 diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hant.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hant.xlf index 4126aed756..34ce17a6f3 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hant.xlf @@ -63,6 +63,76 @@ Do not localize: "template.json" 在路徑 "{0}" 下找不到 "template.json" 檔案。 Do not localize: "template.json" + + Verification Failed. + Verification Failed. + + + + Argument(s) {0} are not recognized. Must be one of: {1}. + Argument(s) {0} are not recognized. Must be one of: {1}. + {0} and {1} is both a list of arguments + + + Specifies pattern(s) defining files to be excluded from verification. + Specifies pattern(s) defining files to be excluded from verification. + + + + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + + + + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + If set to true - all template output files will be verified, unless --exclude-pattern option is used. + + + + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + + + + If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return nonzero return code. + + + + Specifies path to directory with expectation files. + Specifies path to directory with expectation files. + + + + Specifies path to custom assembly implementing the new command. + Specifies path to custom assembly implementing the new command. + + + + Specifies path to target directory to output the generated template. + Specifies path to target directory to output the generated template. + + + + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Do not translate the '-p/--template-path' + + + Specifies path to the directory with template to be verified. + Specifies path to the directory with template to be verified. + + + + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + + + + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + + "{0}" command has encountered an error. See the logs for more details. "{0}" 命令發生錯誤。如需詳細資料,請參閱記錄檔。 diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs index 7ea58c6cc0..76efabbebe 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs @@ -61,11 +61,65 @@ internal LocalizableStrings() { } /// - /// Looks up a localized string similar to aaa. + /// Looks up a localized string similar to Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case.. /// - internal static string aaa { + internal static string engine_error_stdOutFolderExists { get { - return ResourceManager.GetString("aaa", resourceCulture); + return ResourceManager.GetString("engine_error_stdOutFolderExists", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Template name is mandatory, but was not supplied.. + /// + internal static string engine_error_templateNameMandatory { + get { + return ResourceManager.GetString("engine_error_templateNameMandatory", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unexpected error encountered.. + /// + internal static string engine_error_unexpected { + get { + return ResourceManager.GetString("engine_error_unexpected", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Template instantiation expected to pass but it had exit code {0}.. + /// + internal static string engine_error_unexpectedFail { + get { + return ResourceManager.GetString("engine_error_unexpectedFail", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Template instantiation expected to fail but it passed.. + /// + internal static string engine_error_unexpectedPass { + get { + return ResourceManager.GetString("engine_error_unexpectedPass", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}. + /// + internal static string engine_error_unexpectedStdErr { + get { + return ResourceManager.GetString("engine_error_unexpectedStdErr", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Working directory already exists and is not empty.. + /// + internal static string engine_error_workDirExists { + get { + return ResourceManager.GetString("engine_error_workDirExists", resourceCulture); } } } diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx index b29c2adf72..34bc39558b 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx @@ -117,8 +117,28 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + + + Unexpected error encountered. + + + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/ScrubbersDefinition.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/ScrubbersDefinition.cs new file mode 100644 index 0000000000..f573e6acd5 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/ScrubbersDefinition.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier; + +public class ScrubbersDefinition +{ + public static readonly ScrubbersDefinition Empty = new(); + + public ScrubbersDefinition() { } + + public ScrubbersDefinition(Action scrubber, string? extension = null) + { + this.AddScrubber(scrubber, extension); + } + + public Dictionary> ScrubersByExtension { get; private set; } = new Dictionary>(); + + public Action? GeneralScrubber { get; private set; } + + public ScrubbersDefinition AddScrubber(Action scrubber, string? extension = null) + { + if (object.ReferenceEquals(this, Empty)) + { + return new ScrubbersDefinition().AddScrubber(scrubber, extension); + } + + if (extension == null) + { + GeneralScrubber += scrubber; + } + else + { + ScrubersByExtension[extension] = scrubber; + } + + return this; + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs index 3e184dce58..b3e64edfc6 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs @@ -1,57 +1,13 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Text; using Microsoft.Extensions.Options; namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier { /// - /// Delegate signature for performing custom directory content verifications. - /// Expectable verification failures should be signaled with . - /// API provider can either perform content enumeration, skipping and scrubbing by themselves (then the second argument can be ignored) - /// or the can be awaited to get the content of files - filtered by exclusion patterns and scrubbed by scrubbers. + /// Configuration bag for the class. /// - /// - /// - /// - public delegate Task VerifyDirectory(string contentDirectory, Lazy> contentFetcher); - - public class ScrubbersDefinition - { - public static readonly ScrubbersDefinition Empty = new(); - - public ScrubbersDefinition() { } - - public ScrubbersDefinition(Action scrubber, string? extension = null) - { - this.AddScrubber(scrubber, extension); - } - - public Dictionary> ScrubersByExtension { get; private set; } = new Dictionary>(); - - public Action? GeneralScrubber { get; private set; } - - public ScrubbersDefinition AddScrubber(Action scrubber, string? extension = null) - { - if (object.ReferenceEquals(this, Empty)) - { - return new ScrubbersDefinition().AddScrubber(scrubber, extension); - } - - if (extension == null) - { - GeneralScrubber += scrubber; - } - else - { - ScrubersByExtension[extension] = scrubber; - } - - return this; - } - } - public class TemplateVerifierOptions : IOptions { /// diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs index 1a2bed2a4c..552d2b808a 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs @@ -28,7 +28,7 @@ public class VerificationEngine }; private readonly TemplateVerifierOptions _options; - private readonly /*ILogger*/ILogger _logger; + private readonly ILogger _logger; public VerificationEngine(IOptions optionsAccessor, ILogger logger) { @@ -43,6 +43,7 @@ public VerificationEngine(IOptions optionsAccessor, ILo public async Task Execute(CancellationToken cancellationToken = default) { + //TODO: add functionality for uninstalled templates from a local folder if (!string.IsNullOrEmpty(_options.TemplatePath)) { throw new TemplateVerificationException("Custom template path not yet supported.", TemplateVerificationErrorCode.InternalError); @@ -50,14 +51,14 @@ public async Task Execute(CancellationToken cancellationToken = default) if (string.IsNullOrEmpty(_options.TemplateName)) { - throw new TemplateVerificationException("Template name not supplied - but custom template path is not yet supported.", TemplateVerificationErrorCode.InternalError); + throw new TemplateVerificationException(LocalizableStrings.engine_error_templateNameMandatory, TemplateVerificationErrorCode.InternalError); } // Create temp folder and instantiate there string workingDir = _options.OutputDirectory ?? Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); if (Directory.Exists(workingDir) && Directory.EnumerateFileSystemEntries(workingDir).Any()) { - throw new TemplateVerificationException("Working directory already exists and is not empty.", TemplateVerificationErrorCode.WorkingDirectoryExists); + throw new TemplateVerificationException(LocalizableStrings.engine_error_workDirExists, TemplateVerificationErrorCode.WorkingDirectoryExists); } Directory.CreateDirectory(workingDir); @@ -89,7 +90,7 @@ public async Task Execute(CancellationToken cancellationToken = default) if (commandResult.ExitCode == 0) { throw new TemplateVerificationException( - "Template instantiation expected to fail but it passed.", + LocalizableStrings.engine_error_unexpectedPass, TemplateVerificationErrorCode.VerificationFailed); } } @@ -98,8 +99,8 @@ public async Task Execute(CancellationToken cancellationToken = default) if (commandResult.ExitCode != 0) { throw new TemplateVerificationException( - string.Format("Template instantiation expected to pass but it had exit code {0}.", commandResult.ExitCode), - TemplateVerificationErrorCode.VerificationFailed); + string.Format(LocalizableStrings.engine_error_unexpectedFail, commandResult.ExitCode), + TemplateVerificationErrorCode.InstantiationFailed); } // We do not expect stderr in passing command. @@ -108,10 +109,10 @@ public async Task Execute(CancellationToken cancellationToken = default) { throw new TemplateVerificationException( string.Format( - "Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}", + LocalizableStrings.engine_error_unexpectedStdErr, Environment.NewLine, commandResult.StdErr), - TemplateVerificationErrorCode.VerificationFailed); + TemplateVerificationErrorCode.InstantiationFailed); } } @@ -269,7 +270,7 @@ private async Task VerifyResult(TemplateVerifierOptions args, CommandResult comm { throw new TemplateVerificationException( string.Format( - "Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case", + LocalizableStrings.engine_error_stdOutFolderExists, SpecialFiles.StandardStreamsDir), TemplateVerificationErrorCode.InternalError); } @@ -305,7 +306,7 @@ await File.WriteAllTextAsync( } else { - _logger.LogError(e, "Unexpected error encountered"); + _logger.LogError(e, LocalizableStrings.engine_error_unexpected); throw; } } diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerifyDirectory.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerifyDirectory.cs new file mode 100644 index 0000000000..aa88c8b96b --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerifyDirectory.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier; + +/// +/// Delegate signature for performing custom directory content verifications. +/// Expectable verification failures should be signaled with . +/// API provider can either perform content enumeration, skipping and scrubbing by themselves (then the second argument can be ignored) +/// or the can be awaited to get the content of files - filtered by exclusion patterns and scrubbed by scrubbers. +/// +/// +/// +/// +public delegate Task VerifyDirectory(string contentDirectory, Lazy> contentFetcher); diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf index 75e9fc84e1..54e513fbfe 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf index 2fb061101d..f08dad25c2 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf index a75a48f232..f34debb9fe 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf index f84204ab79..cc46148bd2 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf index 1dbc1db926..429b9ef799 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf index ec93a33d40..90d97ede0e 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf index cd44dca432..9209db9cdb 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf index a7d351cab0..d158de1641 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf index b6731553c6..ac94c4d6d3 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf index 32811f1201..c37692a3aa 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf index 956b2b4538..53d39102ef 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf index 29f8e5c3ec..b537dffd02 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf index 872d00dd57..d165066bf3 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf @@ -2,10 +2,40 @@ - - aaa - aaa - To be deleted + + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + {0} is a folder path + + + Template name is mandatory, but was not supplied. + Template name is mandatory, but was not supplied. + + + + Unexpected error encountered. + Unexpected error encountered. + + + + Template instantiation expected to pass but it had exit code {0}. + Template instantiation expected to pass but it had exit code {0}. + {0} is an exit code number + + + Template instantiation expected to fail but it passed. + Template instantiation expected to fail but it passed. + + + + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} + {0} is newline, {1} is the standard error content + + + Working directory already exists and is not empty. + Working directory already exists and is not empty. + From f90e35d45b48b3fefcbb7e417e2bd0bde1186656 Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Fri, 30 Sep 2022 20:14:54 +0200 Subject: [PATCH 09/15] Various improvements for PR --- Microsoft.TemplateEngine.sln | 17 +- .../Commands/Verify/VerifyCommand.cs | 25 +- .../Commands/Verify/VerifyCommandArgs.cs | 25 +- .../Globals.cs | 1 + .../LocalizableStrings.Designer.cs | 16 +- .../LocalizableStrings.resx | 21 +- ...rosoft.TemplateEngine.Authoring.CLI.csproj | 8 +- .../xlf/LocalizableStrings.cs.xlf | 42 ++-- .../xlf/LocalizableStrings.de.xlf | 42 ++-- .../xlf/LocalizableStrings.es.xlf | 42 ++-- .../xlf/LocalizableStrings.fr.xlf | 42 ++-- .../xlf/LocalizableStrings.it.xlf | 42 ++-- .../xlf/LocalizableStrings.ja.xlf | 42 ++-- .../xlf/LocalizableStrings.ko.xlf | 42 ++-- .../xlf/LocalizableStrings.pl.xlf | 42 ++-- .../xlf/LocalizableStrings.pt-BR.xlf | 42 ++-- .../xlf/LocalizableStrings.ru.xlf | 42 ++-- .../xlf/LocalizableStrings.tr.xlf | 42 ++-- .../xlf/LocalizableStrings.zh-Hans.xlf | 42 ++-- .../xlf/LocalizableStrings.zh-Hant.xlf | 42 ++-- ...soft.TemplateEngine.Authoring.Tasks.csproj | 3 +- .../Assertions/CommandResultAssertions.cs | 186 --------------- .../Assertions/CommandResultExtensions.cs | 18 -- .../Commands/BasicCommand.cs | 10 +- .../Commands/DotnetCommand.cs | 8 +- .../Commands/SdkCommandSpec.cs | 6 +- .../Commands/TestCommand.cs | 25 +- .../LocalizableStrings.Designer.cs | 34 +-- .../LocalizableStrings.resx | 20 +- ...teEngine.Authoring.TemplateVerifier.csproj | 11 +- .../PublicAPI.Shipped.txt | 1 + .../PublicAPI.Unshipped.txt | 64 +++++ .../TemplateVerificationErrorCode.cs | 39 ++- .../TemplateVerifierOptions.cs | 8 +- .../VerificationEngine.cs | 225 +++++++++--------- .../VerifyDirectory.cs | 2 +- .../xlf/LocalizableStrings.cs.xlf | 26 +- .../xlf/LocalizableStrings.de.xlf | 26 +- .../xlf/LocalizableStrings.es.xlf | 26 +- .../xlf/LocalizableStrings.fr.xlf | 26 +- .../xlf/LocalizableStrings.it.xlf | 26 +- .../xlf/LocalizableStrings.ja.xlf | 26 +- .../xlf/LocalizableStrings.ko.xlf | 26 +- .../xlf/LocalizableStrings.pl.xlf | 26 +- .../xlf/LocalizableStrings.pt-BR.xlf | 26 +- .../xlf/LocalizableStrings.ru.xlf | 26 +- .../xlf/LocalizableStrings.tr.xlf | 26 +- .../xlf/LocalizableStrings.zh-Hans.xlf | 26 +- .../xlf/LocalizableStrings.zh-Hant.xlf | 26 +- .../AsyncLazy.cs | 13 + .../ExportCommandFailureTests.cs | 1 - .../VerifyCommandTests.cs | 133 ----------- ....TemplateEngine.Authoring.CLI.Tests.csproj | 14 ++ .../VerifyCommandArgsTests.cs | 25 ++ ...ne.Authoring.TemplateVerifier.Tests.csproj | 6 - .../VerificationEngineTests.cs | 48 ++-- 56 files changed, 837 insertions(+), 1060 deletions(-) delete mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultAssertions.cs delete mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultExtensions.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Shipped.txt create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt delete mode 100644 test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs create mode 100644 test/Microsoft.TemplateEngine.Authoring.CLI.Tests/Microsoft.TemplateEngine.Authoring.CLI.Tests.csproj create mode 100644 test/Microsoft.TemplateEngine.Authoring.CLI.Tests/VerifyCommandArgsTests.cs diff --git a/Microsoft.TemplateEngine.sln b/Microsoft.TemplateEngine.sln index b96016faca..2fcdf1e71b 100644 --- a/Microsoft.TemplateEngine.sln +++ b/Microsoft.TemplateEngine.sln @@ -68,7 +68,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{B794BF86 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier", "src\Microsoft.TemplateEngine.Authoring.TemplateVerifier\Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj", "{12764D81-61A7-437A-90B6-9F245E43F457}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests", "test\Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests\Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj", "{DFB18A1E-4C70-48D3-B57A-FA81B405EA04}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests", "test\Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests\Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj", "{DFB18A1E-4C70-48D3-B57A-FA81B405EA04}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.CLI.Tests", "test\Microsoft.TemplateEngine.Authoring.CLI.Tests\Microsoft.TemplateEngine.Authoring.CLI.Tests.csproj", "{F1860546-A949-4A16-ACB2-0C4C3CA2C970}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -416,6 +418,18 @@ Global {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|x64.Build.0 = Release|Any CPU {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|x86.ActiveCfg = Release|Any CPU {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|x86.Build.0 = Release|Any CPU + {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|x64.ActiveCfg = Debug|Any CPU + {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|x64.Build.0 = Debug|Any CPU + {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|x86.ActiveCfg = Debug|Any CPU + {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|x86.Build.0 = Debug|Any CPU + {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|Any CPU.Build.0 = Release|Any CPU + {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|x64.ActiveCfg = Release|Any CPU + {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|x64.Build.0 = Release|Any CPU + {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|x86.ActiveCfg = Release|Any CPU + {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -449,6 +463,7 @@ Global {2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} {12764D81-61A7-437A-90B6-9F245E43F457} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B} {DFB18A1E-4C70-48D3-B57A-FA81B405EA04} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} + {F1860546-A949-4A16-ACB2-0C4C3CA2C970} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6EA1A508-6033-4538-BF98-7F71B4E297AD} diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs index 46a89b0c83..6cb85061a2 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs @@ -4,8 +4,8 @@ using System.CommandLine; using System.CommandLine.Binding; using System.CommandLine.Parsing; -using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.TemplateEngine.Authoring.TemplateVerifier; namespace Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify @@ -14,9 +14,8 @@ internal class VerifyCommand : ExecutableCommand { private const string CommandName = "verify"; - private readonly Argument _templateNameArgument = new("-n") + private readonly Argument _templateNameArgument = new("template-short-name") { - Name = "template-short-name", Description = LocalizableStrings.command_verify_help_templateName_description, // 0 for case where only path is specified Arity = new ArgumentArity(1, 1) @@ -28,9 +27,8 @@ internal class VerifyCommand : ExecutableCommand Arity = new ArgumentArity(0, 1) }; - private readonly Option _templatePathOption = new("-p") + private readonly Option _templatePathOption = new(new[] { "-p", "--template-path" }) { - Name = "--template-path", Description = LocalizableStrings.command_verify_help_templatePath_description, }; @@ -42,15 +40,13 @@ internal class VerifyCommand : ExecutableCommand IsHidden = true }; - private readonly Option _templateOutputPathOption = new("-o") + private readonly Option _templateOutputPathOption = new(new[] { "-o", "--output" }) { - Name = "--output", Description = LocalizableStrings.command_verify_help_outputPath_description, }; - private readonly Option _expectationsDirectoryOption = new("-d") + private readonly Option _expectationsDirectoryOption = new(new[] { "-d", "--expectations-directory" }) { - Name = "--expectations-directory", Description = LocalizableStrings.command_verify_help_expectationsDirPath_description, }; @@ -80,7 +76,7 @@ internal class VerifyCommand : ExecutableCommand Description = LocalizableStrings.command_verify_help_expectFailure_description, }; - private readonly Option> _uniqueForOption = new("--unique-for") + private readonly Option> _uniqueForOption = new("--unique-for") { Description = LocalizableStrings.command_verify_help_uniqueFor_description, Arity = new ArgumentArity(0, 999), @@ -116,9 +112,8 @@ protected override async Task ExecuteAsync(VerifyCommandArgs args, Cancella try { VerificationEngine engine = new VerificationEngine( - new TemplateVerifierOptions() + new TemplateVerifierOptions(templateName: args.TemplateName) { - TemplateName = args.TemplateName, TemplatePath = args.TemplatePath, TemplateSpecificArgs = args.TemplateSpecificArgs, DisableDiffTool = args.DisableDiffTool, @@ -131,14 +126,14 @@ protected override async Task ExecuteAsync(VerifyCommandArgs args, Cancella IsCommandExpectedToFail = args.IsCommandExpectedToFail, UniqueFor = args.UniqueFor, }, - Logger + LoggerFactory ?? NullLoggerFactory.Instance ); await engine.Execute(cancellationToken).ConfigureAwait(false); return 0; } catch (Exception e) { - Reporter.Error.WriteLine(LocalizableStrings.command_verify_error_failed); + Logger.LogError(LocalizableStrings.command_verify_error_failed); Logger.LogError(e.Message); TemplateVerificationException? ex = e as TemplateVerificationException; return (int)(ex?.TemplateVerificationErrorCode ?? TemplateVerificationErrorCode.InternalError); @@ -150,7 +145,7 @@ protected override async Task ExecuteAsync(VerifyCommandArgs args, Cancella /// /// Case insensitive version for . /// - private static void FromAmongCaseInsensitive(Option> option, string[]? allowedValues = null, string? allowedHiddenValue = null) + private static void FromAmongCaseInsensitive(Option option, string[]? allowedValues = null, string? allowedHiddenValue = null) { allowedValues ??= Array.Empty(); option.AddValidator(optionResult => ValidateAllowedValues(optionResult, allowedValues, allowedHiddenValue)); diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs index e5d1407451..7f1107f985 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs @@ -12,7 +12,7 @@ namespace Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify internal sealed class VerifyCommandArgs { public VerifyCommandArgs( - string? templateName, + string templateName, string? templatePath, string? templateSpecificArgs, string? dotnetNewCommandAssemblyPath, @@ -23,7 +23,7 @@ public VerifyCommandArgs( IEnumerable? verificationExcludePatterns, bool? verifyCommandOutput, bool isCommandExpectedToFail, - IEnumerable? uniqueForOptions) + IEnumerable? uniqueForOptions) { TemplateName = templateName; TemplatePath = templatePath; @@ -36,13 +36,13 @@ public VerifyCommandArgs( VerificationExcludePatterns = verificationExcludePatterns; VerifyCommandOutput = verifyCommandOutput; IsCommandExpectedToFail = isCommandExpectedToFail; - UniqueFor = FromOptionTokens(uniqueForOptions); + UniqueFor = uniqueForOptions?.Aggregate((a, b) => a | b); } /// /// Gets the name of locally installed template. /// - public string? TemplateName { get; init; } + public string TemplateName { get; init; } /// /// Gets the path to template.json file or containing directory. @@ -136,22 +136,5 @@ private static string RemoveEnclosingQuotation(string input) return input; } } - - private static UniqueForOption? FromOptionTokens(IEnumerable? tokens) - { - if (tokens == null) - { - return null; - } - - UniqueForOption result = UniqueForOption.None; - - foreach (string token in tokens) - { - result |= Enum.Parse(token, true); - } - - return result; - } } } diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Globals.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Globals.cs index 66de30e624..9cc128d164 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Globals.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Globals.cs @@ -4,3 +4,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.TemplateEngine.Authoring.CLI.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.Designer.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.Designer.cs index 8213e129dc..815cb30209 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.Designer.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.Designer.cs @@ -189,7 +189,7 @@ internal static string command_verify_help_customExcludes_description { } /// - /// Looks up a localized string similar to Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions).. + /// Looks up a localized string similar to Runs the template with specified arguments and compares the result with expectations files.. /// internal static string command_verify_help_description { get { @@ -216,7 +216,7 @@ internal static string command_verify_help_disableDiffTool_description { } /// - /// Looks up a localized string similar to Specifies path to directory with expectation files.. + /// Looks up a localized string similar to Specifies path to the directory with expectation files.. /// internal static string command_verify_help_expectationsDirPath_description { get { @@ -225,7 +225,7 @@ internal static string command_verify_help_expectationsDirPath_description { } /// - /// Looks up a localized string similar to If set to true - 'dotnet new' command is expected to return nonzero return code.. + /// Looks up a localized string similar to If set to true - 'dotnet new' command is expected to return non-zero return code.. /// internal static string command_verify_help_expectFailure_description { get { @@ -234,7 +234,7 @@ internal static string command_verify_help_expectFailure_description { } /// - /// Looks up a localized string similar to Specifies path to custom assembly implementing the new command.. + /// Looks up a localized string similar to Specifies the path to custom assembly implementing 'dotnet new' command.. /// internal static string command_verify_help_newCommandPath_description { get { @@ -243,7 +243,7 @@ internal static string command_verify_help_newCommandPath_description { } /// - /// Looks up a localized string similar to Specifies path to target directory to output the generated template.. + /// Looks up a localized string similar to Specifies the path to target directory to output the generated template to.. /// internal static string command_verify_help_outputPath_description { get { @@ -252,7 +252,7 @@ internal static string command_verify_help_outputPath_description { } /// - /// Looks up a localized string similar to Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option.. + /// Looks up a localized string similar to Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option.. /// internal static string command_verify_help_templateName_description { get { @@ -261,7 +261,7 @@ internal static string command_verify_help_templateName_description { } /// - /// Looks up a localized string similar to Specifies path to the directory with template to be verified.. + /// Looks up a localized string similar to Specifies the path to the directory with template to be verified.. /// internal static string command_verify_help_templatePath_description { get { @@ -270,7 +270,7 @@ internal static string command_verify_help_templatePath_description { } /// - /// Looks up a localized string similar to Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated.. + /// Looks up a localized string similar to Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated.. /// internal static string command_verify_help_uniqueFor_description { get { diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.resx b/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.resx index 8e240a7042..3f760fd527 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.resx +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/LocalizableStrings.resx @@ -172,38 +172,43 @@ Do not localize: "template.json" Specifies pattern(s) defining files to be excluded from verification. - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. + Do not translate 'true'. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. - If set to true - 'dotnet new' command is expected to return nonzero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to custom assembly implementing the new command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj b/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj index c75590eee5..8250fe767c 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Microsoft.TemplateEngine.Authoring.CLI.csproj @@ -16,14 +16,14 @@ - - + + - - + + diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.cs.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.cs.xlf index 959f2037b5..d451e2ea19 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.cs.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.cs.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.de.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.de.xlf index 6690b4fe19..7f733b9dce 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.de.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.de.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.es.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.es.xlf index 18d5c5749b..a2b0f32928 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.es.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.es.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.fr.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.fr.xlf index 71058efe03..0c44da946e 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.fr.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.fr.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.it.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.it.xlf index dff9c7e6cb..492eac7bb9 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.it.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.it.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ja.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ja.xlf index 7e1d96bdd8..512acdd8c4 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ja.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ja.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ko.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ko.xlf index d0bcf3d756..c1dc26907d 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ko.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ko.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pl.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pl.xlf index f2887a6fc8..e9d66c68c6 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pl.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pl.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pt-BR.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pt-BR.xlf index fc387e4275..3663145525 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.pt-BR.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ru.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ru.xlf index 51c1c492d1..d5d79055ff 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ru.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.ru.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.tr.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.tr.xlf index 6310ff13ea..796bc4137d 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.tr.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.tr.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hans.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hans.xlf index a6b7ff70a6..d1890f2be7 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hans.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hant.xlf b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hant.xlf index 34ce17a6f3..1c6beb21fb 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/xlf/LocalizableStrings.zh-Hant.xlf @@ -79,59 +79,59 @@ Do not localize: "template.json" - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). - Runs the template with specified arguments and compares the result with expectations files (and create expectations changes suggestions). + Runs the template with specified arguments and compares the result with expectations files. + Runs the template with specified arguments and compares the result with expectations files. If set to true - all template output files will be verified, unless --exclude-pattern option is used. If set to true - all template output files will be verified, unless --exclude-pattern option is used. - + Do not translate 'true'. Do not translate '--exclude-pattern' If set to true - the diff tool won't be automatically started by the Verifier on verification failures. If set to true - the diff tool won't be automatically started by the Verifier on verification failures. - + Do not translate 'true'. - If set to true - 'dotnet new' command is expected to return nonzero return code. - If set to true - 'dotnet new' command is expected to return nonzero return code. - + If set to true - 'dotnet new' command is expected to return non-zero return code. + If set to true - 'dotnet new' command is expected to return non-zero return code. + Do not translate 'true'. Do not translate 'dotnet new' - Specifies path to directory with expectation files. - Specifies path to directory with expectation files. + Specifies path to the directory with expectation files. + Specifies path to the directory with expectation files. - Specifies path to custom assembly implementing the new command. - Specifies path to custom assembly implementing the new command. - + Specifies the path to custom assembly implementing 'dotnet new' command. + Specifies the path to custom assembly implementing 'dotnet new' command. + Do not translate 'dotnet new' - Specifies path to target directory to output the generated template. - Specifies path to target directory to output the generated template. + Specifies the path to target directory to output the generated template to. + Specifies the path to target directory to output the generated template to. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. - Name of template to be verified. Can be already installed template or template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. + Name of the template to be verified. Can be already installed template or a template within local path specified with -p/--template-path option. Do not translate the '-p/--template-path' - Specifies path to the directory with template to be verified. - Specifies path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. + Specifies the path to the directory with template to be verified. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. - Sets the Verifier expectations directory naming convention - by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. + Sets the Verifier expectations directory naming convention, by indicating which scenarios should be differentiated. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. If set to true - 'dotnet new' command standard output and error contents will be verified along with the produced template files. - + Do not translate 'true'. Do not translate 'dotnet new' "{0}" command has encountered an error. See the logs for more details. diff --git a/src/Microsoft.TemplateEngine.Authoring.Tasks/Microsoft.TemplateEngine.Authoring.Tasks.csproj b/src/Microsoft.TemplateEngine.Authoring.Tasks/Microsoft.TemplateEngine.Authoring.Tasks.csproj index 50dfede5cf..907d1c4824 100644 --- a/src/Microsoft.TemplateEngine.Authoring.Tasks/Microsoft.TemplateEngine.Authoring.Tasks.csproj +++ b/src/Microsoft.TemplateEngine.Authoring.Tasks/Microsoft.TemplateEngine.Authoring.Tasks.csproj @@ -1,4 +1,4 @@ - + $(NETStandardTargetFramework) @@ -14,7 +14,6 @@ - diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultAssertions.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultAssertions.cs deleted file mode 100644 index 591edc0145..0000000000 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultAssertions.cs +++ /dev/null @@ -1,186 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#if NET - -using System.Text.RegularExpressions; -using FluentAssertions; -using FluentAssertions.Execution; -using Microsoft.DotNet.Cli.Utils; - -namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands -{ - public class CommandResultAssertions - { - private CommandResult _commandResult; - - public CommandResultAssertions(CommandResult commandResult) - { - _commandResult = commandResult; - } - - public AndConstraint ExitWith(int expectedExitCode) - { - Execute.Assertion.ForCondition(_commandResult.ExitCode == expectedExitCode) - .FailWith(AppendDiagnosticsTo($"Expected command to exit with {expectedExitCode} but it did not.")); - return new AndConstraint(this); - } - - public AndConstraint Pass() - { - Execute.Assertion.ForCondition(_commandResult.ExitCode == 0) - .FailWith(AppendDiagnosticsTo($"Expected command to pass but it did not.")); - return new AndConstraint(this); - } - - public AndConstraint Fail() - { - Execute.Assertion.ForCondition(_commandResult.ExitCode != 0) - .FailWith(AppendDiagnosticsTo($"Expected command to fail but it did not.")); - return new AndConstraint(this); - } - - public AndConstraint HaveStdOut() - { - Execute.Assertion.ForCondition(!string.IsNullOrEmpty(_commandResult.StdOut)) - .FailWith(AppendDiagnosticsTo("Command did not output anything to stdout")); - return new AndConstraint(this); - } - - public AndConstraint HaveStdOut(string expectedOutput) - { - Execute.Assertion.ForCondition(_commandResult.StdOut.Equals(expectedOutput, StringComparison.Ordinal)) - .FailWith(AppendDiagnosticsTo($"Command did not output with Expected Output. Expected: {expectedOutput}")); - return new AndConstraint(this); - } - - public AndConstraint HaveStdOutContaining(string pattern) - { - Execute.Assertion.ForCondition(_commandResult.StdOut.Contains(pattern)) - .FailWith(AppendDiagnosticsTo($"The command output did not contain expected result: {pattern}{Environment.NewLine}")); - return new AndConstraint(this); - } - - public AndConstraint HaveStdOutContaining(Func predicate, string description = "") - { - Execute.Assertion.ForCondition(predicate(_commandResult.StdOut)) - .FailWith(AppendDiagnosticsTo($"The command output did not contain expected result: {description} {Environment.NewLine}")); - return new AndConstraint(this); - } - - public AndConstraint NotHaveStdOutContaining(string pattern) - { - Execute.Assertion.ForCondition(!_commandResult.StdOut.Contains(pattern)) - .FailWith(AppendDiagnosticsTo($"The command output contained a result it should not have contained: {pattern}{Environment.NewLine}")); - return new AndConstraint(this); - } - - public AndConstraint HaveStdOutContainingIgnoreSpaces(string pattern) - { - string commandResultNoSpaces = _commandResult.StdOut.Replace(" ", ""); - - Execute.Assertion - .ForCondition(commandResultNoSpaces.Contains(pattern)) - .FailWith(AppendDiagnosticsTo($"The command output did not contain expected result: {pattern}{Environment.NewLine}")); - - return new AndConstraint(this); - } - - public AndConstraint HaveStdOutContainingIgnoreCase(string pattern) - { - Execute.Assertion.ForCondition(_commandResult.StdOut.Contains(pattern, StringComparison.OrdinalIgnoreCase)) - .FailWith(AppendDiagnosticsTo($"The command output did not contain expected result (ignoring case): {pattern}{Environment.NewLine}")); - return new AndConstraint(this); - } - - public AndConstraint HaveStdOutMatching(string pattern, RegexOptions options = RegexOptions.None) - { - Execute.Assertion.ForCondition(Regex.Match(_commandResult.StdOut, pattern, options).Success) - .FailWith(AppendDiagnosticsTo($"Matching the command output failed. Pattern: {pattern}{Environment.NewLine}")); - return new AndConstraint(this); - } - - public AndConstraint NotHaveStdOutMatching(string pattern, RegexOptions options = RegexOptions.None) - { - Execute.Assertion.ForCondition(!Regex.Match(_commandResult.StdOut, pattern, options).Success) - .FailWith(AppendDiagnosticsTo($"The command output matched a pattern it should not have. Pattern: {pattern}{Environment.NewLine}")); - return new AndConstraint(this); - } - - public AndConstraint HaveStdErr() - { - Execute.Assertion.ForCondition(!string.IsNullOrEmpty(_commandResult.StdErr)) - .FailWith(AppendDiagnosticsTo("Command did not output anything to StdErr.")); - return new AndConstraint(this); - } - - public AndConstraint HaveStdErr(string expectedOutput) - { - Execute.Assertion.ForCondition(_commandResult.StdErr.Equals(expectedOutput, StringComparison.Ordinal)) - .FailWith(AppendDiagnosticsTo($"Command did not output the expected output to StdErr.{Environment.NewLine}Expected: {expectedOutput}{Environment.NewLine}Actual: {_commandResult.StdErr}")); - return new AndConstraint(this); - } - - public AndConstraint HaveStdErrContaining(string pattern) - { - Execute.Assertion.ForCondition(_commandResult.StdErr.Contains(pattern)) - .FailWith(AppendDiagnosticsTo($"The command error output did not contain expected result: {pattern}{Environment.NewLine}")); - return new AndConstraint(this); - } - - public AndConstraint NotHaveStdErrContaining(string pattern) - { - Execute.Assertion.ForCondition(!_commandResult.StdErr.Contains(pattern)) - .FailWith(AppendDiagnosticsTo($"The command error output contained a result it should not have contained: {pattern}{Environment.NewLine}")); - return new AndConstraint(this); - } - - public AndConstraint HaveStdErrMatching(string pattern, RegexOptions options = RegexOptions.None) - { - Execute.Assertion.ForCondition(Regex.Match(_commandResult.StdErr, pattern, options).Success) - .FailWith(AppendDiagnosticsTo($"Matching the command error output failed. Pattern: {pattern}{Environment.NewLine}")); - return new AndConstraint(this); - } - - public AndConstraint NotHaveStdOut() - { - Execute.Assertion.ForCondition(string.IsNullOrEmpty(_commandResult.StdOut)) - .FailWith(AppendDiagnosticsTo($"Expected command to not output to stdout but it was not:")); - return new AndConstraint(this); - } - - public AndConstraint NotHaveStdErr() - { - Execute.Assertion.ForCondition(string.IsNullOrEmpty(_commandResult.StdErr)) - .FailWith(AppendDiagnosticsTo("Expected command to not output to stderr but it was not:")); - return new AndConstraint(this); - } - - public AndConstraint HaveSkippedProjectCompilation(string skippedProject, string frameworkFullName) - { - _commandResult.StdOut.Should().Contain($"Project {skippedProject} ({frameworkFullName}) was previously compiled. Skipping compilation."); - - return new AndConstraint(this); - } - - public AndConstraint HaveCompiledProject(string compiledProject, string frameworkFullName) - { - _commandResult.StdOut.Should().Contain($"Project {compiledProject} ({frameworkFullName}) will be compiled"); - - return new AndConstraint(this); - } - - private string AppendDiagnosticsTo(string s) - { - return (s + $"{Environment.NewLine}" + - $"File Name: {_commandResult.StartInfo.FileName}{Environment.NewLine}" + - $"Arguments: {_commandResult.StartInfo.Arguments}{Environment.NewLine}" + - $"Exit Code: {_commandResult.ExitCode}{Environment.NewLine}" + - $"StdOut:{Environment.NewLine}{_commandResult.StdOut}{Environment.NewLine}" + - $"StdErr:{Environment.NewLine}{_commandResult.StdErr}{Environment.NewLine}") - //escape curly braces for String.Format - .Replace("{", "{{").Replace("}", "}}"); - } - } -} -#endif diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultExtensions.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultExtensions.cs deleted file mode 100644 index 88c2e13344..0000000000 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/Assertions/CommandResultExtensions.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#if NET - -using Microsoft.DotNet.Cli.Utils; - -namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands -{ - public static class CommandResultExtensions - { - public static CommandResultAssertions Should(this CommandResult commandResult) - { - return new CommandResultAssertions(commandResult); - } - } -} -#endif diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/BasicCommand.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/BasicCommand.cs index 7554f494b1..7e37d7e992 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/BasicCommand.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/BasicCommand.cs @@ -1,18 +1,15 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NET -using System.Collections.Generic; -using System.Linq; -using Xunit.Abstractions; +using Microsoft.Extensions.Logging; namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands { - public class BasicCommand : TestCommand + internal class BasicCommand : TestCommand { private readonly string _processName; - public BasicCommand(ITestOutputHelper log, string processName, params string[] args) : base(log) + public BasicCommand(ILogger log, string processName, params string[] args) : base(log) { _processName = processName; Arguments.AddRange(args.Where(a => !string.IsNullOrWhiteSpace(a))); @@ -30,4 +27,3 @@ protected override SdkCommandSpec CreateCommand(IEnumerable args) } } } -#endif diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/DotnetCommand.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/DotnetCommand.cs index e18fb00c05..db84430f22 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/DotnetCommand.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/DotnetCommand.cs @@ -1,16 +1,15 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NET -using Xunit.Abstractions; +using Microsoft.Extensions.Logging; namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands { - public class DotnetCommand : TestCommand + internal class DotnetCommand : TestCommand { private readonly string commandName; - public DotnetCommand(ITestOutputHelper log, string commandName, params string[] args) : base(log) + public DotnetCommand(ILogger log, string commandName, params string[] args) : base(log) { Arguments.Add(commandName); Arguments.AddRange(args); @@ -44,4 +43,3 @@ private static string CreateTemporaryFolder(string name = "") } } } -#endif diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/SdkCommandSpec.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/SdkCommandSpec.cs index 8cdb500cc0..1d8b34f50f 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/SdkCommandSpec.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/SdkCommandSpec.cs @@ -1,15 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NET - -using System.Collections.Generic; using System.Diagnostics; using Microsoft.DotNet.Cli.Utils; namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands { - public class SdkCommandSpec + internal class SdkCommandSpec { public string? FileName { get; set; } @@ -62,4 +59,3 @@ private string EscapeArgs() } } } -#endif diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs index fb54e8975b..09d22972a4 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs @@ -1,25 +1,20 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#if NET - -using System; -using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using Microsoft.DotNet.Cli.Utils; -using Xunit.Abstractions; +using Microsoft.Extensions.Logging; namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands { - public abstract class TestCommand + internal abstract class TestCommand { - protected TestCommand(ITestOutputHelper log) + protected TestCommand(ILogger log) { Log = log; } - public ITestOutputHelper Log { get; } + public ILogger Log { get; } public string? WorkingDirectory { get; set; } @@ -75,19 +70,18 @@ public virtual CommandResult Execute(IEnumerable args) var result = ((Command)command).Execute(ProcessStartedHandler); - Log.WriteLine($"> {result.StartInfo.FileName} {result.StartInfo.Arguments}"); - Log.WriteLine(result.StdOut); + Log.LogInformation($"> {result.StartInfo.FileName} {result.StartInfo.Arguments}"); + Log.LogInformation(result.StdOut); if (!string.IsNullOrEmpty(result.StdErr)) { - Log.WriteLine(""); - Log.WriteLine("StdErr:"); - Log.WriteLine(result.StdErr); + Log.LogInformation("StdErr:"); + Log.LogInformation(result.StdErr); } if (result.ExitCode != 0) { - Log.WriteLine($"Exit Code: {result.ExitCode}"); + Log.LogInformation($"Exit Code: {result.ExitCode}"); } return result; @@ -122,4 +116,3 @@ private SdkCommandSpec CreateCommandSpec(IEnumerable args) } } } -#endif diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs index 76efabbebe..dddd4bc996 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs @@ -61,65 +61,65 @@ internal LocalizableStrings() { } /// - /// Looks up a localized string similar to Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case.. + /// Looks up a localized string similar to The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.. /// - internal static string engine_error_stdOutFolderExists { + internal static string VerificationEngine_Error_StdOutFolderExists { get { - return ResourceManager.GetString("engine_error_stdOutFolderExists", resourceCulture); + return ResourceManager.GetString("VerificationEngine_Error_StdOutFolderExists", resourceCulture); } } /// /// Looks up a localized string similar to Template name is mandatory, but was not supplied.. /// - internal static string engine_error_templateNameMandatory { + internal static string VerificationEngine_Error_TemplateNameMandatory { get { - return ResourceManager.GetString("engine_error_templateNameMandatory", resourceCulture); + return ResourceManager.GetString("VerificationEngine_Error_TemplateNameMandatory", resourceCulture); } } /// /// Looks up a localized string similar to Unexpected error encountered.. /// - internal static string engine_error_unexpected { + internal static string VerificationEngine_Error_Unexpected { get { - return ResourceManager.GetString("engine_error_unexpected", resourceCulture); + return ResourceManager.GetString("VerificationEngine_Error_Unexpected", resourceCulture); } } /// - /// Looks up a localized string similar to Template instantiation expected to pass but it had exit code {0}.. + /// Looks up a localized string similar to Template instantiation expected to pass but it had exit code '{0}'.. /// - internal static string engine_error_unexpectedFail { + internal static string VerificationEngine_Error_UnexpectedFail { get { - return ResourceManager.GetString("engine_error_unexpectedFail", resourceCulture); + return ResourceManager.GetString("VerificationEngine_Error_UnexpectedFail", resourceCulture); } } /// /// Looks up a localized string similar to Template instantiation expected to fail but it passed.. /// - internal static string engine_error_unexpectedPass { + internal static string VerificationEngine_Error_UnexpectedPass { get { - return ResourceManager.GetString("engine_error_unexpectedPass", resourceCulture); + return ResourceManager.GetString("VerificationEngine_Error_UnexpectedPass", resourceCulture); } } /// /// Looks up a localized string similar to Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1}. /// - internal static string engine_error_unexpectedStdErr { + internal static string VerificationEngine_Error_UnexpectedStdErr { get { - return ResourceManager.GetString("engine_error_unexpectedStdErr", resourceCulture); + return ResourceManager.GetString("VerificationEngine_Error_UnexpectedStdErr", resourceCulture); } } /// - /// Looks up a localized string similar to Working directory already exists and is not empty.. + /// Looks up a localized string similar to The working directory already exists and is not empty.. /// - internal static string engine_error_workDirExists { + internal static string VerificationEngine_Error_WorkDirExists { get { - return ResourceManager.GetString("engine_error_workDirExists", resourceCulture); + return ResourceManager.GetString("VerificationEngine_Error_WorkDirExists", resourceCulture); } } } diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx index 34bc39558b..25d6314a17 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx @@ -117,28 +117,28 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. - + Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. + + The working directory already exists and is not empty. \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj index f1842c44f7..8a30a6cf50 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj @@ -3,20 +3,21 @@ Library $(NETCoreTargetFramework) - A dotnet templating verification engine. + The verification engine for the templates for .NET template engine. true enable enable - true + true + true - - + + @@ -25,7 +26,7 @@ - + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Shipped.txt b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Shipped.txt new file mode 100644 index 0000000000..ab058de62d --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt new file mode 100644 index 0000000000..cd8f7bac1b --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt @@ -0,0 +1,64 @@ +Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition +Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.AddScrubber(System.Action! scrubber, string? extension = null) -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition! +Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.GeneralScrubber.get -> System.Action? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.ScrubbersDefinition() -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.ScrubbersDefinition(System.Action! scrubber, string? extension = null) -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.ScrubersByExtension.get -> System.Collections.Generic.Dictionary!>! +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InstantiationFailed = 100 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InternalError = 70 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.TemplateDoesNotExist = 103 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.VerificationFailed = 65 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.WorkingDirectoryExists = 73 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationException +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationException.TemplateVerificationErrorCode.get -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationException.TemplateVerificationErrorCode.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationException.TemplateVerificationException(string! message, Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode templateVerificationErrorCode) -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationException.TemplateVerificationException(string! message, Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode templateVerificationErrorCode, System.Exception! inner) -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationException.TemplateVerificationException(System.Runtime.Serialization.SerializationInfo! info, System.Runtime.Serialization.StreamingContext context) -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.CustomDirectoryVerifier.get -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerifyDirectory? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.CustomScrubbers.get -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.DisableDefaultVerificationExcludePatterns.get -> bool? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.DisableDefaultVerificationExcludePatterns.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.DisableDiffTool.get -> bool? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.DisableDiffTool.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.DotnetNewCommandAssemblyPath.get -> string? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.DotnetNewCommandAssemblyPath.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.ExpectationsDirectory.get -> string? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.ExpectationsDirectory.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.IsCommandExpectedToFail.get -> bool? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.IsCommandExpectedToFail.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.OutputDirectory.get -> string? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.OutputDirectory.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.StandardOutputFileExtension.get -> string? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.StandardOutputFileExtension.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplateName.get -> string! +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplateName.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplatePath.get -> string? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplatePath.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplateSpecificArgs.get -> System.Collections.Generic.IEnumerable? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplateSpecificArgs.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.TemplateVerifierOptions(string! templateName) -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.UniqueFor.get -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.UniqueFor.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.VerificationExcludePatterns.get -> System.Collections.Generic.IEnumerable? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.VerificationExcludePatterns.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.VerifyCommandOutput.get -> bool? +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.VerifyCommandOutput.init -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.WithCustomDirectoryVerifier(Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerifyDirectory! verifier) -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions! +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions.WithCustomScrubbers(Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition! scrubbers) -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions! +Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption +Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.Architecture = 1 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption +Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.None = 0 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption +Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.OsPlatform = 2 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption +Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.Runtime = 4 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption +Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.RuntimeAndVersion = 8 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption +Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.TargetFramework = 16 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption +Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.TargetFrameworkAndVersion = 32 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption +Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine +Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine.Execute(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! +Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine.VerificationEngine(Microsoft.Extensions.Options.IOptions! optionsAccessor, Microsoft.Extensions.Logging.ILogger! logger) -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine.VerificationEngine(Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions! options, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerifyDirectory +static readonly Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.Empty -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition! \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs index cc3e3c816f..bf400a27d6 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs @@ -3,12 +3,41 @@ namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier { + /// + /// VerificationEngine error codes in thrown . Correspond to VerificationCommand exit codes. + /// + /// Exit codes based on + /// * https://tldp.org/LDP/abs/html/exitcodes.html + /// * https://github.com/openbsd/src/blob/master/include/sysexits.h. + /// related reference: dotnet new exit codes: https://aka.ms/templating-exit-codes. + /// Future exit codes should be allocated in a range of 107 - 113. If not sufficient, a range of 79 - 99 may be used as well. + /// public enum TemplateVerificationErrorCode { - WorkingDirectoryExists = 1, - TemplateDoesNotExist = 1, - InstantiationFailed = 1, - VerificationFailed = 1, - InternalError = 1, + /// + /// Indicates failed verification - assertions defined for the scenarios were not met. + /// E.g. unexpected exit code, stdout/stderr output or created templates content. + /// + VerificationFailed = 65, + + /// + /// Unexpected internal error in . This might indicate a bug. + /// + InternalError = 70, + + /// + /// Configured working directory already exists and is not empty - so instantiation cannot proceed without destructive changes. + /// + WorkingDirectoryExists = 73, + + /// + /// Selected template (via name or path) was not found. + /// + TemplateDoesNotExist = 103, + + /// + /// The template instantiation failed and results were not created. + /// + InstantiationFailed = 100, } } diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs index b3e64edfc6..e425cac20b 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerifierOptions.cs @@ -10,10 +10,16 @@ namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier /// public class TemplateVerifierOptions : IOptions { + /// + /// Initializes a new instance of the class. + /// + /// + public TemplateVerifierOptions(string templateName) => TemplateName = templateName; + /// /// Gets the name of locally installed template. /// - public string? TemplateName { get; init; } + public string TemplateName { get; init; } /// /// Gets the path to template.json file or containing directory. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs index 552d2b808a..7a31a6c607 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs @@ -9,7 +9,6 @@ using Microsoft.Extensions.Options; using Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands; using Microsoft.TemplateEngine.Utils; -using Xunit.Abstractions; namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier { @@ -29,6 +28,14 @@ public class VerificationEngine private readonly TemplateVerifierOptions _options; private readonly ILogger _logger; + private readonly ILoggerFactory? _loggerFactory; + + static VerificationEngine() + { + // Customize diff output of verifier + VerifyDiffPlex.Initialize(OutputType.Compact); + VerifierSettings.UseSplitModeForUniqueDirectory(); + } public VerificationEngine(IOptions optionsAccessor, ILogger logger) { @@ -41,6 +48,12 @@ public VerificationEngine(IOptions optionsAccessor, ILo _logger = logger; } + public VerificationEngine(TemplateVerifierOptions options, ILoggerFactory loggerFactory) + : this(options, loggerFactory.CreateLogger(typeof(VerificationEngine))) + { + _loggerFactory = loggerFactory; + } + public async Task Execute(CancellationToken cancellationToken = default) { //TODO: add functionality for uninstalled templates from a local folder @@ -49,48 +62,14 @@ public async Task Execute(CancellationToken cancellationToken = default) throw new TemplateVerificationException("Custom template path not yet supported.", TemplateVerificationErrorCode.InternalError); } - if (string.IsNullOrEmpty(_options.TemplateName)) - { - throw new TemplateVerificationException(LocalizableStrings.engine_error_templateNameMandatory, TemplateVerificationErrorCode.InternalError); - } - - // Create temp folder and instantiate there - string workingDir = _options.OutputDirectory ?? Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - if (Directory.Exists(workingDir) && Directory.EnumerateFileSystemEntries(workingDir).Any()) - { - throw new TemplateVerificationException(LocalizableStrings.engine_error_workDirExists, TemplateVerificationErrorCode.WorkingDirectoryExists); - } - - Directory.CreateDirectory(workingDir); - - List cmdArgs = new(); - if (!string.IsNullOrEmpty(_options.DotnetNewCommandAssemblyPath)) - { - cmdArgs.Add(_options.DotnetNewCommandAssemblyPath); - } - cmdArgs.Add("new"); - cmdArgs.Add(_options.TemplateName); - if (_options.TemplateSpecificArgs != null) - { - cmdArgs.AddRange(_options.TemplateSpecificArgs); - } - cmdArgs.Add("--debug:ephemeral-hive"); - // let's make sure the template outputs are named deterministically - cmdArgs.Add("-n"); - cmdArgs.Add(_options.TemplateName); - - // TODO: export and use impl from sdk - CommandResult commandResult = - new DotnetCommand(new LoggerProxy(_logger), "dotnet", cmdArgs.ToArray()) - .WithWorkingDirectory(workingDir) - .Execute(); + CommandResult commandResult = RunDotnetNewCommand(_options, _loggerFactory, _logger); if (_options.IsCommandExpectedToFail ?? false) { if (commandResult.ExitCode == 0) { throw new TemplateVerificationException( - LocalizableStrings.engine_error_unexpectedPass, + LocalizableStrings.VerificationEngine_Error_UnexpectedPass, TemplateVerificationErrorCode.VerificationFailed); } } @@ -99,7 +78,7 @@ public async Task Execute(CancellationToken cancellationToken = default) if (commandResult.ExitCode != 0) { throw new TemplateVerificationException( - string.Format(LocalizableStrings.engine_error_unexpectedFail, commandResult.ExitCode), + string.Format(LocalizableStrings.VerificationEngine_Error_UnexpectedFail, commandResult.ExitCode), TemplateVerificationErrorCode.InstantiationFailed); } @@ -109,7 +88,7 @@ public async Task Execute(CancellationToken cancellationToken = default) { throw new TemplateVerificationException( string.Format( - LocalizableStrings.engine_error_unexpectedStdErr, + LocalizableStrings.VerificationEngine_Error_UnexpectedStdErr, Environment.NewLine, commandResult.StdErr), TemplateVerificationErrorCode.InstantiationFailed); @@ -130,43 +109,49 @@ private static string EncodeArgsAsPath(IEnumerable? args) return r.Replace(string.Join('#', args), string.Empty); } - private static void DummyMethod() - { } - - private static async IAsyncEnumerable<(string FilePath, string ScrubbedContent)> GetVerificationContent(string contentDir, List globs, ScrubbersDefinition? scrubbers) + private static CommandResult RunDotnetNewCommand(TemplateVerifierOptions options, ILoggerFactory? loggerFactory, ILogger logger) { - foreach (string filePath in Directory.EnumerateFiles(contentDir, "*", SearchOption.AllDirectories)) + //TODO: add functionality for uninstalled templates from a local folder + if (!string.IsNullOrEmpty(options.TemplatePath)) { - if (globs.Any(g => g.IsMatch(filePath))) - { - continue; - } - - string content = await File.ReadAllTextAsync(filePath).ConfigureAwait(false); - - if (scrubbers != null) - { - string extension = Path.GetExtension(filePath); + throw new TemplateVerificationException("Custom template path not yet supported.", TemplateVerificationErrorCode.InternalError); + } - if (string.IsNullOrEmpty(extension) || !scrubbers.ScrubersByExtension.TryGetValue(extension, out Action? scrubber)) - { - scrubber = scrubbers.GeneralScrubber; - } + // Create temp folder and instantiate there + string workingDir = options.OutputDirectory ?? Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + if (Directory.Exists(workingDir) && Directory.EnumerateFileSystemEntries(workingDir).Any()) + { + throw new TemplateVerificationException(LocalizableStrings.VerificationEngine_Error_WorkDirExists, TemplateVerificationErrorCode.WorkingDirectoryExists); + } - if (scrubber != null) - { - var sb = new StringBuilder(content); - scrubber(sb); - content = sb.ToString(); - } - } + Directory.CreateDirectory(workingDir); - yield return new(filePath, content); + List cmdArgs = new(); + if (!string.IsNullOrEmpty(options.DotnetNewCommandAssemblyPath)) + { + cmdArgs.Add(options.DotnetNewCommandAssemblyPath); + } + cmdArgs.Add("new"); + cmdArgs.Add(options.TemplateName); + if (options.TemplateSpecificArgs != null) + { + cmdArgs.AddRange(options.TemplateSpecificArgs); } + cmdArgs.Add("--debug:ephemeral-hive"); + // let's make sure the template outputs are named deterministically + cmdArgs.Add("-n"); + cmdArgs.Add(options.TemplateName); + + // TODO: export and use impl from sdk + return new DotnetCommand(loggerFactory?.CreateLogger(typeof(DotnetCommand)) ?? logger, "dotnet", cmdArgs.ToArray()) + .WithWorkingDirectory(workingDir) + .Execute(); } - private static Task CreateVerificationTask(string contentDir, TemplateVerifierOptions options) + private static Task CreateVerificationTask(CommandResult commandResult, TemplateVerifierOptions options) { + string contentDir = commandResult.StartInfo.WorkingDirectory; + List exclusionsList = (options.DisableDefaultVerificationExcludePatterns ?? false) ? new() : new(_defaultVerificationExcludePatterns); @@ -178,36 +163,32 @@ private static Task CreateVerificationTask(string contentDir, TemplateVerifierOp List globs = exclusionsList.Select(pattern => Glob.Parse(pattern)).ToList(); - SettingsTask defaultVerifyTask = Verifier.VerifyDirectory( - contentDir, - (filePath) => !globs.Any(g => g.IsMatch(filePath))); + if (options.CustomDirectoryVerifier != null) + { + return options.CustomDirectoryVerifier( + contentDir, + new Lazy>( + GetVerificationContent(contentDir, globs, options.CustomScrubbers))); + } + + VerifySettings verifySettings = new(); if (options.CustomScrubbers != null) { if (options.CustomScrubbers.GeneralScrubber != null) { - defaultVerifyTask = defaultVerifyTask.AddScrubber(options.CustomScrubbers.GeneralScrubber); + verifySettings.AddScrubber(options.CustomScrubbers.GeneralScrubber); } foreach (var pair in options.CustomScrubbers.ScrubersByExtension) { - defaultVerifyTask = defaultVerifyTask.AddScrubber(pair.Key, pair.Value); + verifySettings.AddScrubber(pair.Key, pair.Value); } } - if (options.CustomDirectoryVerifier != null) - { - return options.CustomDirectoryVerifier( - contentDir, - new Lazy>( - GetVerificationContent(contentDir, globs, options.CustomScrubbers))); - } - - Verifier.DerivePathInfo( - (sourceFile, projectDirectory, type, method) => new( - directory: options.ExpectationsDirectory ?? "VerifyExpectations", - typeName: options.TemplateName, - methodName: EncodeArgsAsPath(options.TemplateSpecificArgs))); + verifySettings.UseTypeName(options.TemplateName); + verifySettings.UseDirectory(options.ExpectationsDirectory ?? "VerifyExpectations"); + verifySettings.UseMethodName(EncodeArgsAsPath(options.TemplateSpecificArgs)); if ((options.UniqueFor ?? UniqueForOption.None) != UniqueForOption.None) { @@ -220,22 +201,22 @@ private static Task CreateVerificationTask(string contentDir, TemplateVerifierOp case UniqueForOption.None: break; case UniqueForOption.Architecture: - defaultVerifyTask = defaultVerifyTask.UniqueForArchitecture(); + verifySettings.UniqueForArchitecture(); break; case UniqueForOption.OsPlatform: - defaultVerifyTask = defaultVerifyTask.UniqueForOSPlatform(); + verifySettings.UniqueForOSPlatform(); break; case UniqueForOption.Runtime: - defaultVerifyTask = defaultVerifyTask.UniqueForRuntime(); + verifySettings.UniqueForRuntime(); break; case UniqueForOption.RuntimeAndVersion: - defaultVerifyTask = defaultVerifyTask.UniqueForRuntimeAndVersion(); + verifySettings.UniqueForRuntimeAndVersion(); break; case UniqueForOption.TargetFramework: - defaultVerifyTask = defaultVerifyTask.UniqueForTargetFramework(); + verifySettings.UniqueForTargetFramework(); break; case UniqueForOption.TargetFrameworkAndVersion: - defaultVerifyTask = defaultVerifyTask.UniqueForTargetFrameworkAndVersion(); + verifySettings.UniqueForTargetFrameworkAndVersion(); break; default: throw new ArgumentOutOfRangeException(); @@ -246,17 +227,52 @@ private static Task CreateVerificationTask(string contentDir, TemplateVerifierOp if (options.DisableDiffTool ?? false) { - defaultVerifyTask = defaultVerifyTask.DisableDiff(); + verifySettings.DisableDiff(); } - return defaultVerifyTask; + return Verifier.VerifyDirectory( + contentDir, + (filePath) => !globs.Any(g => g.IsMatch(filePath)), + settings: verifySettings); } - private async Task VerifyResult(TemplateVerifierOptions args, CommandResult commandResult) + private static void DummyMethod() + { } + + private static async IAsyncEnumerable<(string FilePath, string ScrubbedContent)> GetVerificationContent(string contentDir, List globs, ScrubbersDefinition? scrubbers) { - // Customize diff output of verifier - VerifyDiffPlex.Initialize(OutputType.Compact); + foreach (string filePath in Directory.EnumerateFiles(contentDir, "*", SearchOption.AllDirectories)) + { + if (globs.Any(g => g.IsMatch(filePath))) + { + continue; + } + + string content = await File.ReadAllTextAsync(filePath).ConfigureAwait(false); + + if (scrubbers != null) + { + string extension = Path.GetExtension(filePath); + if (string.IsNullOrEmpty(extension) || !scrubbers.ScrubersByExtension.TryGetValue(extension, out Action? scrubber)) + { + scrubber = scrubbers.GeneralScrubber; + } + + if (scrubber != null) + { + var sb = new StringBuilder(content); + scrubber(sb); + content = sb.ToString(); + } + } + + yield return new(filePath, content); + } + } + + private async Task VerifyResult(TemplateVerifierOptions args, CommandResult commandResult) + { UsesVerifyAttribute a = new UsesVerifyAttribute(); // https://github.com/VerifyTests/Verify/blob/d8cbe38f527d6788ecadd6205c82803bec3cdfa6/src/Verify.Xunit/Verifier.cs#L10 // need to simulate execution from tests @@ -270,7 +286,7 @@ private async Task VerifyResult(TemplateVerifierOptions args, CommandResult comm { throw new TemplateVerificationException( string.Format( - LocalizableStrings.engine_error_stdOutFolderExists, + LocalizableStrings.VerificationEngine_Error_StdOutFolderExists, SpecialFiles.StandardStreamsDir), TemplateVerificationErrorCode.InternalError); } @@ -288,7 +304,7 @@ await File.WriteAllTextAsync( .ConfigureAwait(false); } - Task verifyTask = CreateVerificationTask(commandResult.StartInfo.WorkingDirectory, args); + Task verifyTask = CreateVerificationTask(commandResult, args); try { @@ -306,7 +322,7 @@ await File.WriteAllTextAsync( } else { - _logger.LogError(e, LocalizableStrings.engine_error_unexpected); + _logger.LogError(e, LocalizableStrings.VerificationEngine_Error_Unexpected); throw; } } @@ -320,16 +336,5 @@ private static class SpecialFiles public const string DefaultExtension = ".txt"; public static readonly string[] FileNames = { StdOut, StdErr }; } - - private class LoggerProxy : ITestOutputHelper - { - private readonly ILogger _logger; - - public LoggerProxy(ILogger logger) => _logger = logger; - - public void WriteLine(string message) => _logger.LogInformation(message); - - public void WriteLine(string format, params object[] args) => _logger.LogInformation(format, args); - } } } diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerifyDirectory.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerifyDirectory.cs index aa88c8b96b..9612b2054c 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerifyDirectory.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerifyDirectory.cs @@ -7,7 +7,7 @@ namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier; /// Delegate signature for performing custom directory content verifications. /// Expectable verification failures should be signaled with . /// API provider can either perform content enumeration, skipping and scrubbing by themselves (then the second argument can be ignored) -/// or the can be awaited to get the content of files - filtered by exclusion patterns and scrubbed by scrubbers. +/// or the contentFetcher can be awaited to get the content of files - filtered by exclusion patterns and scrubbed by scrubbers. /// /// /// diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf index 54e513fbfe..186b420638 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf index f08dad25c2..6e0d509bd2 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf index f34debb9fe..5cdaeff6ce 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf index cc46148bd2..b3868ea18b 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf index 429b9ef799..9619369dc3 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf index 90d97ede0e..7252afff82 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf index 9209db9cdb..995943df35 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf index d158de1641..9abbb748f4 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf index ac94c4d6d3..a8b6fabcf8 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf index c37692a3aa..3b0ae3dbe7 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf index 53d39102ef..14ebad690a 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf index b537dffd02..2161abc83b 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf index d165066bf3..f445685cd8 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf @@ -2,39 +2,39 @@ - - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. - Folder [{0}] not expected to exist in the template output - cannot verify stdout/stderr in such case. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path - + Template name is mandatory, but was not supplied. Template name is mandatory, but was not supplied. - + Unexpected error encountered. Unexpected error encountered. - - Template instantiation expected to pass but it had exit code {0}. - Template instantiation expected to pass but it had exit code {0}. + + Template instantiation expected to pass but it had exit code '{0}'. + Template instantiation expected to pass but it had exit code '{0}'. {0} is an exit code number - + Template instantiation expected to fail but it passed. Template instantiation expected to fail but it passed. - + Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} Template instantiation expected not to have any stderr output, but stderr output was encountered:{0}{1} {0} is newline, {1} is the standard error content - - Working directory already exists and is not empty. - Working directory already exists and is not empty. + + The working directory already exists and is not empty. + The working directory already exists and is not empty. diff --git a/src/Microsoft.TemplateEngine.Utils/AsyncLazy.cs b/src/Microsoft.TemplateEngine.Utils/AsyncLazy.cs index 7616ff17f3..e7e5faef33 100644 --- a/src/Microsoft.TemplateEngine.Utils/AsyncLazy.cs +++ b/src/Microsoft.TemplateEngine.Utils/AsyncLazy.cs @@ -15,16 +15,29 @@ namespace Microsoft.TemplateEngine.Utils public class AsyncLazy : Lazy> { // inspired by https://devblogs.microsoft.com/pfxteam/asynclazyt/ + + /// + /// Creates a lazy type that performs the value construction asynchronously on a first access. + /// + /// Synchronous value factory that will be executed asynchronously on first access in separate task. public AsyncLazy(Func valueFactory) : base(() => Task.Factory.StartNew(valueFactory, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default)) { } + /// + /// Creates a lazy type that performs the value construction asynchronously on a first access. + /// + /// Asynchronous value factory that will be executed on a first access. public AsyncLazy(Func> taskFactory) : base(() => Task.Factory.StartNew( () => taskFactory(), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default) .Unwrap()) { } + /// + /// The awaiter to be awaited in order to trigger asynchronous value creation. + /// + /// public TaskAwaiter GetAwaiter() { return Value.GetAwaiter(); } } } diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/ExportCommandFailureTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/ExportCommandFailureTests.cs index 7cbb137100..623229588e 100644 --- a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/ExportCommandFailureTests.cs +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/ExportCommandFailureTests.cs @@ -3,7 +3,6 @@ using System.Globalization; using Microsoft.TemplateEngine.TestHelper.Commands; -using Xunit; using Xunit.Abstractions; namespace Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs deleted file mode 100644 index fb9977ceca..0000000000 --- a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs +++ /dev/null @@ -1,133 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using FluentAssertions; -using Microsoft.TemplateEngine.Authoring.TemplateVerifier; -using Microsoft.TemplateEngine.TestHelper; -using Microsoft.TemplateEngine.TestHelper.Commands; -using Xunit.Abstractions; - -namespace Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests -{ - [UsesVerify] - public class VerifyCommandTests - { - private readonly ITestOutputHelper _log; - - public VerifyCommandTests(ITestOutputHelper log) - { - _log = log; - } - - [Fact] - public void VerifyCommandFullDevLoop() - { - // dots issue https://github.com/VerifyTests/Verify/issues/658 - string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); - string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); - string templateDir = "path with spaces"; - - var cmd = new BasicCommand( - _log, - "dotnet", - Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"), - "verify", - "console", - "--template-args", - "--use-program-main -o \"" + templateDir + "\" --no-restore", - "--verify-std", - "-o", - workingDir, - "--expectations-directory", - expectationsDir, - "--disable-diff-tool", - "--unique-for", - "architecture", - "--unique-for", - "RuntimeAndVersion"); - - cmd.Execute() - .Should() - .ExitWith((int)TemplateVerificationErrorCode.VerificationFailed) - .And.HaveStdErrContaining("Verification Failed."); - - // Assert template created - Directory.Exists(Path.Combine(workingDir, templateDir)).Should().BeTrue(); - File.Exists(Path.Combine(workingDir, templateDir, "console.csproj")).Should().BeTrue(); - File.Exists(Path.Combine(workingDir, templateDir, "Program.cs")).Should().BeTrue(); - - // Assert verification files created - Directory.Exists(expectationsDir).Should().BeTrue(); - Directory.GetDirectories(expectationsDir).Length.Should().Be(1); - //for simplicity move to the created dir - expectationsDir = Directory.GetDirectories(expectationsDir).Single(); - File.Exists(Path.Combine(expectationsDir, templateDir, "console.received.csproj")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, templateDir, "Program.received.cs")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "std-streams", "stdout.received.txt")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "std-streams", "stderr.received.txt")).Should().BeTrue(); - // .verified files are only created when diff tool is used - that is however turned off in CI - //File.Exists(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeTrue(); - //File.Exists(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeTrue(); - //File.Exists(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeTrue(); - //File.Exists(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeTrue(); - Directory.GetFiles(expectationsDir, "*", SearchOption.AllDirectories).Length.Should().Be(4); - - // .verified files are only created when diff tool is used - that is however turned off in CI - //File.ReadAllText(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeEmpty(); - //File.ReadAllText(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeEmpty(); - //File.ReadAllText(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeEmpty(); - //File.ReadAllText(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeEmpty(); - File.ReadAllText(Path.Combine(expectationsDir, templateDir, "console.received.csproj").UnixifyLineBreaks()).Should() - .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "console.csproj")).UnixifyLineBreaks()); - File.ReadAllText(Path.Combine(expectationsDir, templateDir, "Program.received.cs").UnixifyLineBreaks()).Should() - .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "Program.cs")).UnixifyLineBreaks()); - - // Accept changes - File.Move( - Path.Combine(expectationsDir, templateDir, "console.received.csproj"), - Path.Combine(expectationsDir, templateDir, "console.verified.csproj")); - File.Move( - Path.Combine(expectationsDir, templateDir, "Program.received.cs"), - Path.Combine(expectationsDir, templateDir, "Program.verified.cs")); - File.Move( - Path.Combine(expectationsDir, "std-streams", "stdout.received.txt"), - Path.Combine(expectationsDir, "std-streams", "stdout.verified.txt")); - File.Move( - Path.Combine(expectationsDir, "std-streams", "stderr.received.txt"), - Path.Combine(expectationsDir, "std-streams", "stderr.verified.txt")); - - //reset the expectations dir to where it was before previous run - expectationsDir = Path.GetDirectoryName(expectationsDir)!; - - // And run again same scenario - verification should succeed now - string workingDir2 = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - var cmd2 = new BasicCommand( - _log, - "dotnet", - Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"), - "verify", - "console", - "--template-args", - "--use-program-main -o \"" + templateDir + "\" --no-restore", - "--verify-std", - "-o", - workingDir2, - "--expectations-directory", - expectationsDir, - "--unique-for", - "architecture", - "--unique-for", - "RuntimeAndVersion"); - - cmd2.Execute() - .Should() - .Pass() - .And.HaveStdOutContaining("Running the verification of console.") - .And.NotHaveStdErr(); - - Directory.Delete(workingDir, true); - Directory.Delete(workingDir2, true); - Directory.Delete(expectationsDir, true); - } - } -} diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.Tests/Microsoft.TemplateEngine.Authoring.CLI.Tests.csproj b/test/Microsoft.TemplateEngine.Authoring.CLI.Tests/Microsoft.TemplateEngine.Authoring.CLI.Tests.csproj new file mode 100644 index 0000000000..92aab69eda --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.Tests/Microsoft.TemplateEngine.Authoring.CLI.Tests.csproj @@ -0,0 +1,14 @@ + + + $(NETCoreTargetFramework) + false + enable + enable + + + + + + + + diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.Tests/VerifyCommandArgsTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.Tests/VerifyCommandArgsTests.cs new file mode 100644 index 0000000000..a5b53e1378 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.Tests/VerifyCommandArgsTests.cs @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using FluentAssertions; +using Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify; + +namespace Microsoft.TemplateEngine.Authoring.CLI.Tests +{ + public class VerifyCommandArgsTests + { + [Theory] + [InlineData(null, new string[] { })] + [InlineData(" ", new string[] { })] + [InlineData(" a b c", new string[] { "a", "b", "c" })] + [InlineData(" abc ", new string[] { "abc" })] + [InlineData("a \"b c \" d ", new string[] { "a", "b c ", "d" })] + [InlineData("aa \" bb cc \"dd", new string[] { "aa", " bb cc ", "dd" })] + [InlineData("aa q= 'bb cc'dd", new string[] { "aa", "q=", "bb cc", "dd" })] + public void OnTokenizeJoinedArgsResultIsExpected(string? input, IEnumerable expectedOutput) + { + var result = VerifyCommandArgs.TokenizeJoinedArgs(input); + result.Should().BeEquivalentTo(expectedOutput, options => options.WithStrictOrdering()); + } + } +} diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj index ded7a847e5..d5e5095ce2 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj @@ -4,12 +4,6 @@ enable enable - - - Always - - - diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/VerificationEngineTests.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/VerificationEngineTests.cs index 689fd0f06f..3d323235cb 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/VerificationEngineTests.cs +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/VerificationEngineTests.cs @@ -1,12 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -//using FluentAssertions; -//using Microsoft.TemplateEngine.Authoring.TemplateVerifier; -//using Microsoft.TemplateEngine.TestHelper; -//using Microsoft.TemplateEngine.TestHelper.Commands; -//using Xunit.Abstractions; - using FluentAssertions; using Microsoft.Extensions.Logging; using Microsoft.TemplateEngine.TestHelper; @@ -30,9 +24,8 @@ public async void VerificationEngineFullDevLoop() string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); string templateDir = "path with spaces"; - TemplateVerifierOptions options = new TemplateVerifierOptions() + TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: "console") { - TemplateName = "console", TemplateSpecificArgs = new string[] { "--use-program-main", "-o", templateDir, "--no-restore" }, DisableDiffTool = true, ExpectationsDirectory = expectationsDir, @@ -55,33 +48,24 @@ await executeTask // Assert verification files created Directory.Exists(expectationsDir).Should().BeTrue(); - Directory.GetDirectories(expectationsDir).Length.Should().Be(1); - //for simplicity move to the created dir - expectationsDir = Directory.GetDirectories(expectationsDir).Single(); - File.Exists(Path.Combine(expectationsDir, templateDir, "console.received.csproj")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, templateDir, "Program.received.cs")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "std-streams", "stdout.received.txt")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "std-streams", "stderr.received.txt")).Should().BeTrue(); + Directory.GetDirectories(expectationsDir).Length.Should().Be(2); + //for simplicity move to the received dir + expectationsDir = Directory.GetDirectories(expectationsDir).Single(d => d.EndsWith(".received", StringComparison.Ordinal)); + File.Exists(Path.Combine(expectationsDir, templateDir, "console.csproj")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, templateDir, "Program.cs")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "std-streams", "stdout.txt")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "std-streams", "stderr.txt")).Should().BeTrue(); Directory.GetFiles(expectationsDir, "*", SearchOption.AllDirectories).Length.Should().Be(4); - File.ReadAllText(Path.Combine(expectationsDir, templateDir, "console.received.csproj").UnixifyLineBreaks()).Should() + File.ReadAllText(Path.Combine(expectationsDir, templateDir, "console.csproj").UnixifyLineBreaks()).Should() .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "console.csproj")).UnixifyLineBreaks()); - File.ReadAllText(Path.Combine(expectationsDir, templateDir, "Program.received.cs").UnixifyLineBreaks()).Should() + File.ReadAllText(Path.Combine(expectationsDir, templateDir, "Program.cs").UnixifyLineBreaks()).Should() .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "Program.cs")).UnixifyLineBreaks()); // Accept changes - File.Move( - Path.Combine(expectationsDir, templateDir, "console.received.csproj"), - Path.Combine(expectationsDir, templateDir, "console.verified.csproj")); - File.Move( - Path.Combine(expectationsDir, templateDir, "Program.received.cs"), - Path.Combine(expectationsDir, templateDir, "Program.verified.cs")); - File.Move( - Path.Combine(expectationsDir, "std-streams", "stdout.received.txt"), - Path.Combine(expectationsDir, "std-streams", "stdout.verified.txt")); - File.Move( - Path.Combine(expectationsDir, "std-streams", "stderr.received.txt"), - Path.Combine(expectationsDir, "std-streams", "stderr.verified.txt")); + string verifiedDir = expectationsDir.Replace(".received", ".verified", StringComparison.Ordinal); + Directory.Delete(verifiedDir, false); + Directory.Move(expectationsDir, verifiedDir); //reset the expectations dir to where it was before previous run expectationsDir = Path.GetDirectoryName(expectationsDir)!; @@ -89,9 +73,8 @@ await executeTask // And run again same scenario - verification should succeed now string workingDir2 = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - TemplateVerifierOptions options2 = new TemplateVerifierOptions() + TemplateVerifierOptions options2 = new TemplateVerifierOptions(templateName: "console") { - TemplateName = "console", TemplateSpecificArgs = new string[] { "--use-program-main", "-o", templateDir, "--no-restore" }, DisableDiffTool = true, ExpectationsDirectory = expectationsDir, @@ -117,9 +100,8 @@ public async void VerificationEngineCustomVerifier() string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); string templateDir = "path with spaces"; - TemplateVerifierOptions options = new TemplateVerifierOptions() + TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: "console") { - TemplateName = "console", TemplateSpecificArgs = new string[] { "--use-program-main", "-o", templateDir, "--no-restore" }, DisableDiffTool = true, OutputDirectory = workingDir, From 6e5f69aaba54a2232aef575d397ee59a3c940acb Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Wed, 5 Oct 2022 13:52:41 +0200 Subject: [PATCH 10/15] Add the uninstalled template testing option --- Microsoft.TemplateEngine.sln | 45 ++-- .../Commands/Verify/VerifyCommandArgs.cs | 2 +- .../Commands/CommandResultData.cs | 30 +++ .../Commands/CommandRunner.cs | 13 ++ .../Commands/ICommandRunner.cs | 10 + .../Commands/TestCommand.cs | 4 +- .../LocalizableStrings.Designer.cs | 9 + .../LocalizableStrings.resx | 5 +- .../PublicAPI.Unshipped.txt | 1 + .../TemplateVerificationErrorCode.cs | 5 + .../VerificationEngine.cs | 105 ++++++--- .../xlf/LocalizableStrings.cs.xlf | 5 + .../xlf/LocalizableStrings.de.xlf | 5 + .../xlf/LocalizableStrings.es.xlf | 5 + .../xlf/LocalizableStrings.fr.xlf | 5 + .../xlf/LocalizableStrings.it.xlf | 5 + .../xlf/LocalizableStrings.ja.xlf | 5 + .../xlf/LocalizableStrings.ko.xlf | 5 + .../xlf/LocalizableStrings.pl.xlf | 5 + .../xlf/LocalizableStrings.pt-BR.xlf | 5 + .../xlf/LocalizableStrings.ru.xlf | 5 + .../xlf/LocalizableStrings.tr.xlf | 5 + .../xlf/LocalizableStrings.zh-Hans.xlf | 5 + .../xlf/LocalizableStrings.zh-Hant.xlf | 5 + ...gine.Authoring.CLI.IntegrationTests.csproj | 4 + .../.template.config/template.json | 24 ++ .../TestTemplate/Test.cs | 11 + .../VerifyCommandArgsTests.cs | 25 -- .../VerifyCommandTests.cs | 213 ++++++++++++++++++ ....TemplateVerifier.IntegrationTests.csproj} | 0 .../VerificationEngineTests.cs | 151 +++++++++++++ ...uthoring.TemplateVerifier.UnitTests.csproj | 13 ++ 32 files changed, 656 insertions(+), 79 deletions(-) create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandResultData.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandRunner.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/ICommandRunner.cs create mode 100644 test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/TestTemplate/.template.config/template.json create mode 100644 test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/TestTemplate/Test.cs delete mode 100644 test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandArgsTests.cs create mode 100644 test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs rename test/{Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj => Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj} (100%) create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj diff --git a/Microsoft.TemplateEngine.sln b/Microsoft.TemplateEngine.sln index 2fcdf1e71b..3f045b2ef2 100644 --- a/Microsoft.TemplateEngine.sln +++ b/Microsoft.TemplateEngine.sln @@ -68,10 +68,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{B794BF86 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier", "src\Microsoft.TemplateEngine.Authoring.TemplateVerifier\Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj", "{12764D81-61A7-437A-90B6-9F245E43F457}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests", "test\Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests\Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj", "{DFB18A1E-4C70-48D3-B57A-FA81B405EA04}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.CLI.Tests", "test\Microsoft.TemplateEngine.Authoring.CLI.Tests\Microsoft.TemplateEngine.Authoring.CLI.Tests.csproj", "{F1860546-A949-4A16-ACB2-0C4C3CA2C970}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests", "test\Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests\Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj", "{B1DDA327-F55E-466A-AF3E-7F039B9B51A9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests", "test\Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests\Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj", "{D478568D-CA20-4331-9019-F585B564425E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -406,18 +408,6 @@ Global {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x64.Build.0 = Release|Any CPU {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x86.ActiveCfg = Release|Any CPU {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x86.Build.0 = Release|Any CPU - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Debug|x64.ActiveCfg = Debug|Any CPU - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Debug|x64.Build.0 = Debug|Any CPU - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Debug|x86.ActiveCfg = Debug|Any CPU - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Debug|x86.Build.0 = Debug|Any CPU - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|Any CPU.Build.0 = Release|Any CPU - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|x64.ActiveCfg = Release|Any CPU - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|x64.Build.0 = Release|Any CPU - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|x86.ActiveCfg = Release|Any CPU - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04}.Release|x86.Build.0 = Release|Any CPU {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|Any CPU.Build.0 = Debug|Any CPU {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -430,6 +420,30 @@ Global {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|x64.Build.0 = Release|Any CPU {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|x86.ActiveCfg = Release|Any CPU {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|x86.Build.0 = Release|Any CPU + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|x64.ActiveCfg = Debug|Any CPU + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|x64.Build.0 = Debug|Any CPU + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|x86.ActiveCfg = Debug|Any CPU + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|x86.Build.0 = Debug|Any CPU + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Release|Any CPU.Build.0 = Release|Any CPU + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Release|x64.ActiveCfg = Release|Any CPU + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Release|x64.Build.0 = Release|Any CPU + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Release|x86.ActiveCfg = Release|Any CPU + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Release|x86.Build.0 = Release|Any CPU + {D478568D-CA20-4331-9019-F585B564425E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D478568D-CA20-4331-9019-F585B564425E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D478568D-CA20-4331-9019-F585B564425E}.Debug|x64.ActiveCfg = Debug|Any CPU + {D478568D-CA20-4331-9019-F585B564425E}.Debug|x64.Build.0 = Debug|Any CPU + {D478568D-CA20-4331-9019-F585B564425E}.Debug|x86.ActiveCfg = Debug|Any CPU + {D478568D-CA20-4331-9019-F585B564425E}.Debug|x86.Build.0 = Debug|Any CPU + {D478568D-CA20-4331-9019-F585B564425E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D478568D-CA20-4331-9019-F585B564425E}.Release|Any CPU.Build.0 = Release|Any CPU + {D478568D-CA20-4331-9019-F585B564425E}.Release|x64.ActiveCfg = Release|Any CPU + {D478568D-CA20-4331-9019-F585B564425E}.Release|x64.Build.0 = Release|Any CPU + {D478568D-CA20-4331-9019-F585B564425E}.Release|x86.ActiveCfg = Release|Any CPU + {D478568D-CA20-4331-9019-F585B564425E}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -462,8 +476,9 @@ Global {BD758B10-A47F-4159-B9A1-997723AF7349} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B} {2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} {12764D81-61A7-437A-90B6-9F245E43F457} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B} - {DFB18A1E-4C70-48D3-B57A-FA81B405EA04} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} {F1860546-A949-4A16-ACB2-0C4C3CA2C970} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} + {B1DDA327-F55E-466A-AF3E-7F039B9B51A9} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} + {D478568D-CA20-4331-9019-F585B564425E} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6EA1A508-6033-4538-BF98-7F71B4E297AD} diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs index 7f1107f985..fc36314df6 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs @@ -36,7 +36,7 @@ public VerifyCommandArgs( VerificationExcludePatterns = verificationExcludePatterns; VerifyCommandOutput = verifyCommandOutput; IsCommandExpectedToFail = isCommandExpectedToFail; - UniqueFor = uniqueForOptions?.Aggregate((a, b) => a | b); + UniqueFor = uniqueForOptions?.Aggregate(UniqueForOption.None, (a, b) => a | b); } /// diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandResultData.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandResultData.cs new file mode 100644 index 0000000000..e8edebb75b --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandResultData.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.DotNet.Cli.Utils; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands +{ + internal class CommandResultData + { + public CommandResultData(int exitCode, string stdOut, string stdErr, string workingDirectory) + { + ExitCode = exitCode; + StdOut = stdOut; + StdErr = stdErr; + WorkingDirectory = workingDirectory; + } + + public CommandResultData(CommandResult commandResult) + : this(commandResult.ExitCode, commandResult.StdOut, commandResult.StdErr, commandResult.StartInfo.WorkingDirectory) + { } + + public int ExitCode { get; } + + public string StdOut { get; } + + public string StdErr { get; } + + public string WorkingDirectory { get; } + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandRunner.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandRunner.cs new file mode 100644 index 0000000000..8b3ef8d524 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/CommandRunner.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands +{ + internal class CommandRunner : ICommandRunner + { + public CommandResultData RunCommand(TestCommand testCommand) + { + return new CommandResultData(testCommand.Execute()); + } + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/ICommandRunner.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/ICommandRunner.cs new file mode 100644 index 0000000000..a5344249db --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/ICommandRunner.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands +{ + internal interface ICommandRunner + { + CommandResultData RunCommand(TestCommand testCommand); + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs index 09d22972a4..c04e586b4d 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Commands/TestCommand.cs @@ -75,8 +75,8 @@ public virtual CommandResult Execute(IEnumerable args) if (!string.IsNullOrEmpty(result.StdErr)) { - Log.LogInformation("StdErr:"); - Log.LogInformation(result.StdErr); + Log.LogWarning("StdErr:"); + Log.LogWarning(result.StdErr); } if (result.ExitCode != 0) diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs index dddd4bc996..cdc55bd7bf 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs @@ -60,6 +60,15 @@ internal LocalizableStrings() { } } + /// + /// Looks up a localized string similar to Template installation expected to pass but it had exit code '{0}'.. + /// + internal static string VerificationEngine_Error_InstallUnexpectedFail { + get { + return ResourceManager.GetString("VerificationEngine_Error_InstallUnexpectedFail", resourceCulture); + } + } + /// /// Looks up a localized string similar to The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.. /// diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx index 25d6314a17..0b26f12919 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx @@ -117,6 +117,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Template installation expected to pass but it had exit code '{0}'. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path @@ -141,4 +144,4 @@ The working directory already exists and is not empty. - \ No newline at end of file + diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt index cd8f7bac1b..1369270f50 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt @@ -5,6 +5,7 @@ Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.Scrubber Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.ScrubbersDefinition(System.Action! scrubber, string? extension = null) -> void Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.ScrubersByExtension.get -> System.Collections.Generic.Dictionary!>! Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InstallFailed = 106 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InstantiationFailed = 100 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InternalError = 70 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.TemplateDoesNotExist = 103 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs index bf400a27d6..8ab6862b53 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs @@ -39,5 +39,10 @@ public enum TemplateVerificationErrorCode /// The template instantiation failed and results were not created. /// InstantiationFailed = 100, + + /// + /// Installation/Uninstallation Failed - Processing issues. + /// + InstallFailed = 106, } } diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs index 7a31a6c607..ac796df361 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs @@ -4,7 +4,6 @@ using System.Reflection; using System.Text; using System.Text.RegularExpressions; -using Microsoft.DotNet.Cli.Utils; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands; @@ -29,6 +28,7 @@ public class VerificationEngine private readonly TemplateVerifierOptions _options; private readonly ILogger _logger; private readonly ILoggerFactory? _loggerFactory; + private readonly ICommandRunner _commandRunner = new CommandRunner(); static VerificationEngine() { @@ -54,15 +54,15 @@ public VerificationEngine(TemplateVerifierOptions options, ILoggerFactory logger _loggerFactory = loggerFactory; } - public async Task Execute(CancellationToken cancellationToken = default) + internal VerificationEngine(TemplateVerifierOptions options, ICommandRunner commandRunner, ILogger logger) + : this(options, logger) { - //TODO: add functionality for uninstalled templates from a local folder - if (!string.IsNullOrEmpty(_options.TemplatePath)) - { - throw new TemplateVerificationException("Custom template path not yet supported.", TemplateVerificationErrorCode.InternalError); - } + _commandRunner = commandRunner; + } - CommandResult commandResult = RunDotnetNewCommand(_options, _loggerFactory, _logger); + public async Task Execute(CancellationToken cancellationToken = default) + { + CommandResultData commandResult = RunDotnetNewCommand(_options, _commandRunner, _loggerFactory, _logger); if (_options.IsCommandExpectedToFail ?? false) { @@ -109,14 +109,8 @@ private static string EncodeArgsAsPath(IEnumerable? args) return r.Replace(string.Join('#', args), string.Empty); } - private static CommandResult RunDotnetNewCommand(TemplateVerifierOptions options, ILoggerFactory? loggerFactory, ILogger logger) + private static CommandResultData RunDotnetNewCommand(TemplateVerifierOptions options, ICommandRunner commandRunner, ILoggerFactory? loggerFactory, ILogger logger) { - //TODO: add functionality for uninstalled templates from a local folder - if (!string.IsNullOrEmpty(options.TemplatePath)) - { - throw new TemplateVerificationException("Custom template path not yet supported.", TemplateVerificationErrorCode.InternalError); - } - // Create temp folder and instantiate there string workingDir = options.OutputDirectory ?? Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); if (Directory.Exists(workingDir) && Directory.EnumerateFileSystemEntries(workingDir).Any()) @@ -125,33 +119,74 @@ private static CommandResult RunDotnetNewCommand(TemplateVerifierOptions options } Directory.CreateDirectory(workingDir); + ILogger commandLogger = loggerFactory?.CreateLogger(typeof(DotnetCommand)) ?? logger; + string? customHiveLocation = null; + + if (!string.IsNullOrEmpty(options.TemplatePath)) + { + customHiveLocation = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName(), "home"); + var installCommand = + new DotnetCommand(commandLogger, "new", "install", options.TemplatePath) + .WithCustomHive(customHiveLocation) + .WithWorkingDirectory(workingDir); + + CommandResultData installCommandResult = commandRunner.RunCommand(installCommand); + + if (installCommandResult.ExitCode != 0) + { + throw new TemplateVerificationException( + string.Format(LocalizableStrings.VerificationEngine_Error_InstallUnexpectedFail, installCommandResult.ExitCode), + TemplateVerificationErrorCode.InstantiationFailed); + } + } List cmdArgs = new(); if (!string.IsNullOrEmpty(options.DotnetNewCommandAssemblyPath)) { cmdArgs.Add(options.DotnetNewCommandAssemblyPath); } - cmdArgs.Add("new"); cmdArgs.Add(options.TemplateName); if (options.TemplateSpecificArgs != null) { cmdArgs.AddRange(options.TemplateSpecificArgs); } - cmdArgs.Add("--debug:ephemeral-hive"); - // let's make sure the template outputs are named deterministically - cmdArgs.Add("-n"); - cmdArgs.Add(options.TemplateName); - // TODO: export and use impl from sdk - return new DotnetCommand(loggerFactory?.CreateLogger(typeof(DotnetCommand)) ?? logger, "dotnet", cmdArgs.ToArray()) - .WithWorkingDirectory(workingDir) - .Execute(); + if (!string.IsNullOrEmpty(customHiveLocation)) + { + cmdArgs.Add("--debug:custom-hive"); + cmdArgs.Add(customHiveLocation); + } + else + { + cmdArgs.Add("--debug:ephemeral-hive"); + } + + // let's make sure the template outputs are named and placed deterministically + if (!cmdArgs.Select(arg => arg.Trim()) + .Any(arg => new[] { "-n", "--name" }.Contains(arg, StringComparer.OrdinalIgnoreCase))) + { + cmdArgs.Add("-n"); + cmdArgs.Add(options.TemplateName); + } + if (!cmdArgs.Select(arg => arg.Trim()) + .Any(arg => new[] { "-o", "--output" }.Contains(arg, StringComparer.OrdinalIgnoreCase))) + { + cmdArgs.Add("-o"); + cmdArgs.Add(options.TemplateName); + } + + var command = new DotnetCommand(loggerFactory?.CreateLogger(typeof(DotnetCommand)) ?? logger, "new", cmdArgs.ToArray()) + .WithWorkingDirectory(workingDir); + var result = commandRunner.RunCommand(command); + if (!string.IsNullOrEmpty(customHiveLocation)) + { + Directory.Delete(customHiveLocation, true); + } + return result; } - private static Task CreateVerificationTask(CommandResult commandResult, TemplateVerifierOptions options) + private static Task CreateVerificationTask(string contentDir, TemplateVerifierOptions options) { - string contentDir = commandResult.StartInfo.WorkingDirectory; - List exclusionsList = (options.DisableDefaultVerificationExcludePatterns ?? false) ? new() : new(_defaultVerificationExcludePatterns); @@ -271,7 +306,7 @@ private static void DummyMethod() } } - private async Task VerifyResult(TemplateVerifierOptions args, CommandResult commandResult) + private async Task VerifyResult(TemplateVerifierOptions args, CommandResultData commandResultData) { UsesVerifyAttribute a = new UsesVerifyAttribute(); // https://github.com/VerifyTests/Verify/blob/d8cbe38f527d6788ecadd6205c82803bec3cdfa6/src/Verify.Xunit/Verifier.cs#L10 @@ -282,7 +317,7 @@ private async Task VerifyResult(TemplateVerifierOptions args, CommandResult comm if (_options.VerifyCommandOutput ?? false) { - if (Directory.Exists(Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir))) + if (Directory.Exists(Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir))) { throw new TemplateVerificationException( string.Format( @@ -291,20 +326,20 @@ private async Task VerifyResult(TemplateVerifierOptions args, CommandResult comm TemplateVerificationErrorCode.InternalError); } - Directory.CreateDirectory(Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir)); + Directory.CreateDirectory(Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir)); await File.WriteAllTextAsync( - Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdOut + (_options.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)), - commandResult.StdOut) + Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdOut + (_options.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)), + commandResultData.StdOut) .ConfigureAwait(false); await File.WriteAllTextAsync( - Path.Combine(commandResult.StartInfo.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdErr + (_options.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)), - commandResult.StdErr) + Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdErr + (_options.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)), + commandResultData.StdErr) .ConfigureAwait(false); } - Task verifyTask = CreateVerificationTask(commandResult, args); + Task verifyTask = CreateVerificationTask(commandResultData.WorkingDirectory, args); try { diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf index 186b420638..ab6f73e4ec 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf index 6e0d509bd2..cb553651d2 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf index 5cdaeff6ce..acfecd99d4 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf index b3868ea18b..3e34eb02bf 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf index 9619369dc3..4c47e8a3a6 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf index 7252afff82..cfc1e0f951 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf index 995943df35..1d01c029d5 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf index 9abbb748f4..a890794172 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf index a8b6fabcf8..1e7cdff13c 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf index 3b0ae3dbe7..9c07d9deec 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf index 14ebad690a..ed1d88eedd 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf index 2161abc83b..2352764aff 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf index f445685cd8..505eaaed90 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf @@ -2,6 +2,11 @@ + + Template installation expected to pass but it had exit code '{0}'. + Template installation expected to pass but it had exit code '{0}'. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj index cde80c6391..10511e3363 100644 --- a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj @@ -14,6 +14,10 @@ + + + + diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/TestTemplate/.template.config/template.json b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/TestTemplate/.template.config/template.json new file mode 100644 index 0000000000..b60eb7bc74 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/TestTemplate/.template.config/template.json @@ -0,0 +1,24 @@ +{ + "author": "Test Asset", + "classifications": [ "Test Asset" ], + "name": "SampleTestTemplate", + "generatorVersions": "[1.0.0.0-*)", + "groupIdentity": "TestAssets.SampleTestTemplate", + "precedence": "100", + "identity": "TestAssets.SampleTestTemplate", + "shortName": "TestAssets.SampleTestTemplate", + "symbols": { + "paramA": { + "type": "parameter", + "datatype": "string", + "replaces": "placeholderA", + "defaultValue": "false" + }, + "paramB": { + "type": "parameter", + "datatype": "string", + "isRequired": true, + "replaces": "placeholderB" + } + } +} diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/TestTemplate/Test.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/TestTemplate/Test.cs new file mode 100644 index 0000000000..0de65665c3 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/TestTemplate/Test.cs @@ -0,0 +1,11 @@ + +// value of paramA: placeholderA +// value of paramB: placeholderB + +//#if( paramA ) + // A is enabled +//#endif + +//#if( paramB ) + // B is enabled +//#endif diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandArgsTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandArgsTests.cs deleted file mode 100644 index 9cdd0aa879..0000000000 --- a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandArgsTests.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using FluentAssertions; -using Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify; - -namespace Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests -{ - public class VerifyCommandArgsTests - { - [Theory] - [InlineData(null, new string[] { })] - [InlineData(" ", new string[] { })] - [InlineData(" a b c", new string[] { "a", "b", "c" })] - [InlineData(" abc ", new string[] { "abc" })] - [InlineData("a \"b c \" d ", new string[] { "a", "b c ", "d" })] - [InlineData("aa \" bb cc \"dd", new string[] { "aa", " bb cc ", "dd" })] - [InlineData("aa q= 'bb cc'dd", new string[] { "aa", "q=", "bb cc", "dd" })] - public void OnTokenizeJoinedArgsResultIsExpected(string? input, IEnumerable expectedOutput) - { - var result = VerifyCommandArgs.TokenizeJoinedArgs(input); - result.Should().BeEquivalentTo(expectedOutput, options => options.WithStrictOrdering()); - } - } -} diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs new file mode 100644 index 0000000000..517b3c3340 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs @@ -0,0 +1,213 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using FluentAssertions; +using Microsoft.TemplateEngine.Authoring.TemplateVerifier; +using Microsoft.TemplateEngine.TestHelper; +using Microsoft.TemplateEngine.TestHelper.Commands; +using Xunit.Abstractions; + +namespace Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests +{ + [UsesVerify] + public class VerifyCommandTests + { + private readonly ITestOutputHelper _log; + + public VerifyCommandTests(ITestOutputHelper log) + { + _log = log; + } + + [Fact] + public void VerifyCommandFullDevLoop() + { + // dots issue https://github.com/VerifyTests/Verify/issues/658 + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string templateOutputDir = "path with spaces"; + + var cmd = new BasicCommand( + _log, + "dotnet", + Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"), + "verify", + "console", + "--template-args", + "--use-program-main -o \"" + templateOutputDir + "\" --no-restore", + "--verify-std", + "-o", + workingDir, + "--expectations-directory", + expectationsDir, + "--disable-diff-tool", + "--unique-for", + "architecture", + "--unique-for", + "RuntimeAndVersion"); + + cmd.Execute() + .Should() + .ExitWith((int)TemplateVerificationErrorCode.VerificationFailed) + .And.HaveStdOutContaining("Verification Failed."); + + // Assert template created + Directory.Exists(Path.Combine(workingDir, templateOutputDir)).Should().BeTrue(); + File.Exists(Path.Combine(workingDir, templateOutputDir, "console.csproj")).Should().BeTrue(); + File.Exists(Path.Combine(workingDir, templateOutputDir, "Program.cs")).Should().BeTrue(); + + // Assert verification files created + Directory.Exists(expectationsDir).Should().BeTrue(); + Directory.GetDirectories(expectationsDir).Length.Should().Be(2); + //for simplicity move to the created dir + expectationsDir = Directory.GetDirectories(expectationsDir).Single(d => d.EndsWith(".received", StringComparison.Ordinal)); + File.Exists(Path.Combine(expectationsDir, templateOutputDir, "console.csproj")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, templateOutputDir, "Program.cs")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "std-streams", "stdout.txt")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "std-streams", "stderr.txt")).Should().BeTrue(); + Directory.GetFiles(expectationsDir, "*", SearchOption.AllDirectories).Length.Should().Be(4); + // .verified files are only created when diff tool is used - that is however turned off in CI + //File.Exists(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeTrue(); + //File.Exists(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeTrue(); + //File.Exists(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeTrue(); + //File.Exists(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeTrue(); + + // .verified files are only created when diff tool is used - that is however turned off in CI + //File.ReadAllText(Path.Combine(expectationsDir, "console.console.csproj.verified.csproj")).Should().BeEmpty(); + //File.ReadAllText(Path.Combine(expectationsDir, "console.Program.cs.verified.cs")).Should().BeEmpty(); + //File.ReadAllText(Path.Combine(expectationsDir, "console.StdOut.verified.txt")).Should().BeEmpty(); + //File.ReadAllText(Path.Combine(expectationsDir, "console.StdErr.verified.txt")).Should().BeEmpty(); + File.ReadAllText(Path.Combine(expectationsDir, templateOutputDir, "console.csproj").UnixifyLineBreaks()).Should() + .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateOutputDir, "console.csproj")).UnixifyLineBreaks()); + File.ReadAllText(Path.Combine(expectationsDir, templateOutputDir, "Program.cs").UnixifyLineBreaks()).Should() + .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateOutputDir, "Program.cs")).UnixifyLineBreaks()); + + // Accept changes + string verifiedDir = expectationsDir.Replace(".received", ".verified", StringComparison.Ordinal); + Directory.Delete(verifiedDir, false); + Directory.Move(expectationsDir, verifiedDir); + + //reset the expectations dir to where it was before previous run + expectationsDir = Path.GetDirectoryName(expectationsDir)!; + + // And run again same scenario - verification should succeed now + string workingDir2 = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + var cmd2 = new BasicCommand( + _log, + "dotnet", + Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"), + "verify", + "console", + "--template-args", + "--use-program-main -o \"" + templateOutputDir + "\" --no-restore", + "--verify-std", + "-o", + workingDir2, + "--expectations-directory", + expectationsDir, + "--unique-for", + "architecture", + "--unique-for", + "RuntimeAndVersion"); + + cmd2.Execute() + .Should() + .Pass() + .And.HaveStdOutContaining("Running the verification of console.") + .And.NotHaveStdErr(); + + Directory.Delete(workingDir, true); + Directory.Delete(workingDir2, true); + Directory.Delete(expectationsDir, true); + } + + [Fact] + public void VerifyCommandFullDevLoopWithNotInstalledTemplate() + { + // dots issue https://github.com/VerifyTests/Verify/issues/658 + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string templateShortName = "TestAssets.SampleTestTemplate"; + string templateOutputDir = templateShortName; + + //get the template location + string executingAssemblyPath = this.GetType().Assembly.Location; + string templateLocation = Path.Combine(Path.GetDirectoryName(executingAssemblyPath)!, "TestTemplate"); + + var cmd = new BasicCommand( + _log, + "dotnet", + Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"), + "verify", + templateShortName, + "--template-path", + templateLocation, + "--template-args", + "--paramB true", + "--verify-std", + "-o", + workingDir, + "--expectations-directory", + expectationsDir, + "--disable-diff-tool"); + + cmd.Execute() + .Should() + .ExitWith((int)TemplateVerificationErrorCode.VerificationFailed) + .And.HaveStdOutContaining("Verification Failed."); + + // Assert template created + Directory.Exists(Path.Combine(workingDir, templateOutputDir)).Should().BeTrue(); + File.Exists(Path.Combine(workingDir, templateOutputDir, "Test.cs")).Should().BeTrue(); + + // Assert verification files created + Directory.Exists(expectationsDir).Should().BeTrue(); + Directory.GetDirectories(expectationsDir).Length.Should().Be(2); + //for simplicity move to the created dir + expectationsDir = Directory.GetDirectories(expectationsDir).Single(d => d.EndsWith(".received", StringComparison.Ordinal)); + File.Exists(Path.Combine(expectationsDir, templateOutputDir, "Test.cs")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "std-streams", "stdout.txt")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "std-streams", "stderr.txt")).Should().BeTrue(); + Directory.GetFiles(expectationsDir, "*", SearchOption.AllDirectories).Length.Should().Be(3); + + File.ReadAllText(Path.Combine(expectationsDir, templateOutputDir, "Test.cs").UnixifyLineBreaks()).Should() + .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateOutputDir, "Test.cs")).UnixifyLineBreaks()); + + // Accept changes + string verifiedDir = expectationsDir.Replace(".received", ".verified", StringComparison.Ordinal); + Directory.Delete(verifiedDir, false); + Directory.Move(expectationsDir, verifiedDir); + + //reset the expectations dir to where it was before previous run + expectationsDir = Path.GetDirectoryName(expectationsDir)!; + + // And run again same scenario - verification should succeed now + string workingDir2 = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + var cmd2 = new BasicCommand( + _log, + "dotnet", + Path.GetFullPath("Microsoft.TemplateEngine.Authoring.CLI.dll"), + "verify", + templateShortName, + "--template-path", + templateLocation, + "--template-args", + "--paramB true", + "--verify-std", + "-o", + workingDir2, + "--expectations-directory", + expectationsDir); + + cmd2.Execute() + .Should() + .Pass() + .And.HaveStdOutContaining(string.Format("Running the verification of {0}.", templateShortName)) + .And.NotHaveStdErr(); + + Directory.Delete(workingDir, true); + Directory.Delete(workingDir2, true); + Directory.Delete(expectationsDir, true); + } + } +} diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj similarity index 100% rename from test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests.csproj rename to test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs new file mode 100644 index 0000000000..ba163919de --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs @@ -0,0 +1,151 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using FluentAssertions; +using Microsoft.Extensions.Logging; +using Microsoft.TemplateEngine.TestHelper; +using Xunit.Abstractions; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests +{ + public class VerificationEngineTests + { + private readonly ILogger _log; + + public VerificationEngineTests(ITestOutputHelper log) + { + _log = new XunitLoggerProvider(log).CreateLogger("TestRun"); + } + + [Fact] + public async void VerificationEngineFullDevLoop() + { + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string templateDir = "path with spaces"; + + TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: "console") + { + TemplateSpecificArgs = new string[] { "--use-program-main", "-o", templateDir, "--no-restore" }, + DisableDiffTool = true, + ExpectationsDirectory = expectationsDir, + OutputDirectory = workingDir, + VerifyCommandOutput = true, + UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, + }; + + VerificationEngine engine = new VerificationEngine(options, _log); + Func executeTask = () => engine.Execute(); + await executeTask + .Should() + .ThrowAsync() + .Where(e => e.TemplateVerificationErrorCode == TemplateVerificationErrorCode.VerificationFailed); + + // Assert template created + Directory.Exists(Path.Combine(workingDir, templateDir)).Should().BeTrue(); + File.Exists(Path.Combine(workingDir, templateDir, "console.csproj")).Should().BeTrue(); + File.Exists(Path.Combine(workingDir, templateDir, "Program.cs")).Should().BeTrue(); + + // Assert verification files created + Directory.Exists(expectationsDir).Should().BeTrue(); + Directory.GetDirectories(expectationsDir).Length.Should().Be(2); + //for simplicity move to the received dir + expectationsDir = Directory.GetDirectories(expectationsDir).Single(d => d.EndsWith(".received", StringComparison.Ordinal)); + File.Exists(Path.Combine(expectationsDir, templateDir, "console.csproj")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, templateDir, "Program.cs")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "std-streams", "stdout.txt")).Should().BeTrue(); + File.Exists(Path.Combine(expectationsDir, "std-streams", "stderr.txt")).Should().BeTrue(); + Directory.GetFiles(expectationsDir, "*", SearchOption.AllDirectories).Length.Should().Be(4); + + File.ReadAllText(Path.Combine(expectationsDir, templateDir, "console.csproj").UnixifyLineBreaks()).Should() + .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "console.csproj")).UnixifyLineBreaks()); + File.ReadAllText(Path.Combine(expectationsDir, templateDir, "Program.cs").UnixifyLineBreaks()).Should() + .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "Program.cs")).UnixifyLineBreaks()); + + // Accept changes + string verifiedDir = expectationsDir.Replace(".received", ".verified", StringComparison.Ordinal); + Directory.Delete(verifiedDir, false); + Directory.Move(expectationsDir, verifiedDir); + + //reset the expectations dir to where it was before previous run + expectationsDir = Path.GetDirectoryName(expectationsDir)!; + + // And run again same scenario - verification should succeed now + string workingDir2 = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + + TemplateVerifierOptions options2 = new TemplateVerifierOptions(templateName: "console") + { + TemplateSpecificArgs = new string[] { "--use-program-main", "-o", templateDir, "--no-restore" }, + DisableDiffTool = true, + ExpectationsDirectory = expectationsDir, + OutputDirectory = workingDir2, + VerifyCommandOutput = true, + UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, + }; + + VerificationEngine engine2 = new VerificationEngine(options2, _log); + Func executeTask2 = () => engine2.Execute(); + await executeTask2 + .Should() + .NotThrowAsync(); + + Directory.Delete(workingDir, true); + Directory.Delete(workingDir2, true); + Directory.Delete(expectationsDir, true); + } + + [Fact] + public async void VerificationEngineCustomVerifier() + { + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string templateDir = "path with spaces"; + + TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: "console") + { + TemplateSpecificArgs = new string[] { "--use-program-main", "-o", templateDir, "--no-restore" }, + DisableDiffTool = true, + OutputDirectory = workingDir, + VerificationExcludePatterns = new[] { "*.cs" }, + VerifyCommandOutput = true, + UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, + } + .WithCustomScrubbers( + ScrubbersDefinition.Empty + .AddScrubber(sb => sb.Replace("Donut", "Veggies"), ".txt") + .AddScrubber(sb => sb.Replace(DateTime.UtcNow.ToString("yyyy-MM-dd"), "2000-01-01")) + ) + .WithCustomDirectoryVerifier( + async (content, contentFetcher) => + { + await foreach (var file in contentFetcher.Value) + { + if (Path.GetExtension(file.FilePath).Equals(".cs")) + { + throw new Exception(".cs files should be excluded per VerificationExcludePatterns"); + } + + if (Path.GetFileName(file.FilePath).Equals("stdout.txt", StringComparison.OrdinalIgnoreCase) + && !file.ScrubbedContent.Contains("Console")) + { + throw new Exception("stdout should contain 'Console'"); + } + + if (Path.GetExtension(file.FilePath).Equals(".csproj") + && !file.ScrubbedContent.Contains("enable")) + { + throw new Exception("Implicit usings should be used"); + } + } + } + ); + + VerificationEngine engine = new VerificationEngine(options, _log); + Func executeTask = () => engine.Execute(); + await executeTask + .Should() + .NotThrowAsync(); + + Directory.Delete(workingDir, true); + } + } +} diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj new file mode 100644 index 0000000000..d5e5095ce2 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj @@ -0,0 +1,13 @@ + + + $(NETCoreTargetFramework) + enable + enable + + + + + + + + From bced6df398f35abcea7281a7a7b8f9c065e59115 Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Wed, 5 Oct 2022 19:39:54 +0200 Subject: [PATCH 11/15] Add integration tests and unit tests --- Microsoft.TemplateEngine.sln | 30 +-- .../Commands/Verify/VerifyCommand.cs | 31 +-- .../Commands/Verify/VerifyCommandArgs.cs | 16 +- .../Globals.cs | 2 +- .../Globals.cs | 2 + .../IFileSystem.cs | 21 ++ .../LocalizableStrings.Designer.cs | 9 + .../LocalizableStrings.resx | 3 + .../PhysicalFileSystem.cs | 21 ++ .../PublicAPI.Unshipped.txt | 1 + .../ScrubbersDefinition.cs | 9 +- .../TemplateVerificationErrorCode.cs | 5 + .../VerificationEngine.cs | 214 ++++++++++-------- .../xlf/LocalizableStrings.cs.xlf | 5 + .../xlf/LocalizableStrings.de.xlf | 5 + .../xlf/LocalizableStrings.es.xlf | 5 + .../xlf/LocalizableStrings.fr.xlf | 5 + .../xlf/LocalizableStrings.it.xlf | 5 + .../xlf/LocalizableStrings.ja.xlf | 5 + .../xlf/LocalizableStrings.ko.xlf | 5 + .../xlf/LocalizableStrings.pl.xlf | 5 + .../xlf/LocalizableStrings.pt-BR.xlf | 5 + .../xlf/LocalizableStrings.ru.xlf | 5 + .../xlf/LocalizableStrings.tr.xlf | 5 + .../xlf/LocalizableStrings.zh-Hans.xlf | 5 + .../xlf/LocalizableStrings.zh-Hant.xlf | 5 + ...lateEngine.Authoring.CLI.UnitTests.csproj} | 0 .../VerifyCommandArgsTests.cs | 2 +- .../VerifyCommandTests.cs | 97 ++++++++ ...uthoring.TemplateVerifier.UnitTests.csproj | 5 + .../VerificationEngineTests.cs | 63 ++++++ 31 files changed, 462 insertions(+), 134 deletions(-) create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IFileSystem.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystem.cs rename test/{Microsoft.TemplateEngine.Authoring.CLI.Tests/Microsoft.TemplateEngine.Authoring.CLI.Tests.csproj => Microsoft.TemplateEngine.Authoring.CLI.UnitTests/Microsoft.TemplateEngine.Authoring.CLI.UnitTests.csproj} (100%) rename test/{Microsoft.TemplateEngine.Authoring.CLI.Tests => Microsoft.TemplateEngine.Authoring.CLI.UnitTests}/VerifyCommandArgsTests.cs (94%) create mode 100644 test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandTests.cs create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs diff --git a/Microsoft.TemplateEngine.sln b/Microsoft.TemplateEngine.sln index 3f045b2ef2..3d6a02719b 100644 --- a/Microsoft.TemplateEngine.sln +++ b/Microsoft.TemplateEngine.sln @@ -68,12 +68,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{B794BF86 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier", "src\Microsoft.TemplateEngine.Authoring.TemplateVerifier\Microsoft.TemplateEngine.Authoring.TemplateVerifier.csproj", "{12764D81-61A7-437A-90B6-9F245E43F457}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.CLI.Tests", "test\Microsoft.TemplateEngine.Authoring.CLI.Tests\Microsoft.TemplateEngine.Authoring.CLI.Tests.csproj", "{F1860546-A949-4A16-ACB2-0C4C3CA2C970}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests", "test\Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests\Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj", "{B1DDA327-F55E-466A-AF3E-7F039B9B51A9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests", "test\Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests\Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj", "{D478568D-CA20-4331-9019-F585B564425E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.TemplateEngine.Authoring.CLI.UnitTests", "test\Microsoft.TemplateEngine.Authoring.CLI.UnitTests\Microsoft.TemplateEngine.Authoring.CLI.UnitTests.csproj", "{E8B9226E-879F-495A-BDAD-2607844D048C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -408,18 +408,6 @@ Global {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x64.Build.0 = Release|Any CPU {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x86.ActiveCfg = Release|Any CPU {12764D81-61A7-437A-90B6-9F245E43F457}.Release|x86.Build.0 = Release|Any CPU - {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|x64.ActiveCfg = Debug|Any CPU - {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|x64.Build.0 = Debug|Any CPU - {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|x86.ActiveCfg = Debug|Any CPU - {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Debug|x86.Build.0 = Debug|Any CPU - {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|Any CPU.Build.0 = Release|Any CPU - {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|x64.ActiveCfg = Release|Any CPU - {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|x64.Build.0 = Release|Any CPU - {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|x86.ActiveCfg = Release|Any CPU - {F1860546-A949-4A16-ACB2-0C4C3CA2C970}.Release|x86.Build.0 = Release|Any CPU {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|Any CPU.Build.0 = Debug|Any CPU {B1DDA327-F55E-466A-AF3E-7F039B9B51A9}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -444,6 +432,18 @@ Global {D478568D-CA20-4331-9019-F585B564425E}.Release|x64.Build.0 = Release|Any CPU {D478568D-CA20-4331-9019-F585B564425E}.Release|x86.ActiveCfg = Release|Any CPU {D478568D-CA20-4331-9019-F585B564425E}.Release|x86.Build.0 = Release|Any CPU + {E8B9226E-879F-495A-BDAD-2607844D048C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E8B9226E-879F-495A-BDAD-2607844D048C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E8B9226E-879F-495A-BDAD-2607844D048C}.Debug|x64.ActiveCfg = Debug|Any CPU + {E8B9226E-879F-495A-BDAD-2607844D048C}.Debug|x64.Build.0 = Debug|Any CPU + {E8B9226E-879F-495A-BDAD-2607844D048C}.Debug|x86.ActiveCfg = Debug|Any CPU + {E8B9226E-879F-495A-BDAD-2607844D048C}.Debug|x86.Build.0 = Debug|Any CPU + {E8B9226E-879F-495A-BDAD-2607844D048C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E8B9226E-879F-495A-BDAD-2607844D048C}.Release|Any CPU.Build.0 = Release|Any CPU + {E8B9226E-879F-495A-BDAD-2607844D048C}.Release|x64.ActiveCfg = Release|Any CPU + {E8B9226E-879F-495A-BDAD-2607844D048C}.Release|x64.Build.0 = Release|Any CPU + {E8B9226E-879F-495A-BDAD-2607844D048C}.Release|x86.ActiveCfg = Release|Any CPU + {E8B9226E-879F-495A-BDAD-2607844D048C}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -476,9 +476,9 @@ Global {BD758B10-A47F-4159-B9A1-997723AF7349} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B} {2FFDBB61-8AE8-468B-87D3-0D907D7C2FFE} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} {12764D81-61A7-437A-90B6-9F245E43F457} = {B794BF86-4185-4DCE-AC86-C27D5D966B9B} - {F1860546-A949-4A16-ACB2-0C4C3CA2C970} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} {B1DDA327-F55E-466A-AF3E-7F039B9B51A9} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} {D478568D-CA20-4331-9019-F585B564425E} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} + {E8B9226E-879F-495A-BDAD-2607844D048C} = {8B498D0C-F488-4B38-8A7D-B20BF9DB6F60} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {6EA1A508-6033-4538-BF98-7F71B4E297AD} diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs index 6cb85061a2..bc5f3acbda 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs @@ -105,6 +105,23 @@ public VerifyCommand(ILoggerFactory loggerFactory) AddOption(_uniqueForOption); } + internal static VerifyCommandArgs ExtractArguments(VerifyCommand verifyCommand, ParseResult parseResult) + { + return new VerifyCommandArgs( + templateName: parseResult.GetValueForArgument(verifyCommand._templateNameArgument), + templateSpecificArgs: parseResult.GetValueForOption(verifyCommand._remainingArguments), + templatePath: parseResult.GetValueForOption(verifyCommand._templatePathOption), + dotnetNewCommandAssemblyPath: parseResult.GetValueForOption(verifyCommand._newCommandPathOption), + expectationsDirectory: parseResult.GetValueForOption(verifyCommand._expectationsDirectoryOption), + outputDirectory: parseResult.GetValueForOption(verifyCommand._templateOutputPathOption), + disableDiffTool: parseResult.GetValueForOption(verifyCommand._disableDiffToolOption), + disableDefaultVerificationExcludePatterns: parseResult.GetValueForOption(verifyCommand._disableDefaultExcludePatternsOption), + verificationExcludePatterns: parseResult.GetValueForOption(verifyCommand._excludePatternOption), + verifyCommandOutput: parseResult.GetValueForOption(verifyCommand._verifyCommandOutputOption), + isCommandExpectedToFail: parseResult.GetValueForOption(verifyCommand._isCommandExpectedToFailOption), + uniqueForOptions: parseResult.GetValueForOption(verifyCommand._uniqueForOption)); + } + protected override async Task ExecuteAsync(VerifyCommandArgs args, CancellationToken cancellationToken = default) { Logger.LogInformation("Running the verification of {templateName}.", args.TemplateName); @@ -175,19 +192,7 @@ internal VerifyModelBinder(VerifyCommand verifyCommand) protected override VerifyCommandArgs GetBoundValue(BindingContext bindingContext) { - return new VerifyCommandArgs( - templateName: bindingContext.ParseResult.GetValueForArgument(_verifyCommand._templateNameArgument), - templateSpecificArgs: bindingContext.ParseResult.GetValueForOption(_verifyCommand._remainingArguments), - templatePath: bindingContext.ParseResult.GetValueForOption(_verifyCommand._templatePathOption), - dotnetNewCommandAssemblyPath: bindingContext.ParseResult.GetValueForOption(_verifyCommand._newCommandPathOption), - expectationsDirectory: bindingContext.ParseResult.GetValueForOption(_verifyCommand._expectationsDirectoryOption), - outputDirectory: bindingContext.ParseResult.GetValueForOption(_verifyCommand._templateOutputPathOption), - disableDiffTool: bindingContext.ParseResult.GetValueForOption(_verifyCommand._disableDiffToolOption), - disableDefaultVerificationExcludePatterns: bindingContext.ParseResult.GetValueForOption(_verifyCommand._disableDefaultExcludePatternsOption), - verificationExcludePatterns: bindingContext.ParseResult.GetValueForOption(_verifyCommand._excludePatternOption), - verifyCommandOutput: bindingContext.ParseResult.GetValueForOption(_verifyCommand._verifyCommandOutputOption), - isCommandExpectedToFail: bindingContext.ParseResult.GetValueForOption(_verifyCommand._isCommandExpectedToFailOption), - uniqueForOptions: bindingContext.ParseResult.GetValueForOption(_verifyCommand._uniqueForOption)); + return VerifyCommand.ExtractArguments(_verifyCommand, bindingContext.ParseResult); } } } diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs index fc36314df6..a6fb0b2cdd 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommandArgs.cs @@ -11,6 +11,12 @@ namespace Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify /// internal sealed class VerifyCommandArgs { + public VerifyCommandArgs(string templateName, string? templateSpecificArgs) + { + TemplateName = templateName; + TemplateSpecificArgs = TokenizeJoinedArgs(templateSpecificArgs); + } + public VerifyCommandArgs( string templateName, string? templatePath, @@ -24,10 +30,9 @@ public VerifyCommandArgs( bool? verifyCommandOutput, bool isCommandExpectedToFail, IEnumerable? uniqueForOptions) + : this(templateName, templateSpecificArgs) { - TemplateName = templateName; TemplatePath = templatePath; - TemplateSpecificArgs = TokenizeJoinedArgs(templateSpecificArgs); DotnetNewCommandAssemblyPath = dotnetNewCommandAssemblyPath; ExpectationsDirectory = expectationsDirectory; OutputDirectory = outputDirectory; @@ -36,7 +41,7 @@ public VerifyCommandArgs( VerificationExcludePatterns = verificationExcludePatterns; VerifyCommandOutput = verifyCommandOutput; IsCommandExpectedToFail = isCommandExpectedToFail; - UniqueFor = uniqueForOptions?.Aggregate(UniqueForOption.None, (a, b) => a | b); + UniqueFor = ToUniqueForOptionFlags(uniqueForOptions); } /// @@ -120,6 +125,11 @@ public static IEnumerable TokenizeJoinedArgs(string? joinedArgs) .Where(s => !string.IsNullOrWhiteSpace(s)); } + public static UniqueForOption? ToUniqueForOptionFlags(IEnumerable? uniqueForOptions) + { + return uniqueForOptions?.Aggregate(UniqueForOption.None, (a, b) => a | b); + } + private static string RemoveEnclosingQuotation(string input) { int indexOfLast = input.Length - 1; diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Globals.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Globals.cs index 9cc128d164..08fae9e6e6 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Globals.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Globals.cs @@ -4,4 +4,4 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] -[assembly: InternalsVisibleTo("Microsoft.TemplateEngine.Authoring.CLI.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.TemplateEngine.Authoring.CLI.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Globals.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Globals.cs index 66de30e624..974d69b2b9 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Globals.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Globals.cs @@ -4,3 +4,5 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IFileSystem.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IFileSystem.cs new file mode 100644 index 0000000000..7cdbdc8d31 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IFileSystem.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier +{ + internal interface IFileSystem + { + public bool DirectoryExists(string path); + + public IEnumerable EnumerateFiles(string path, string searchPattern, SearchOption searchOption); + + Task ReadAllTextAsync(string path); + + Task WriteAllTextAsync(string path, string? contents); + + void CreateDirectory(string path); + + void DeleteDirectory(string path, bool recursive); + + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs index cdc55bd7bf..06fe6f9322 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.Designer.cs @@ -69,6 +69,15 @@ internal static string VerificationEngine_Error_InstallUnexpectedFail { } } + /// + /// Looks up a localized string similar to File extension passed to scrubber should not start with dot.. + /// + internal static string VerificationEngine_Error_ScrubberExtension { + get { + return ResourceManager.GetString("VerificationEngine_Error_ScrubberExtension", resourceCulture); + } + } + /// /// Looks up a localized string similar to The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case.. /// diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx index 0b26f12919..2f13e36175 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/LocalizableStrings.resx @@ -120,6 +120,9 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. {0} is a folder path diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystem.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystem.cs new file mode 100644 index 0000000000..1a059c82f5 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystem.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier +{ + internal class PhysicalFileSystem : IFileSystem + { + public bool DirectoryExists(string path) => Directory.Exists(path); + + public IEnumerable EnumerateFiles(string path, string searchPattern, SearchOption searchOption) => + Directory.EnumerateFiles(path, searchPattern, searchOption); + + public Task ReadAllTextAsync(string path) => File.ReadAllTextAsync(path); + + public Task WriteAllTextAsync(string path, string? contents) => File.WriteAllTextAsync(path, contents); + + public void CreateDirectory(string path) => Directory.CreateDirectory(path); + + public void DeleteDirectory(string path, bool recursive) => Directory.Delete(path, recursive); + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt index 1369270f50..44b2e70dbf 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt @@ -8,6 +8,7 @@ Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCod Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InstallFailed = 106 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InstantiationFailed = 100 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InternalError = 70 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode +Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.InvalidOption = 127 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.TemplateDoesNotExist = 103 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.VerificationFailed = 65 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode.WorkingDirectoryExists = 73 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerificationErrorCode diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/ScrubbersDefinition.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/ScrubbersDefinition.cs index f573e6acd5..20c38b41f4 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/ScrubbersDefinition.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/ScrubbersDefinition.cs @@ -27,13 +27,18 @@ public ScrubbersDefinition AddScrubber(Action scrubber, string? e return new ScrubbersDefinition().AddScrubber(scrubber, extension); } - if (extension == null) + if (string.IsNullOrWhiteSpace(extension)) { GeneralScrubber += scrubber; } + // This is to get the same behavior as Verify.NET + else if (extension.Trim().StartsWith('.')) + { + throw new TemplateVerificationException(LocalizableStrings.VerificationEngine_Error_ScrubberExtension, TemplateVerificationErrorCode.InvalidOption); + } else { - ScrubersByExtension[extension] = scrubber; + ScrubersByExtension[extension.Trim()] = scrubber; } return this; diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs index 8ab6862b53..6a5a675435 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/TemplateVerificationErrorCode.cs @@ -44,5 +44,10 @@ public enum TemplateVerificationErrorCode /// Installation/Uninstallation Failed - Processing issues. /// InstallFailed = 106, + + /// + /// Unrecognized option(s) and/or argument(s) for a command. + /// + InvalidOption = 127, } } diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs index ac796df361..d24472e866 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs @@ -29,6 +29,7 @@ public class VerificationEngine private readonly ILogger _logger; private readonly ILoggerFactory? _loggerFactory; private readonly ICommandRunner _commandRunner = new CommandRunner(); + private readonly IFileSystem _fileSystem = new PhysicalFileSystem(); static VerificationEngine() { @@ -98,6 +99,92 @@ public async Task Execute(CancellationToken cancellationToken = default) await VerifyResult(_options, commandResult).ConfigureAwait(false); } + internal static Task CreateVerificationTask(string contentDir, TemplateVerifierOptions options, IFileSystem fileSystem) + { + List exclusionsList = (options.DisableDefaultVerificationExcludePatterns ?? false) + ? new() + : new(_defaultVerificationExcludePatterns); + + if (options.VerificationExcludePatterns != null) + { + exclusionsList.AddRange(options.VerificationExcludePatterns); + } + + List globs = exclusionsList.Select(pattern => Glob.Parse(pattern)).ToList(); + + if (options.CustomDirectoryVerifier != null) + { + return options.CustomDirectoryVerifier( + contentDir, + new Lazy>( + GetVerificationContent(contentDir, globs, options.CustomScrubbers, fileSystem))); + } + + VerifySettings verifySettings = new(); + + if (options.CustomScrubbers != null) + { + if (options.CustomScrubbers.GeneralScrubber != null) + { + verifySettings.AddScrubber(options.CustomScrubbers.GeneralScrubber); + } + + foreach (var pair in options.CustomScrubbers.ScrubersByExtension) + { + verifySettings.AddScrubber(pair.Key, pair.Value); + } + } + + verifySettings.UseTypeName(options.TemplateName); + verifySettings.UseDirectory(options.ExpectationsDirectory ?? "VerifyExpectations"); + verifySettings.UseMethodName(EncodeArgsAsPath(options.TemplateSpecificArgs)); + + if ((options.UniqueFor ?? UniqueForOption.None) != UniqueForOption.None) + { + foreach (UniqueForOption value in Enum.GetValues(typeof(UniqueForOption))) + { + if ((options.UniqueFor & value) == value) + { + switch (value) + { + case UniqueForOption.None: + break; + case UniqueForOption.Architecture: + verifySettings.UniqueForArchitecture(); + break; + case UniqueForOption.OsPlatform: + verifySettings.UniqueForOSPlatform(); + break; + case UniqueForOption.Runtime: + verifySettings.UniqueForRuntime(); + break; + case UniqueForOption.RuntimeAndVersion: + verifySettings.UniqueForRuntimeAndVersion(); + break; + case UniqueForOption.TargetFramework: + verifySettings.UniqueForTargetFramework(); + break; + case UniqueForOption.TargetFrameworkAndVersion: + verifySettings.UniqueForTargetFrameworkAndVersion(); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + } + } + + if (options.DisableDiffTool ?? false) + { + verifySettings.DisableDiff(); + } + + return Verifier.VerifyDirectory( + contentDir, + (filePath) => !globs.Any(g => g.IsMatch(filePath)), + settings: verifySettings); + } + private static string EncodeArgsAsPath(IEnumerable? args) { if (args == null || !args.Any()) @@ -185,119 +272,48 @@ private static CommandResultData RunDotnetNewCommand(TemplateVerifierOptions opt return result; } - private static Task CreateVerificationTask(string contentDir, TemplateVerifierOptions options) - { - List exclusionsList = (options.DisableDefaultVerificationExcludePatterns ?? false) - ? new() - : new(_defaultVerificationExcludePatterns); - - if (options.VerificationExcludePatterns != null) - { - exclusionsList.AddRange(options.VerificationExcludePatterns); - } - - List globs = exclusionsList.Select(pattern => Glob.Parse(pattern)).ToList(); - - if (options.CustomDirectoryVerifier != null) - { - return options.CustomDirectoryVerifier( - contentDir, - new Lazy>( - GetVerificationContent(contentDir, globs, options.CustomScrubbers))); - } - - VerifySettings verifySettings = new(); - - if (options.CustomScrubbers != null) - { - if (options.CustomScrubbers.GeneralScrubber != null) - { - verifySettings.AddScrubber(options.CustomScrubbers.GeneralScrubber); - } - - foreach (var pair in options.CustomScrubbers.ScrubersByExtension) - { - verifySettings.AddScrubber(pair.Key, pair.Value); - } - } - - verifySettings.UseTypeName(options.TemplateName); - verifySettings.UseDirectory(options.ExpectationsDirectory ?? "VerifyExpectations"); - verifySettings.UseMethodName(EncodeArgsAsPath(options.TemplateSpecificArgs)); - - if ((options.UniqueFor ?? UniqueForOption.None) != UniqueForOption.None) - { - foreach (UniqueForOption value in Enum.GetValues(typeof(UniqueForOption))) - { - if ((options.UniqueFor & value) == value) - { - switch (value) - { - case UniqueForOption.None: - break; - case UniqueForOption.Architecture: - verifySettings.UniqueForArchitecture(); - break; - case UniqueForOption.OsPlatform: - verifySettings.UniqueForOSPlatform(); - break; - case UniqueForOption.Runtime: - verifySettings.UniqueForRuntime(); - break; - case UniqueForOption.RuntimeAndVersion: - verifySettings.UniqueForRuntimeAndVersion(); - break; - case UniqueForOption.TargetFramework: - verifySettings.UniqueForTargetFramework(); - break; - case UniqueForOption.TargetFrameworkAndVersion: - verifySettings.UniqueForTargetFrameworkAndVersion(); - break; - default: - throw new ArgumentOutOfRangeException(); - } - } - } - } - - if (options.DisableDiffTool ?? false) - { - verifySettings.DisableDiff(); - } - - return Verifier.VerifyDirectory( - contentDir, - (filePath) => !globs.Any(g => g.IsMatch(filePath)), - settings: verifySettings); - } - private static void DummyMethod() { } - private static async IAsyncEnumerable<(string FilePath, string ScrubbedContent)> GetVerificationContent(string contentDir, List globs, ScrubbersDefinition? scrubbers) + private static async IAsyncEnumerable<(string FilePath, string ScrubbedContent)> GetVerificationContent( + string contentDir, + List globs, + ScrubbersDefinition? scrubbers, + IFileSystem fileSystem) { - foreach (string filePath in Directory.EnumerateFiles(contentDir, "*", SearchOption.AllDirectories)) + foreach (string filePath in fileSystem.EnumerateFiles(contentDir, "*", SearchOption.AllDirectories)) { if (globs.Any(g => g.IsMatch(filePath))) { continue; } - string content = await File.ReadAllTextAsync(filePath).ConfigureAwait(false); + string content = await fileSystem.ReadAllTextAsync(filePath).ConfigureAwait(false); if (scrubbers != null) { string extension = Path.GetExtension(filePath); - - if (string.IsNullOrEmpty(extension) || !scrubbers.ScrubersByExtension.TryGetValue(extension, out Action? scrubber)) + // This is to get the same behavior as Verify.NET + if (extension.Length > 0) { - scrubber = scrubbers.GeneralScrubber; + extension = extension[1..]; } + StringBuilder? sb = null; - if (scrubber != null) + if (!string.IsNullOrEmpty(extension) && scrubbers.ScrubersByExtension.TryGetValue(extension, out Action? scrubber)) { - var sb = new StringBuilder(content); + sb = new StringBuilder(content); scrubber(sb); + } + + if (scrubbers.GeneralScrubber != null) + { + sb = sb ?? new StringBuilder(content); + scrubbers.GeneralScrubber(sb); + } + + if (sb != null) + { content = sb.ToString(); } } @@ -317,7 +333,7 @@ private async Task VerifyResult(TemplateVerifierOptions args, CommandResultData if (_options.VerifyCommandOutput ?? false) { - if (Directory.Exists(Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir))) + if (_fileSystem.DirectoryExists(Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir))) { throw new TemplateVerificationException( string.Format( @@ -326,20 +342,20 @@ private async Task VerifyResult(TemplateVerifierOptions args, CommandResultData TemplateVerificationErrorCode.InternalError); } - Directory.CreateDirectory(Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir)); + _fileSystem.CreateDirectory(Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir)); - await File.WriteAllTextAsync( + await _fileSystem.WriteAllTextAsync( Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdOut + (_options.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)), commandResultData.StdOut) .ConfigureAwait(false); - await File.WriteAllTextAsync( + await _fileSystem.WriteAllTextAsync( Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdErr + (_options.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)), commandResultData.StdErr) .ConfigureAwait(false); } - Task verifyTask = CreateVerificationTask(commandResultData.WorkingDirectory, args); + Task verifyTask = CreateVerificationTask(commandResultData.WorkingDirectory, args, _fileSystem); try { diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf index ab6f73e4ec..bf14b01923 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.cs.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf index cb553651d2..1313fa12b5 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.de.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf index acfecd99d4..5b705cebdc 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.es.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf index 3e34eb02bf..0094d0c9c7 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.fr.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf index 4c47e8a3a6..6078316e39 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.it.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf index cfc1e0f951..b2de952bf6 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ja.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf index 1d01c029d5..8afaac8f26 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ko.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf index a890794172..ab145ca527 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pl.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf index 1e7cdff13c..5f67ef0a9a 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.pt-BR.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf index 9c07d9deec..4914bd0a68 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.ru.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf index ed1d88eedd..f52ec73632 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.tr.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf index 2352764aff..b2445f8d93 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hans.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf index 505eaaed90..42f012f204 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/xlf/LocalizableStrings.zh-Hant.xlf @@ -7,6 +7,11 @@ Template installation expected to pass but it had exit code '{0}'. + + File extension passed to scrubber should not start with dot. + File extension passed to scrubber should not start with dot. + + The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. The folder [{0}] should not exist in the template output - cannot verify stdout/stderr in such case. diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.Tests/Microsoft.TemplateEngine.Authoring.CLI.Tests.csproj b/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/Microsoft.TemplateEngine.Authoring.CLI.UnitTests.csproj similarity index 100% rename from test/Microsoft.TemplateEngine.Authoring.CLI.Tests/Microsoft.TemplateEngine.Authoring.CLI.Tests.csproj rename to test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/Microsoft.TemplateEngine.Authoring.CLI.UnitTests.csproj diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.Tests/VerifyCommandArgsTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandArgsTests.cs similarity index 94% rename from test/Microsoft.TemplateEngine.Authoring.CLI.Tests/VerifyCommandArgsTests.cs rename to test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandArgsTests.cs index a5b53e1378..8017674a03 100644 --- a/test/Microsoft.TemplateEngine.Authoring.CLI.Tests/VerifyCommandArgsTests.cs +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandArgsTests.cs @@ -4,7 +4,7 @@ using FluentAssertions; using Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify; -namespace Microsoft.TemplateEngine.Authoring.CLI.Tests +namespace Microsoft.TemplateEngine.Authoring.CLI.UnitTests { public class VerifyCommandArgsTests { diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandTests.cs new file mode 100644 index 0000000000..cd8577e5b9 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.UnitTests/VerifyCommandTests.cs @@ -0,0 +1,97 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Concurrent; +using System.CommandLine; +using FluentAssertions; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.TemplateEngine.Authoring.CLI.Commands.Verify; +using Microsoft.TemplateEngine.Authoring.TemplateVerifier; + +namespace Microsoft.TemplateEngine.Authoring.CLI.UnitTests +{ + public class VerifyCommandTests + { + public static IEnumerable CanParseVerifyCommandArgsData => + new object?[][] + { + new object[] + { + "someName -p path --template-args \" a b cc\" --disable-diff-tool", + new VerifyCommandArgs( + "someName", + " a b cc") + { + TemplatePath = "path", + DisableDiffTool = true, + DisableDefaultVerificationExcludePatterns = false, + VerificationExcludePatterns = Enumerable.Empty(), + VerifyCommandOutput = false, + IsCommandExpectedToFail = false, + UniqueFor = UniqueForOption.None, + } + }, + new object[] + { + "someName -p path --template-args \" a \'b cc\'\" --unique-for Runtime", + new VerifyCommandArgs( + "someName", + " a \"b cc\"") + { + TemplatePath = "path", + DisableDiffTool = false, + DisableDefaultVerificationExcludePatterns = false, + VerificationExcludePatterns = Enumerable.Empty(), + VerifyCommandOutput = false, + IsCommandExpectedToFail = false, + UniqueFor = UniqueForOption.Runtime, + } + }, + + new object[] + { + "someName", + new VerifyCommandArgs( + "someName", + null) + { + DisableDiffTool = false, + DisableDefaultVerificationExcludePatterns = false, + VerificationExcludePatterns = Enumerable.Empty(), + VerifyCommandOutput = false, + IsCommandExpectedToFail = false, + UniqueFor = UniqueForOption.None, + } + }, + new object[] + { + "someName --new-command-assembly a\\b\\c.dll", + new VerifyCommandArgs( + "someName", + null) + { + DotnetNewCommandAssemblyPath = "a\\b\\c.dll", + DisableDiffTool = false, + DisableDefaultVerificationExcludePatterns = false, + VerificationExcludePatterns = Enumerable.Empty(), + VerifyCommandOutput = false, + IsCommandExpectedToFail = false, + UniqueFor = UniqueForOption.None, + } + }, + }; + + [Theory] + [MemberData(nameof(CanParseVerifyCommandArgsData))] + internal void CanParseVerifyCommandArgs(string command, VerifyCommandArgs expVerifyCommandArgs) + { + VerifyCommand verifyCommand = new VerifyCommand(NullLoggerFactory.Instance); + + ParseResult parseResult = verifyCommand.Parse(command); + + VerifyCommandArgs args = VerifyCommand.ExtractArguments(verifyCommand, parseResult); + + args.Should().BeEquivalentTo(expVerifyCommandArgs); + } + } +} diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj index d5e5095ce2..1cb4ec940e 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj @@ -10,4 +10,9 @@ + + + + + diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs new file mode 100644 index 0000000000..9b5f149bbe --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using FakeItEasy; +using FluentAssertions; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests +{ + [UsesVerify] + public class VerificationEngineTests + { + [Fact] + public async void CreateVerificationTaskWithCustomScrubbersAndVerifier() + { + string verifyLocation = "foo\\bar\\baz"; + + Dictionary files = new Dictionary() + { + { "Program.cs", "aa bb cc" }, + { "Subfolder\\Class.cs", "123 456 789 aa" }, + { "out.dll", "a1 b2" } + }; + + IFileSystem fileSystem = A.Fake(); + A.CallTo(() => fileSystem.EnumerateFiles(verifyLocation, "*", SearchOption.AllDirectories)).Returns(files.Keys); + A.CallTo(() => fileSystem.ReadAllTextAsync(A._)).ReturnsLazily((string fileName) => Task.FromResult(files[fileName])); + + Dictionary resultContents = new Dictionary(); + + TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: "console") + { + TemplateSpecificArgs = null, + DisableDiffTool = null, + OutputDirectory = verifyLocation, + VerificationExcludePatterns = new[] { "*.dll" }, + VerifyCommandOutput = null, + UniqueFor = null, + } + .WithCustomScrubbers( + ScrubbersDefinition.Empty + .AddScrubber(sb => sb.Replace("bb", "xx"), "cs") + .AddScrubber(sb => sb.Replace("cc", "yy"), "dll") + .AddScrubber(sb => sb.Replace("123", "yy"), "dll") + .AddScrubber(sb => sb.Replace("aa", "zz")) + ) + .WithCustomDirectoryVerifier( + async (content, contentFetcher) => + { + await foreach (var file in contentFetcher.Value) + { + resultContents[file.FilePath] = file.ScrubbedContent; + } + } + ); + + await VerificationEngine.CreateVerificationTask(verifyLocation, options, fileSystem); + + resultContents.Keys.Count.Should().Be(2); + resultContents["Program.cs"].Should().BeEquivalentTo("zz xx cc"); + resultContents["Subfolder\\Class.cs"].Should().BeEquivalentTo("123 456 789 zz"); + } + } +} From 25018fccf3744ae8505f74296786d594a203c19a Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Thu, 6 Oct 2022 20:47:00 +0200 Subject: [PATCH 12/15] Add VerifyEngine unit tests, add ability to place expectations in code base or current dir --- .../Commands/Verify/VerifyCommand.cs | 41 ++--- .../std-streams/stderr.txt | 1 + .../std-streams/stdout.txt | 1 + .../PublicAPI.Unshipped.txt | 6 +- .../VerificationEngine.cs | 62 ++++--- ...gine.Authoring.CLI.IntegrationTests.csproj | 2 +- .../VerificationEngineTests.cs | 13 +- .../VerificationEngineTests.cs | 151 ------------------ .../std-streams/stderr.txt | 1 + .../std-streams/stdout.txt | 1 + .../std-streams/stderr.txt | 1 + .../std-streams/stdout.txt | 1 + ...uthoring.TemplateVerifier.UnitTests.csproj | 6 + .../VerificationEngineTests.cs | 93 ++++++++++- 14 files changed, 175 insertions(+), 205 deletions(-) create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt delete mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/VerificationEngineTests.cs create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.Windows.verified/std-streams/stderr.txt create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.Windows.verified/std-streams/stdout.txt diff --git a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs index bc5f3acbda..8a41dce441 100644 --- a/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs +++ b/src/Microsoft.TemplateEngine.Authoring.CLI/Commands/Verify/VerifyCommand.cs @@ -128,24 +128,29 @@ protected override async Task ExecuteAsync(VerifyCommandArgs args, Cancella try { - VerificationEngine engine = new VerificationEngine( - new TemplateVerifierOptions(templateName: args.TemplateName) - { - TemplatePath = args.TemplatePath, - TemplateSpecificArgs = args.TemplateSpecificArgs, - DisableDiffTool = args.DisableDiffTool, - DisableDefaultVerificationExcludePatterns = args.DisableDefaultVerificationExcludePatterns, - VerificationExcludePatterns = args.VerificationExcludePatterns, - DotnetNewCommandAssemblyPath = args.DotnetNewCommandAssemblyPath, - ExpectationsDirectory = args.ExpectationsDirectory, - OutputDirectory = args.OutputDirectory, - VerifyCommandOutput = args.VerifyCommandOutput, - IsCommandExpectedToFail = args.IsCommandExpectedToFail, - UniqueFor = args.UniqueFor, - }, - LoggerFactory ?? NullLoggerFactory.Instance - ); - await engine.Execute(cancellationToken).ConfigureAwait(false); + VerificationEngine engine = new VerificationEngine(LoggerFactory ?? NullLoggerFactory.Instance); + TemplateVerifierOptions options = new(templateName: args.TemplateName) + { + TemplatePath = args.TemplatePath, + TemplateSpecificArgs = args.TemplateSpecificArgs, + DisableDiffTool = args.DisableDiffTool, + DisableDefaultVerificationExcludePatterns = args.DisableDefaultVerificationExcludePatterns, + VerificationExcludePatterns = args.VerificationExcludePatterns, + DotnetNewCommandAssemblyPath = args.DotnetNewCommandAssemblyPath, + ExpectationsDirectory = args.ExpectationsDirectory, + OutputDirectory = args.OutputDirectory, + VerifyCommandOutput = args.VerifyCommandOutput, + IsCommandExpectedToFail = args.IsCommandExpectedToFail, + UniqueFor = args.UniqueFor, + }; + await engine.Execute( + options, + cancellationToken, + // We explicitly pass a path - so that the engine then process it and gets the current executing dir + // and treats it as a code base of caller of API (as in case of CLI usage we do not want to store + // expectation files in CLI sources dir) + Path.Combine(Environment.CurrentDirectory, "_") + ).ConfigureAwait(false); return 0; } catch (Exception e) diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt new file mode 100644 index 0000000000..994af8b0a8 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt @@ -0,0 +1 @@ +stderr content \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt new file mode 100644 index 0000000000..e9cc259327 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt @@ -0,0 +1 @@ +stdout content \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt index 44b2e70dbf..294d43a6a6 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PublicAPI.Unshipped.txt @@ -59,8 +59,8 @@ Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.RuntimeAndVe Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.TargetFramework = 16 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption.TargetFrameworkAndVersion = 32 -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.UniqueForOption Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine -Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine.Execute(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task! -Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine.VerificationEngine(Microsoft.Extensions.Options.IOptions! optionsAccessor, Microsoft.Extensions.Logging.ILogger! logger) -> void -Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine.VerificationEngine(Microsoft.TemplateEngine.Authoring.TemplateVerifier.TemplateVerifierOptions! options, Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine.Execute(Microsoft.Extensions.Options.IOptions! optionsAccessor, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken), string! sourceFile = "") -> System.Threading.Tasks.Task! +Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine.VerificationEngine(Microsoft.Extensions.Logging.ILogger! logger) -> void +Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerificationEngine.VerificationEngine(Microsoft.Extensions.Logging.ILoggerFactory! loggerFactory) -> void Microsoft.TemplateEngine.Authoring.TemplateVerifier.VerifyDirectory static readonly Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition.Empty -> Microsoft.TemplateEngine.Authoring.TemplateVerifier.ScrubbersDefinition! \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs index d24472e866..cd3f8dd222 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Reflection; +using System.Runtime.CompilerServices; using System.Text; using System.Text.RegularExpressions; using Microsoft.Extensions.Logging; @@ -25,7 +26,6 @@ public class VerificationEngine "*.exe", }; - private readonly TemplateVerifierOptions _options; private readonly ILogger _logger; private readonly ILoggerFactory? _loggerFactory; private readonly ICommandRunner _commandRunner = new CommandRunner(); @@ -38,34 +38,38 @@ static VerificationEngine() VerifierSettings.UseSplitModeForUniqueDirectory(); } - public VerificationEngine(IOptions optionsAccessor, ILogger logger) + public VerificationEngine(ILogger logger) { - if (optionsAccessor == null) - { - throw new ArgumentNullException(nameof(optionsAccessor)); - } - - _options = optionsAccessor.Value; _logger = logger; } - public VerificationEngine(TemplateVerifierOptions options, ILoggerFactory loggerFactory) - : this(options, loggerFactory.CreateLogger(typeof(VerificationEngine))) + public VerificationEngine(ILoggerFactory loggerFactory) + : this(loggerFactory.CreateLogger(typeof(VerificationEngine))) { _loggerFactory = loggerFactory; } - internal VerificationEngine(TemplateVerifierOptions options, ICommandRunner commandRunner, ILogger logger) - : this(options, logger) + internal VerificationEngine(ICommandRunner commandRunner, ILogger logger) + : this(logger) { _commandRunner = commandRunner; } - public async Task Execute(CancellationToken cancellationToken = default) + public async Task Execute( + IOptions optionsAccessor, + CancellationToken cancellationToken = default, + [CallerFilePath] string sourceFile = "") { - CommandResultData commandResult = RunDotnetNewCommand(_options, _commandRunner, _loggerFactory, _logger); + if (optionsAccessor == null) + { + throw new ArgumentNullException(nameof(optionsAccessor)); + } + + TemplateVerifierOptions options = optionsAccessor.Value; - if (_options.IsCommandExpectedToFail ?? false) + CommandResultData commandResult = RunDotnetNewCommand(options, _commandRunner, _loggerFactory, _logger); + + if (options.IsCommandExpectedToFail ?? false) { if (commandResult.ExitCode == 0) { @@ -85,7 +89,7 @@ public async Task Execute(CancellationToken cancellationToken = default) // We do not expect stderr in passing command. // However if verification of stdout and stderr is opted-in - we will let that verification validate the stderr content - if (!(_options.VerifyCommandOutput ?? false) && !string.IsNullOrEmpty(commandResult.StdErr)) + if (!(options.VerifyCommandOutput ?? false) && !string.IsNullOrEmpty(commandResult.StdErr)) { throw new TemplateVerificationException( string.Format( @@ -96,10 +100,15 @@ public async Task Execute(CancellationToken cancellationToken = default) } } - await VerifyResult(_options, commandResult).ConfigureAwait(false); + await VerifyResult(options, commandResult, string.IsNullOrEmpty(sourceFile) ? string.Empty : Path.GetDirectoryName(sourceFile)!) + .ConfigureAwait(false); } - internal static Task CreateVerificationTask(string contentDir, TemplateVerifierOptions options, IFileSystem fileSystem) + internal static Task CreateVerificationTask( + string contentDir, + string callerDir, + TemplateVerifierOptions options, + IFileSystem fileSystem) { List exclusionsList = (options.DisableDefaultVerificationExcludePatterns ?? false) ? new() @@ -136,7 +145,12 @@ internal static Task CreateVerificationTask(string contentDir, TemplateVerifierO } verifySettings.UseTypeName(options.TemplateName); - verifySettings.UseDirectory(options.ExpectationsDirectory ?? "VerifyExpectations"); + string expectationsDir = options.ExpectationsDirectory ?? "VerifyExpectations"; + if (!string.IsNullOrEmpty(callerDir) && !Path.IsPathRooted(expectationsDir)) + { + expectationsDir = Path.Combine(callerDir, expectationsDir); + } + verifySettings.UseDirectory(expectationsDir); verifySettings.UseMethodName(EncodeArgsAsPath(options.TemplateSpecificArgs)); if ((options.UniqueFor ?? UniqueForOption.None) != UniqueForOption.None) @@ -322,7 +336,7 @@ private static void DummyMethod() } } - private async Task VerifyResult(TemplateVerifierOptions args, CommandResultData commandResultData) + private async Task VerifyResult(TemplateVerifierOptions args, CommandResultData commandResultData, string callerDir) { UsesVerifyAttribute a = new UsesVerifyAttribute(); // https://github.com/VerifyTests/Verify/blob/d8cbe38f527d6788ecadd6205c82803bec3cdfa6/src/Verify.Xunit/Verifier.cs#L10 @@ -331,7 +345,7 @@ private async Task VerifyResult(TemplateVerifierOptions args, CommandResultData MethodInfo mi = v.Method; a.Before(mi); - if (_options.VerifyCommandOutput ?? false) + if (args.VerifyCommandOutput ?? false) { if (_fileSystem.DirectoryExists(Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir))) { @@ -345,17 +359,17 @@ private async Task VerifyResult(TemplateVerifierOptions args, CommandResultData _fileSystem.CreateDirectory(Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir)); await _fileSystem.WriteAllTextAsync( - Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdOut + (_options.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)), + Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdOut + (args.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)), commandResultData.StdOut) .ConfigureAwait(false); await _fileSystem.WriteAllTextAsync( - Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdErr + (_options.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)), + Path.Combine(commandResultData.WorkingDirectory, SpecialFiles.StandardStreamsDir, SpecialFiles.StdErr + (args.StandardOutputFileExtension ?? SpecialFiles.DefaultExtension)), commandResultData.StdErr) .ConfigureAwait(false); } - Task verifyTask = CreateVerificationTask(commandResultData.WorkingDirectory, args, _fileSystem); + Task verifyTask = CreateVerificationTask(commandResultData.WorkingDirectory, callerDir, args, _fileSystem); try { diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj index 10511e3363..0b4a64851c 100644 --- a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj @@ -17,7 +17,7 @@ - + diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs index ba163919de..b0000bfe19 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs @@ -34,8 +34,8 @@ public async void VerificationEngineFullDevLoop() UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, }; - VerificationEngine engine = new VerificationEngine(options, _log); - Func executeTask = () => engine.Execute(); + VerificationEngine engine = new VerificationEngine(_log); + Func executeTask = () => engine.Execute(options); await executeTask .Should() .ThrowAsync() @@ -83,8 +83,7 @@ await executeTask UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, }; - VerificationEngine engine2 = new VerificationEngine(options2, _log); - Func executeTask2 = () => engine2.Execute(); + Func executeTask2 = () => engine.Execute(options2); await executeTask2 .Should() .NotThrowAsync(); @@ -111,7 +110,7 @@ public async void VerificationEngineCustomVerifier() } .WithCustomScrubbers( ScrubbersDefinition.Empty - .AddScrubber(sb => sb.Replace("Donut", "Veggies"), ".txt") + .AddScrubber(sb => sb.Replace("Donut", "Veggies"), "txt") .AddScrubber(sb => sb.Replace(DateTime.UtcNow.ToString("yyyy-MM-dd"), "2000-01-01")) ) .WithCustomDirectoryVerifier( @@ -139,8 +138,8 @@ public async void VerificationEngineCustomVerifier() } ); - VerificationEngine engine = new VerificationEngine(options, _log); - Func executeTask = () => engine.Execute(); + VerificationEngine engine = new VerificationEngine(_log); + Func executeTask = () => engine.Execute(options); await executeTask .Should() .NotThrowAsync(); diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/VerificationEngineTests.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/VerificationEngineTests.cs deleted file mode 100644 index 3d323235cb..0000000000 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests/VerificationEngineTests.cs +++ /dev/null @@ -1,151 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using FluentAssertions; -using Microsoft.Extensions.Logging; -using Microsoft.TemplateEngine.TestHelper; -using Xunit.Abstractions; - -namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.Tests -{ - public class VerificationEngineTests - { - private readonly ILogger _log; - - public VerificationEngineTests(ITestOutputHelper log) - { - _log = new XunitLoggerProvider(log).CreateLogger("TestRun"); - } - - [Fact] - public async void VerificationEngineFullDevLoop() - { - string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); - string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); - string templateDir = "path with spaces"; - - TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: "console") - { - TemplateSpecificArgs = new string[] { "--use-program-main", "-o", templateDir, "--no-restore" }, - DisableDiffTool = true, - ExpectationsDirectory = expectationsDir, - OutputDirectory = workingDir, - VerifyCommandOutput = true, - UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, - }; - - VerificationEngine engine = new VerificationEngine(options, _log); - Func executeTask = () => engine.Execute(); - await executeTask - .Should() - .ThrowAsync() - .Where(e => e.TemplateVerificationErrorCode == TemplateVerificationErrorCode.VerificationFailed); - - // Assert template created - Directory.Exists(Path.Combine(workingDir, templateDir)).Should().BeTrue(); - File.Exists(Path.Combine(workingDir, templateDir, "console.csproj")).Should().BeTrue(); - File.Exists(Path.Combine(workingDir, templateDir, "Program.cs")).Should().BeTrue(); - - // Assert verification files created - Directory.Exists(expectationsDir).Should().BeTrue(); - Directory.GetDirectories(expectationsDir).Length.Should().Be(2); - //for simplicity move to the received dir - expectationsDir = Directory.GetDirectories(expectationsDir).Single(d => d.EndsWith(".received", StringComparison.Ordinal)); - File.Exists(Path.Combine(expectationsDir, templateDir, "console.csproj")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, templateDir, "Program.cs")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "std-streams", "stdout.txt")).Should().BeTrue(); - File.Exists(Path.Combine(expectationsDir, "std-streams", "stderr.txt")).Should().BeTrue(); - Directory.GetFiles(expectationsDir, "*", SearchOption.AllDirectories).Length.Should().Be(4); - - File.ReadAllText(Path.Combine(expectationsDir, templateDir, "console.csproj").UnixifyLineBreaks()).Should() - .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "console.csproj")).UnixifyLineBreaks()); - File.ReadAllText(Path.Combine(expectationsDir, templateDir, "Program.cs").UnixifyLineBreaks()).Should() - .BeEquivalentTo(File.ReadAllText(Path.Combine(workingDir, templateDir, "Program.cs")).UnixifyLineBreaks()); - - // Accept changes - string verifiedDir = expectationsDir.Replace(".received", ".verified", StringComparison.Ordinal); - Directory.Delete(verifiedDir, false); - Directory.Move(expectationsDir, verifiedDir); - - //reset the expectations dir to where it was before previous run - expectationsDir = Path.GetDirectoryName(expectationsDir)!; - - // And run again same scenario - verification should succeed now - string workingDir2 = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - - TemplateVerifierOptions options2 = new TemplateVerifierOptions(templateName: "console") - { - TemplateSpecificArgs = new string[] { "--use-program-main", "-o", templateDir, "--no-restore" }, - DisableDiffTool = true, - ExpectationsDirectory = expectationsDir, - OutputDirectory = workingDir2, - VerifyCommandOutput = true, - UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, - }; - - VerificationEngine engine2 = new VerificationEngine(options2, _log); - Func executeTask2 = () => engine2.Execute(); - await executeTask2 - .Should() - .NotThrowAsync(); - - Directory.Delete(workingDir, true); - Directory.Delete(workingDir2, true); - Directory.Delete(expectationsDir, true); - } - - [Fact] - public async void VerificationEngineCustomVerifier() - { - string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); - string templateDir = "path with spaces"; - - TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: "console") - { - TemplateSpecificArgs = new string[] { "--use-program-main", "-o", templateDir, "--no-restore" }, - DisableDiffTool = true, - OutputDirectory = workingDir, - VerificationExcludePatterns = new[] { "*.cs" }, - VerifyCommandOutput = true, - UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, - } - .WithCustomScrubbers( - ScrubbersDefinition.Empty - .AddScrubber(sb => sb.Replace("Donut", "Veggies"), ".txt") - .AddScrubber(sb => sb.Replace(DateTime.UtcNow.ToString("yyyy-MM-dd"), "2000-01-01")) - ) - .WithCustomDirectoryVerifier( - async (content, contentFetcher) => - { - await foreach (var file in contentFetcher.Value) - { - if (Path.GetExtension(file.FilePath).Equals(".cs")) - { - throw new Exception(".cs files should be excluded per VerificationExcludePatterns"); - } - - if (Path.GetFileName(file.FilePath).Equals("stdout.txt", StringComparison.OrdinalIgnoreCase) - && !file.ScrubbedContent.Contains("Console")) - { - throw new Exception("stdout should contain 'Console'"); - } - - if (Path.GetExtension(file.FilePath).Equals(".csproj") - && !file.ScrubbedContent.Contains("enable")) - { - throw new Exception("Implicit usings should be used"); - } - } - } - ); - - VerificationEngine engine = new VerificationEngine(options, _log); - Func executeTask = () => engine.Execute(); - await executeTask - .Should() - .NotThrowAsync(); - - Directory.Delete(workingDir, true); - } - } -} diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt new file mode 100644 index 0000000000..994af8b0a8 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt @@ -0,0 +1 @@ +stderr content \ No newline at end of file diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt new file mode 100644 index 0000000000..e9cc259327 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt @@ -0,0 +1 @@ +stdout content \ No newline at end of file diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.Windows.verified/std-streams/stderr.txt b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.Windows.verified/std-streams/stderr.txt new file mode 100644 index 0000000000..1980902be4 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.Windows.verified/std-streams/stderr.txt @@ -0,0 +1 @@ +another stderr content \ No newline at end of file diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.Windows.verified/std-streams/stdout.txt b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.Windows.verified/std-streams/stdout.txt new file mode 100644 index 0000000000..db3dcaee12 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.Windows.verified/std-streams/stdout.txt @@ -0,0 +1 @@ +different stdout content \ No newline at end of file diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj index 1cb4ec940e..6fe77a004d 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj @@ -15,4 +15,10 @@ + + + + + + diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs index 9b5f149bbe..ce1f890f73 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs @@ -1,14 +1,26 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.InteropServices.JavaScript; using FakeItEasy; using FluentAssertions; +using Microsoft.Extensions.Logging; +using Microsoft.TemplateEngine.Authoring.TemplateVerifier.Commands; +using Microsoft.TemplateEngine.TestHelper; +using Xunit.Abstractions; namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests { [UsesVerify] public class VerificationEngineTests { + private readonly ILogger _log; + + public VerificationEngineTests(ITestOutputHelper log) + { + _log = new XunitLoggerProvider(log).CreateLogger("TestRun"); + } + [Fact] public async void CreateVerificationTaskWithCustomScrubbersAndVerifier() { @@ -53,11 +65,90 @@ public async void CreateVerificationTaskWithCustomScrubbersAndVerifier() } ); - await VerificationEngine.CreateVerificationTask(verifyLocation, options, fileSystem); + await VerificationEngine.CreateVerificationTask(verifyLocation, "callerLocation", options, fileSystem); resultContents.Keys.Count.Should().Be(2); resultContents["Program.cs"].Should().BeEquivalentTo("zz xx cc"); resultContents["Subfolder\\Class.cs"].Should().BeEquivalentTo("123 456 789 zz"); } + + [Fact] + public async void ExecuteFailsOnInstantiationFailure() + { + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string expectationsDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + + ICommandRunner commandRunner = A.Fake(); + A.CallTo(() => commandRunner.RunCommand(A._)) + .Returns(new CommandResultData(20, "stdout content", "stderr content", workingDir)); + + TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: "made-up-template") + { + TemplateSpecificArgs = new string[] { "--a", "-b", "c", "--d" }, + DisableDiffTool = true, + ExpectationsDirectory = expectationsDir, + OutputDirectory = workingDir, + VerifyCommandOutput = true, + UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, + }; + + VerificationEngine engine = new VerificationEngine(_log); + Func executeTask = () => engine.Execute(options); + await executeTask + .Should() + .ThrowAsync() + .Where(e => e.TemplateVerificationErrorCode == TemplateVerificationErrorCode.InstantiationFailed); + + } + + [Fact] + public async void ExecuteSucceedsOnExpectedInstantiationFailure() + { + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string expectationsDir = "Expectations"; + + ICommandRunner commandRunner = A.Fake(); + A.CallTo(() => commandRunner.RunCommand(A._)) + .Returns(new CommandResultData(20, "stdout content", "stderr content", workingDir)); + + TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: "made-up-template") + { + TemplateSpecificArgs = new string[] { "--a", "-b", "c", "--d" }, + //DisableDiffTool = true, + ExpectationsDirectory = expectationsDir, + IsCommandExpectedToFail = true, + OutputDirectory = workingDir, + VerifyCommandOutput = true, + UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, + }; + + VerificationEngine engine = new VerificationEngine(commandRunner, _log); + await engine.Execute(options); + } + + [Fact] + public async void ExecuteSucceedsOnExpectedInstantiationSuccess() + { + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string expectationsDir = "Expectations"; + + ICommandRunner commandRunner = A.Fake(); + A.CallTo(() => commandRunner.RunCommand(A._)) + .Returns(new CommandResultData(0, "different stdout content", "another stderr content", workingDir)); + + TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: "made-up-template") + { + TemplateSpecificArgs = new string[] { "--x", "y", "-z" }, + //DisableDiffTool = true, + ExpectationsDirectory = expectationsDir, + IsCommandExpectedToFail = false, + OutputDirectory = workingDir, + VerifyCommandOutput = true, + UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, + }; + + VerificationEngine engine = new VerificationEngine(commandRunner, _log); + await engine.Execute(options); + } } } From e0d49da03b805fd42dd2bfe0b948e685ed14aaa1 Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Fri, 7 Oct 2022 18:45:54 +0200 Subject: [PATCH 13/15] Add sample usage in unit test --- .../TestAssets.SampleTestTemplate/Test.cs | 6 ++++ .../std-streams/stderr.txt | 1 + .../std-streams/stdout.txt | 1 + ...g.TemplateVerifier.IntegrationTests.csproj | 10 +++++++ .../.template.config/template.json | 24 ++++++++++++++++ .../TestTemplate/Test.cs | 11 ++++++++ .../VerificationEngineTests.cs | 28 +++++++++++++++++++ ...uthoring.TemplateVerifier.UnitTests.csproj | 4 +-- 8 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Expectations/TestAssets.SampleTestTemplate.--paramB#true.DotNet7_0.verified/TestAssets.SampleTestTemplate/Test.cs create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Expectations/TestAssets.SampleTestTemplate.--paramB#true.DotNet7_0.verified/std-streams/stderr.txt create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Expectations/TestAssets.SampleTestTemplate.--paramB#true.DotNet7_0.verified/std-streams/stdout.txt create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/.template.config/template.json create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/Test.cs diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Expectations/TestAssets.SampleTestTemplate.--paramB#true.DotNet7_0.verified/TestAssets.SampleTestTemplate/Test.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Expectations/TestAssets.SampleTestTemplate.--paramB#true.DotNet7_0.verified/TestAssets.SampleTestTemplate/Test.cs new file mode 100644 index 0000000000..e68913f9bb --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Expectations/TestAssets.SampleTestTemplate.--paramB#true.DotNet7_0.verified/TestAssets.SampleTestTemplate/Test.cs @@ -0,0 +1,6 @@ + +// value of paramA: false +// value of paramB: true + + + // ******* diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Expectations/TestAssets.SampleTestTemplate.--paramB#true.DotNet7_0.verified/std-streams/stderr.txt b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Expectations/TestAssets.SampleTestTemplate.--paramB#true.DotNet7_0.verified/std-streams/stderr.txt new file mode 100644 index 0000000000..5f282702bb --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Expectations/TestAssets.SampleTestTemplate.--paramB#true.DotNet7_0.verified/std-streams/stderr.txt @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Expectations/TestAssets.SampleTestTemplate.--paramB#true.DotNet7_0.verified/std-streams/stdout.txt b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Expectations/TestAssets.SampleTestTemplate.--paramB#true.DotNet7_0.verified/std-streams/stdout.txt new file mode 100644 index 0000000000..9e2d2f7ea3 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Expectations/TestAssets.SampleTestTemplate.--paramB#true.DotNet7_0.verified/std-streams/stdout.txt @@ -0,0 +1 @@ +The template "SampleTestTemplate" was created successfully. \ No newline at end of file diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj index d5e5095ce2..3d85044e87 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj @@ -10,4 +10,14 @@ + + + + + + + + + + diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/.template.config/template.json b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/.template.config/template.json new file mode 100644 index 0000000000..b60eb7bc74 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/.template.config/template.json @@ -0,0 +1,24 @@ +{ + "author": "Test Asset", + "classifications": [ "Test Asset" ], + "name": "SampleTestTemplate", + "generatorVersions": "[1.0.0.0-*)", + "groupIdentity": "TestAssets.SampleTestTemplate", + "precedence": "100", + "identity": "TestAssets.SampleTestTemplate", + "shortName": "TestAssets.SampleTestTemplate", + "symbols": { + "paramA": { + "type": "parameter", + "datatype": "string", + "replaces": "placeholderA", + "defaultValue": "false" + }, + "paramB": { + "type": "parameter", + "datatype": "string", + "isRequired": true, + "replaces": "placeholderB" + } + } +} diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/Test.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/Test.cs new file mode 100644 index 0000000000..0de65665c3 --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/Test.cs @@ -0,0 +1,11 @@ + +// value of paramA: placeholderA +// value of paramB: placeholderB + +//#if( paramA ) + // A is enabled +//#endif + +//#if( paramB ) + // B is enabled +//#endif diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs index b0000bfe19..fa4facc871 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs @@ -146,5 +146,33 @@ await executeTask Directory.Delete(workingDir, true); } + + [Fact] + public async void VerificationEngineSampleDogfoodTest() + { + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string templateShortName = "TestAssets.SampleTestTemplate"; + + //get the template location + string executingAssemblyPath = this.GetType().Assembly.Location; + string templateLocation = Path.Combine(Path.GetDirectoryName(executingAssemblyPath)!, "TestTemplate"); + + TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: templateShortName) + { + TemplateSpecificArgs = new string[] { "--paramB", "true" }, + TemplatePath = templateLocation, + ExpectationsDirectory = "Expectations", + OutputDirectory = workingDir, + VerifyCommandOutput = true, + UniqueFor = UniqueForOption.RuntimeAndVersion, + } + .WithCustomScrubbers( + ScrubbersDefinition.Empty + .AddScrubber(sb => sb.Replace("B is enabled", "*******")) + ); + + VerificationEngine engine = new VerificationEngine(_log); + await engine.Execute(options); + } } } diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj index 6fe77a004d..864aad8cfb 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests.csproj @@ -16,9 +16,9 @@ - + - + From 0513f64aa8aaad157d918067e278033fb10bdbaa Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Fri, 7 Oct 2022 18:57:48 +0200 Subject: [PATCH 14/15] Adjust assertions (OS agnostic) --- .../std-streams/stderr.txt | 0 .../std-streams/stdout.txt | 0 .../std-streams/stderr.txt | 0 .../std-streams/stdout.txt | 0 .../VerificationEngineTests.cs | 2 -- 5 files changed, 2 deletions(-) rename test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/{made-up-template.--a#-b#c#--d.Windows.verified => made-up-template.--a#-b#c#--d.verified}/std-streams/stderr.txt (100%) rename test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/{made-up-template.--a#-b#c#--d.Windows.verified => made-up-template.--a#-b#c#--d.verified}/std-streams/stdout.txt (100%) rename test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/{made-up-template.--x#y#-z.Windows.verified => made-up-template.--x#y#-z.verified}/std-streams/stderr.txt (100%) rename test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/{made-up-template.--x#y#-z.Windows.verified => made-up-template.--x#y#-z.verified}/std-streams/stdout.txt (100%) diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.verified/std-streams/stderr.txt similarity index 100% rename from test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt rename to test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.verified/std-streams/stderr.txt diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.verified/std-streams/stdout.txt similarity index 100% rename from test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt rename to test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--a#-b#c#--d.verified/std-streams/stdout.txt diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.Windows.verified/std-streams/stderr.txt b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.verified/std-streams/stderr.txt similarity index 100% rename from test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.Windows.verified/std-streams/stderr.txt rename to test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.verified/std-streams/stderr.txt diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.Windows.verified/std-streams/stdout.txt b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.verified/std-streams/stdout.txt similarity index 100% rename from test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.Windows.verified/std-streams/stdout.txt rename to test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/Expectations/made-up-template.--x#y#-z.verified/std-streams/stdout.txt diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs index ce1f890f73..a81d59b123 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs @@ -119,7 +119,6 @@ public async void ExecuteSucceedsOnExpectedInstantiationFailure() IsCommandExpectedToFail = true, OutputDirectory = workingDir, VerifyCommandOutput = true, - UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, }; VerificationEngine engine = new VerificationEngine(commandRunner, _log); @@ -144,7 +143,6 @@ public async void ExecuteSucceedsOnExpectedInstantiationSuccess() IsCommandExpectedToFail = false, OutputDirectory = workingDir, VerifyCommandOutput = true, - UniqueFor = UniqueForOption.OsPlatform | UniqueForOption.OsPlatform, }; VerificationEngine engine = new VerificationEngine(commandRunner, _log); From 9c4c7db4396cdb848e10fec9ffa6e00c62e65afe Mon Sep 17 00:00:00 2001 From: Jan Krivanek Date: Mon, 10 Oct 2022 14:52:54 +0200 Subject: [PATCH 15/15] Fix code locations --- .../std-streams/stderr.txt | 1 - .../std-streams/stdout.txt | 1 - .../IFileSystem.cs | 21 -------- .../IPhysicalFileSystemEx.cs | 20 ++++++++ .../PhysicalFileSystem.cs | 21 -------- .../PhysicalFileSystemEx.cs | 16 +++++++ .../VerificationEngine.cs | 6 +-- ...gine.Authoring.CLI.IntegrationTests.csproj | 4 -- .../VerifyCommandTests.cs | 5 +- .../ExampleTemplateTest.cs | 48 +++++++++++++++++++ ...g.TemplateVerifier.IntegrationTests.csproj | 9 ++-- .../.template.config/template.json | 24 ---------- .../TestTemplate/Test.cs | 11 ----- .../VerificationEngineTests.cs | 28 ----------- .../VerificationEngineTests.cs | 5 +- ...rosoft.TemplateEngine.TestTemplates.csproj | 4 +- .../.template.config/template.json | 0 .../test_templates}/TestTemplate/Test.cs | 0 18 files changed, 100 insertions(+), 124 deletions(-) delete mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt delete mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt delete mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IFileSystem.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IPhysicalFileSystemEx.cs delete mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystem.cs create mode 100644 src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystemEx.cs create mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/ExampleTemplateTest.cs delete mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/.template.config/template.json delete mode 100644 test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/Test.cs rename test/{Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests => Microsoft.TemplateEngine.TestTemplates/test_templates}/TestTemplate/.template.config/template.json (100%) rename test/{Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests => Microsoft.TemplateEngine.TestTemplates/test_templates}/TestTemplate/Test.cs (100%) diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt deleted file mode 100644 index 994af8b0a8..0000000000 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stderr.txt +++ /dev/null @@ -1 +0,0 @@ -stderr content \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt deleted file mode 100644 index e9cc259327..0000000000 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/Expectations/made-up-template.--a#-b#c#--d.Windows.verified/std-streams/stdout.txt +++ /dev/null @@ -1 +0,0 @@ -stdout content \ No newline at end of file diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IFileSystem.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IFileSystem.cs deleted file mode 100644 index 7cdbdc8d31..0000000000 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IFileSystem.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier -{ - internal interface IFileSystem - { - public bool DirectoryExists(string path); - - public IEnumerable EnumerateFiles(string path, string searchPattern, SearchOption searchOption); - - Task ReadAllTextAsync(string path); - - Task WriteAllTextAsync(string path, string? contents); - - void CreateDirectory(string path); - - void DeleteDirectory(string path, bool recursive); - - } -} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IPhysicalFileSystemEx.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IPhysicalFileSystemEx.cs new file mode 100644 index 0000000000..abb48993ce --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/IPhysicalFileSystemEx.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.TemplateEngine.Abstractions.PhysicalFileSystem; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier +{ + internal interface IPhysicalFileSystemEx : IPhysicalFileSystem + { + /// + /// Same behavior as . + /// + Task ReadAllTextAsync(string path, CancellationToken cancellationToken = default); + + /// + /// Same behavior as . + /// + Task WriteAllTextAsync(string path, string? contents, CancellationToken cancellationToken = default); + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystem.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystem.cs deleted file mode 100644 index 1a059c82f5..0000000000 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystem.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier -{ - internal class PhysicalFileSystem : IFileSystem - { - public bool DirectoryExists(string path) => Directory.Exists(path); - - public IEnumerable EnumerateFiles(string path, string searchPattern, SearchOption searchOption) => - Directory.EnumerateFiles(path, searchPattern, searchOption); - - public Task ReadAllTextAsync(string path) => File.ReadAllTextAsync(path); - - public Task WriteAllTextAsync(string path, string? contents) => File.WriteAllTextAsync(path, contents); - - public void CreateDirectory(string path) => Directory.CreateDirectory(path); - - public void DeleteDirectory(string path, bool recursive) => Directory.Delete(path, recursive); - } -} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystemEx.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystemEx.cs new file mode 100644 index 0000000000..fb9e245e88 --- /dev/null +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/PhysicalFileSystemEx.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.TemplateEngine.Utils; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier +{ + internal class PhysicalFileSystemEx : PhysicalFileSystem, IPhysicalFileSystemEx + { + public Task ReadAllTextAsync(string path, CancellationToken cancellationToken = default) + => File.ReadAllTextAsync(path, cancellationToken); + + public Task WriteAllTextAsync(string path, string? contents, CancellationToken cancellationToken = default) + => File.WriteAllTextAsync(path, contents, cancellationToken); + } +} diff --git a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs index cd3f8dd222..5848ee370b 100644 --- a/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs +++ b/src/Microsoft.TemplateEngine.Authoring.TemplateVerifier/VerificationEngine.cs @@ -29,7 +29,7 @@ public class VerificationEngine private readonly ILogger _logger; private readonly ILoggerFactory? _loggerFactory; private readonly ICommandRunner _commandRunner = new CommandRunner(); - private readonly IFileSystem _fileSystem = new PhysicalFileSystem(); + private readonly IPhysicalFileSystemEx _fileSystem = new PhysicalFileSystemEx(); static VerificationEngine() { @@ -108,7 +108,7 @@ internal static Task CreateVerificationTask( string contentDir, string callerDir, TemplateVerifierOptions options, - IFileSystem fileSystem) + IPhysicalFileSystemEx fileSystem) { List exclusionsList = (options.DisableDefaultVerificationExcludePatterns ?? false) ? new() @@ -293,7 +293,7 @@ private static void DummyMethod() string contentDir, List globs, ScrubbersDefinition? scrubbers, - IFileSystem fileSystem) + IPhysicalFileSystemEx fileSystem) { foreach (string filePath in fileSystem.EnumerateFiles(contentDir, "*", SearchOption.AllDirectories)) { diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj index 0b4a64851c..cde80c6391 100644 --- a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests.csproj @@ -14,10 +14,6 @@ - - - - diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs index 517b3c3340..cca64ae001 100644 --- a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs +++ b/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/VerifyCommandTests.cs @@ -5,12 +5,13 @@ using Microsoft.TemplateEngine.Authoring.TemplateVerifier; using Microsoft.TemplateEngine.TestHelper; using Microsoft.TemplateEngine.TestHelper.Commands; +using Microsoft.TemplateEngine.Tests; using Xunit.Abstractions; namespace Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests { [UsesVerify] - public class VerifyCommandTests + public class VerifyCommandTests : TestBase { private readonly ITestOutputHelper _log; @@ -132,7 +133,7 @@ public void VerifyCommandFullDevLoopWithNotInstalledTemplate() //get the template location string executingAssemblyPath = this.GetType().Assembly.Location; - string templateLocation = Path.Combine(Path.GetDirectoryName(executingAssemblyPath)!, "TestTemplate"); + string templateLocation = Path.Combine(TestTemplatesLocation, "TestTemplate"); var cmd = new BasicCommand( _log, diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/ExampleTemplateTest.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/ExampleTemplateTest.cs new file mode 100644 index 0000000000..78e5ed28da --- /dev/null +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/ExampleTemplateTest.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Logging; +using Microsoft.TemplateEngine.TestHelper; +using Microsoft.TemplateEngine.Tests; +using Xunit.Abstractions; + +namespace Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests +{ + public class ExampleTemplateTest : TestBase + { + private readonly ILogger _log; + + public ExampleTemplateTest(ITestOutputHelper log) + { + _log = new XunitLoggerProvider(log).CreateLogger("TestRun"); + } + + [Fact] + public async void VerificationEngineSampleDogfoodTest() + { + string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); + string templateShortName = "TestAssets.SampleTestTemplate"; + + //get the template location + string executingAssemblyPath = this.GetType().Assembly.Location; + string templateLocation = Path.Combine(TestTemplatesLocation, "TestTemplate"); + + TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: templateShortName) + { + TemplateSpecificArgs = new string[] { "--paramB", "true" }, + TemplatePath = templateLocation, + ExpectationsDirectory = "Expectations", + OutputDirectory = workingDir, + VerifyCommandOutput = true, + UniqueFor = UniqueForOption.RuntimeAndVersion, + } + .WithCustomScrubbers( + ScrubbersDefinition.Empty + .AddScrubber(sb => sb.Replace("B is enabled", "*******")) + ); + + VerificationEngine engine = new VerificationEngine(_log); + await engine.Execute(options); + } + } +} diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj index 3d85044e87..db7748bf8e 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests.csproj @@ -8,16 +8,17 @@ + - - - - + + + + diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/.template.config/template.json b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/.template.config/template.json deleted file mode 100644 index b60eb7bc74..0000000000 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/.template.config/template.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "author": "Test Asset", - "classifications": [ "Test Asset" ], - "name": "SampleTestTemplate", - "generatorVersions": "[1.0.0.0-*)", - "groupIdentity": "TestAssets.SampleTestTemplate", - "precedence": "100", - "identity": "TestAssets.SampleTestTemplate", - "shortName": "TestAssets.SampleTestTemplate", - "symbols": { - "paramA": { - "type": "parameter", - "datatype": "string", - "replaces": "placeholderA", - "defaultValue": "false" - }, - "paramB": { - "type": "parameter", - "datatype": "string", - "isRequired": true, - "replaces": "placeholderB" - } - } -} diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/Test.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/Test.cs deleted file mode 100644 index 0de65665c3..0000000000 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/TestTemplate/Test.cs +++ /dev/null @@ -1,11 +0,0 @@ - -// value of paramA: placeholderA -// value of paramB: placeholderB - -//#if( paramA ) - // A is enabled -//#endif - -//#if( paramB ) - // B is enabled -//#endif diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs index fa4facc871..b0000bfe19 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.IntegrationTests/VerificationEngineTests.cs @@ -146,33 +146,5 @@ await executeTask Directory.Delete(workingDir, true); } - - [Fact] - public async void VerificationEngineSampleDogfoodTest() - { - string workingDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", string.Empty)); - string templateShortName = "TestAssets.SampleTestTemplate"; - - //get the template location - string executingAssemblyPath = this.GetType().Assembly.Location; - string templateLocation = Path.Combine(Path.GetDirectoryName(executingAssemblyPath)!, "TestTemplate"); - - TemplateVerifierOptions options = new TemplateVerifierOptions(templateName: templateShortName) - { - TemplateSpecificArgs = new string[] { "--paramB", "true" }, - TemplatePath = templateLocation, - ExpectationsDirectory = "Expectations", - OutputDirectory = workingDir, - VerifyCommandOutput = true, - UniqueFor = UniqueForOption.RuntimeAndVersion, - } - .WithCustomScrubbers( - ScrubbersDefinition.Empty - .AddScrubber(sb => sb.Replace("B is enabled", "*******")) - ); - - VerificationEngine engine = new VerificationEngine(_log); - await engine.Execute(options); - } } } diff --git a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs index a81d59b123..3bfbb2d229 100644 --- a/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs +++ b/test/Microsoft.TemplateEngine.Authoring.TemplateVerifier.UnitTests/VerificationEngineTests.cs @@ -33,9 +33,10 @@ public async void CreateVerificationTaskWithCustomScrubbersAndVerifier() { "out.dll", "a1 b2" } }; - IFileSystem fileSystem = A.Fake(); + IPhysicalFileSystemEx fileSystem = A.Fake(); A.CallTo(() => fileSystem.EnumerateFiles(verifyLocation, "*", SearchOption.AllDirectories)).Returns(files.Keys); - A.CallTo(() => fileSystem.ReadAllTextAsync(A._)).ReturnsLazily((string fileName) => Task.FromResult(files[fileName])); + A.CallTo(() => fileSystem.ReadAllTextAsync(A._, A._)) + .ReturnsLazily((string fileName, CancellationToken _) => Task.FromResult(files[fileName])); Dictionary resultContents = new Dictionary(); diff --git a/test/Microsoft.TemplateEngine.TestTemplates/Microsoft.TemplateEngine.TestTemplates.csproj b/test/Microsoft.TemplateEngine.TestTemplates/Microsoft.TemplateEngine.TestTemplates.csproj index 9d07da7269..331ad190fc 100644 --- a/test/Microsoft.TemplateEngine.TestTemplates/Microsoft.TemplateEngine.TestTemplates.csproj +++ b/test/Microsoft.TemplateEngine.TestTemplates/Microsoft.TemplateEngine.TestTemplates.csproj @@ -16,10 +16,10 @@ - + - + diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/TestTemplate/.template.config/template.json b/test/Microsoft.TemplateEngine.TestTemplates/test_templates/TestTemplate/.template.config/template.json similarity index 100% rename from test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/TestTemplate/.template.config/template.json rename to test/Microsoft.TemplateEngine.TestTemplates/test_templates/TestTemplate/.template.config/template.json diff --git a/test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/TestTemplate/Test.cs b/test/Microsoft.TemplateEngine.TestTemplates/test_templates/TestTemplate/Test.cs similarity index 100% rename from test/Microsoft.TemplateEngine.Authoring.CLI.IntegrationTests/TestTemplate/Test.cs rename to test/Microsoft.TemplateEngine.TestTemplates/test_templates/TestTemplate/Test.cs