From cc61999120ce1cc78d6c52c5dd21f02d09da9794 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Wed, 2 Jun 2021 13:34:29 -0700 Subject: [PATCH 01/11] Add retry support --- .../BlazorServerTemplateTest.cs | 3 ++ .../BlazorWasmTemplateTest.cs | 8 +++ src/Testing/src/RetryAttribute.cs | 27 ++++++++++ src/Testing/src/xunit/AspNetTestInvoker.cs | 49 ++++++++++++++++++- src/Testing/test/RetryTest.cs | 32 ++++++++++++ 5 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/Testing/src/RetryAttribute.cs create mode 100644 src/Testing/test/RetryTest.cs diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs index db87158ffbf3..101cfda2103e 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs @@ -26,6 +26,7 @@ public BlazorServerTemplateTest(ProjectFactoryFixture projectFactory) public override string ProjectType { get; } = "blazorserver"; [Theory] + [Retry] [InlineData(BrowserKind.Chromium)] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30761")] public async Task BlazorServerTemplateWorks_NoAuth(BrowserKind browserKind) @@ -82,6 +83,7 @@ await BrowserManager.GetBrowserInstance(browserKind, BrowserContextInfo) : BrowserManager.WithBrowsers(new[] { BrowserKind.Chromium }, true, false); [Theory] + [Retry] [MemberData(nameof(BlazorServerTemplateWorks_IndividualAuthData))] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30882")] [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/30825", Queues = "All.OSX")] @@ -172,6 +174,7 @@ private async Task TestBasicNavigation(Project project, IPage page) } [Theory] + [Retry] [InlineData("IndividualB2C", null)] [InlineData("IndividualB2C", new string[] { "--called-api-url \"https://graph.microsoft.com\"", "--called-api-scopes user.readwrite" })] [InlineData("SingleOrg", null)] diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs index 24ff97cc2779..7200f04822fb 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs @@ -31,6 +31,7 @@ public BlazorWasmTemplateTest(ProjectFactoryFixture projectFactory) public override string ProjectType { get; } = "blazorwasm"; [Theory] + [Retry] [InlineData(BrowserKind.Chromium)] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30882")] public async Task BlazorWasmStandaloneTemplate_Works(BrowserKind browserKind) @@ -68,6 +69,7 @@ private async Task NavigateToPage(IBrowserContext browser, string listeni } [Theory] + [Retry] [InlineData(BrowserKind.Chromium)] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30882")] public async Task BlazorWasmHostedTemplate_Works(BrowserKind browserKind) @@ -117,6 +119,7 @@ private static async Task AssertCompressionFormat(AspNetProcess aspNetProcess, s } [Theory] + [Retry] [InlineData(BrowserKind.Chromium)] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30882")] public async Task BlazorWasmStandalonePwaTemplate_Works(BrowserKind browserKind) @@ -153,6 +156,7 @@ public async Task BlazorWasmStandalonePwaTemplate_Works(BrowserKind browserKind) } [Theory] + [Retry] [InlineData(BrowserKind.Chromium)] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30882")] public async Task BlazorWasmHostedPwaTemplate_Works(BrowserKind browserKind) @@ -224,6 +228,7 @@ private void ValidatePublishedServiceWorker(Project project) } [ConditionalTheory] + [Retry] [InlineData(BrowserKind.Chromium)] // LocalDB doesn't work on non Windows platforms [OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)] @@ -234,6 +239,7 @@ public Task BlazorWasmHostedTemplate_IndividualAuth_Works_WithLocalDB(BrowserKin // This test depends on BlazorWasmTemplate_CreateBuildPublish_IndividualAuthNoLocalDb running first [Theory] + [Retry] [InlineData(BrowserKind.Chromium)] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30882")] [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/30825", Queues = "All.OSX")] @@ -319,6 +325,7 @@ private async Task BlazorWasmHostedTemplate_IndividualAuth_Works(BrowserKind bro } [Theory] + [Retry] [InlineData(BrowserKind.Chromium, Skip = "https://github.com/dotnet/aspnetcore/issues/28596")] public async Task BlazorWasmStandaloneTemplate_IndividualAuth_Works(BrowserKind browserKind) { @@ -418,6 +425,7 @@ public TemplateInstance(string name, params string[] arguments) } [Theory] + [Retry] [MemberData(nameof(TemplateData))] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30851")] public Task BlazorWasmHostedTemplate_AzureActiveDirectoryTemplate_Works(TemplateInstance instance) diff --git a/src/Testing/src/RetryAttribute.cs b/src/Testing/src/RetryAttribute.cs new file mode 100644 index 000000000000..eda5315dc214 --- /dev/null +++ b/src/Testing/src/RetryAttribute.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.ComponentModel; + +namespace Microsoft.AspNetCore.Testing +{ + /// + /// Runs a test multiple times when it fails + /// This can be used on an assembly, class, or method name. Requires using the AspNetCore test framework. + /// + [EditorBrowsable(EditorBrowsableState.Never)] + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = false)] + public class RetryAttribute : Attribute + { + public RetryAttribute(int maxRetries = 3) + { + MaxRetries = maxRetries; + } + + /// + /// The maximum number of times to retry a failed test. Defaults to 3. + /// + public int MaxRetries { get; } + } +} diff --git a/src/Testing/src/xunit/AspNetTestInvoker.cs b/src/Testing/src/xunit/AspNetTestInvoker.cs index ab1a7c9694d3..6337feff2922 100644 --- a/src/Testing/src/xunit/AspNetTestInvoker.cs +++ b/src/Testing/src/xunit/AspNetTestInvoker.cs @@ -45,7 +45,16 @@ await Aggregator.RunAsync(async () => } }); - var time = await base.InvokeTestMethodAsync(testClassInstance); + var retryAttribute = GetRetryAttribute(TestMethod); + var time = 0.0M; + if (retryAttribute == null) + { + time = await base.InvokeTestMethodAsync(testClassInstance); + } + else + { + time = await RetryAsync(retryAttribute, testClassInstance); + } await Aggregator.RunAsync(async () => { @@ -59,6 +68,44 @@ await Aggregator.RunAsync(async () => return time; } + protected async Task RetryAsync(RetryAttribute retryAttribute, object testClassInstance) + { + var attempts = 0; + var timeTaken = 0.0M; + for (attempts = 0; attempts < retryAttribute.MaxRetries; attempts++) + { + timeTaken = await base.InvokeTestMethodAsync(testClassInstance); + if (!Aggregator.HasExceptions) + { + return timeTaken; + } + else if (attempts < retryAttribute.MaxRetries - 1) + { + Aggregator.Clear(); + } + } + + return timeTaken; + } + + + private RetryAttribute GetRetryAttribute(MethodInfo methodInfo) + { + var attributeCandidate = methodInfo.GetCustomAttribute(); + if (attributeCandidate != null) + { + return attributeCandidate; + } + + attributeCandidate = methodInfo.DeclaringType.GetCustomAttribute(); + if (attributeCandidate != null) + { + return attributeCandidate; + } + + return methodInfo.DeclaringType.Assembly.GetCustomAttribute(); + } + private static IEnumerable GetLifecycleHooks(object testClassInstance, Type testClass, MethodInfo testMethod) { foreach (var attribute in testMethod.GetCustomAttributes(inherit: true).OfType()) diff --git a/src/Testing/test/RetryTest.cs b/src/Testing/test/RetryTest.cs new file mode 100644 index 000000000000..2d6f65dd2d7b --- /dev/null +++ b/src/Testing/test/RetryTest.cs @@ -0,0 +1,32 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Xunit; + +namespace Microsoft.AspNetCore.Testing +{ + [Retry] + public class RetryTest + { + private static int _retryFailsUntil3 = 0; + + [Fact] + public void RetryFailsUntil3() + { + _retryFailsUntil3++; + if (_retryFailsUntil3 != 2) throw new Exception("NOOOOOOOO"); + } + + private static int _canOverrideRetries = 0; + + [Fact] + [Retry(5)] + public void CanOverrideRetries() + { + _canOverrideRetries++; + if (_canOverrideRetries != 5) throw new Exception("NOOOOOOOO"); + } + + } +} From 61f740f7e6927537e94889e4ba9dd46818b079b3 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Wed, 2 Jun 2021 22:07:36 -0700 Subject: [PATCH 02/11] Force create since retry will overwrite --- src/ProjectTemplates/Shared/TemplatePackageInstaller.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs b/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs index 9a6c698ffb33..04a925408b53 100644 --- a/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs +++ b/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs @@ -80,7 +80,7 @@ public static async Task RunDotNetNew(ITestOutputHelper output, strin DotNetMuxer.MuxerPathOrDefault(), //--debug:disable-sdk-templates means, don't include C:\Program Files\dotnet\templates, aka. what comes with SDK, so we don't need to uninstall //--debug:custom-hive means, don't install templates on CI/developer machine, instead create new temporary instance - $"new {arguments} --debug:disable-sdk-templates --debug:custom-hive \"{CustomHivePath}\""); + $"new {arguments} --force --debug:disable-sdk-templates --debug:custom-hive \"{CustomHivePath}\""); await proc.Exited; From 451bb7e9d3d0d7cc6554220ca8e5a7ae3ee227a2 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Wed, 2 Jun 2021 22:13:42 -0700 Subject: [PATCH 03/11] Delete files since retry will recreate --- src/ProjectTemplates/Shared/Project.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ProjectTemplates/Shared/Project.cs b/src/ProjectTemplates/Shared/Project.cs index 84417ced0375..baa2b2519e81 100644 --- a/src/ProjectTemplates/Shared/Project.cs +++ b/src/ProjectTemplates/Shared/Project.cs @@ -102,6 +102,18 @@ internal async Task RunDotNetNewAsync( try { Output.WriteLine("Acquired DotNetNewLock"); + + Output.WriteLine($"Deleting contents of {TemplateOutputDir}"); + var di = new DirectoryInfo(TemplateOutputDir); + foreach (FileInfo file in di.EnumerateFiles()) + { + file.Delete(); + } + foreach (DirectoryInfo dir in di.EnumerateDirectories()) + { + dir.Delete(true); + } + // Temporary while investigating why this process occasionally never runs or exits on Debian 9 environmentVariables.Add("COREHOST_TRACE", "1"); using var execution = ProcessEx.Run(Output, AppContext.BaseDirectory, DotNetMuxer.MuxerPathOrDefault(), argString, environmentVariables); From 0dadff4736bf8d4f16967c61c33838376dab6ffd Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Thu, 3 Jun 2021 09:24:02 -0700 Subject: [PATCH 04/11] Only clean if dir exists --- src/ProjectTemplates/Shared/Project.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/ProjectTemplates/Shared/Project.cs b/src/ProjectTemplates/Shared/Project.cs index baa2b2519e81..362662b2da48 100644 --- a/src/ProjectTemplates/Shared/Project.cs +++ b/src/ProjectTemplates/Shared/Project.cs @@ -103,16 +103,19 @@ internal async Task RunDotNetNewAsync( { Output.WriteLine("Acquired DotNetNewLock"); - Output.WriteLine($"Deleting contents of {TemplateOutputDir}"); - var di = new DirectoryInfo(TemplateOutputDir); - foreach (FileInfo file in di.EnumerateFiles()) + if (Directory.Exists(TemplateOutputDir)) { - file.Delete(); + Output.WriteLine($"Template directory already exists, deleting contents of {TemplateOutputDir}"); + var di = new DirectoryInfo(TemplateOutputDir); + foreach (FileInfo file in di.EnumerateFiles()) + { + file.Delete(); + } + foreach (DirectoryInfo dir in di.EnumerateDirectories()) + { + dir.Delete(true); + } } - foreach (DirectoryInfo dir in di.EnumerateDirectories()) - { - dir.Delete(true); - } // Temporary while investigating why this process occasionally never runs or exits on Debian 9 environmentVariables.Add("COREHOST_TRACE", "1"); From a962382ec530f1e613664a3cd9f8210f24668b19 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Thu, 3 Jun 2021 09:24:32 -0700 Subject: [PATCH 05/11] Update RetryTest.cs --- src/Testing/test/RetryTest.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Testing/test/RetryTest.cs b/src/Testing/test/RetryTest.cs index 2d6f65dd2d7b..3f62c87ca7af 100644 --- a/src/Testing/test/RetryTest.cs +++ b/src/Testing/test/RetryTest.cs @@ -27,6 +27,5 @@ public void CanOverrideRetries() _canOverrideRetries++; if (_canOverrideRetries != 5) throw new Exception("NOOOOOOOO"); } - } } From a96c459017993c1b73b2c64cc58540e0910905dc Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Thu, 3 Jun 2021 09:24:52 -0700 Subject: [PATCH 06/11] Update AspNetTestInvoker.cs --- src/Testing/src/xunit/AspNetTestInvoker.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Testing/src/xunit/AspNetTestInvoker.cs b/src/Testing/src/xunit/AspNetTestInvoker.cs index 6337feff2922..0d34db32f035 100644 --- a/src/Testing/src/xunit/AspNetTestInvoker.cs +++ b/src/Testing/src/xunit/AspNetTestInvoker.cs @@ -88,7 +88,6 @@ protected async Task RetryAsync(RetryAttribute retryAttribute, object t return timeTaken; } - private RetryAttribute GetRetryAttribute(MethodInfo methodInfo) { var attributeCandidate = methodInfo.GetCustomAttribute(); From 0aff7efdcf7dbb9e3afcd1c2e65993e873e1fa89 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Thu, 3 Jun 2021 17:49:12 -0700 Subject: [PATCH 07/11] PR feedback --- .../BlazorTemplates.Tests/BlazorServerTemplateTest.cs | 4 +--- .../BlazorTemplates.Tests/BlazorWasmTemplateTest.cs | 9 +-------- src/Testing/src/xunit/AspNetTestInvoker.cs | 2 ++ 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs index 101cfda2103e..88548db7715b 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs @@ -16,6 +16,7 @@ namespace Templates.Test { + [Retry] public class BlazorServerTemplateTest : BlazorTemplateTest { public BlazorServerTemplateTest(ProjectFactoryFixture projectFactory) @@ -26,7 +27,6 @@ public BlazorServerTemplateTest(ProjectFactoryFixture projectFactory) public override string ProjectType { get; } = "blazorserver"; [Theory] - [Retry] [InlineData(BrowserKind.Chromium)] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30761")] public async Task BlazorServerTemplateWorks_NoAuth(BrowserKind browserKind) @@ -83,7 +83,6 @@ await BrowserManager.GetBrowserInstance(browserKind, BrowserContextInfo) : BrowserManager.WithBrowsers(new[] { BrowserKind.Chromium }, true, false); [Theory] - [Retry] [MemberData(nameof(BlazorServerTemplateWorks_IndividualAuthData))] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30882")] [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/30825", Queues = "All.OSX")] @@ -174,7 +173,6 @@ private async Task TestBasicNavigation(Project project, IPage page) } [Theory] - [Retry] [InlineData("IndividualB2C", null)] [InlineData("IndividualB2C", new string[] { "--called-api-url \"https://graph.microsoft.com\"", "--called-api-scopes user.readwrite" })] [InlineData("SingleOrg", null)] diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs index 7200f04822fb..76b1605b85bf 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorWasmTemplateTest.cs @@ -23,6 +23,7 @@ namespace Templates.Test { + [Retry] public class BlazorWasmTemplateTest : BlazorTemplateTest { public BlazorWasmTemplateTest(ProjectFactoryFixture projectFactory) @@ -31,7 +32,6 @@ public BlazorWasmTemplateTest(ProjectFactoryFixture projectFactory) public override string ProjectType { get; } = "blazorwasm"; [Theory] - [Retry] [InlineData(BrowserKind.Chromium)] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30882")] public async Task BlazorWasmStandaloneTemplate_Works(BrowserKind browserKind) @@ -69,7 +69,6 @@ private async Task NavigateToPage(IBrowserContext browser, string listeni } [Theory] - [Retry] [InlineData(BrowserKind.Chromium)] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30882")] public async Task BlazorWasmHostedTemplate_Works(BrowserKind browserKind) @@ -119,7 +118,6 @@ private static async Task AssertCompressionFormat(AspNetProcess aspNetProcess, s } [Theory] - [Retry] [InlineData(BrowserKind.Chromium)] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30882")] public async Task BlazorWasmStandalonePwaTemplate_Works(BrowserKind browserKind) @@ -156,7 +154,6 @@ public async Task BlazorWasmStandalonePwaTemplate_Works(BrowserKind browserKind) } [Theory] - [Retry] [InlineData(BrowserKind.Chromium)] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30882")] public async Task BlazorWasmHostedPwaTemplate_Works(BrowserKind browserKind) @@ -228,7 +225,6 @@ private void ValidatePublishedServiceWorker(Project project) } [ConditionalTheory] - [Retry] [InlineData(BrowserKind.Chromium)] // LocalDB doesn't work on non Windows platforms [OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)] @@ -239,7 +235,6 @@ public Task BlazorWasmHostedTemplate_IndividualAuth_Works_WithLocalDB(BrowserKin // This test depends on BlazorWasmTemplate_CreateBuildPublish_IndividualAuthNoLocalDb running first [Theory] - [Retry] [InlineData(BrowserKind.Chromium)] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30882")] [SkipOnHelix("https://github.com/dotnet/aspnetcore/issues/30825", Queues = "All.OSX")] @@ -325,7 +320,6 @@ private async Task BlazorWasmHostedTemplate_IndividualAuth_Works(BrowserKind bro } [Theory] - [Retry] [InlineData(BrowserKind.Chromium, Skip = "https://github.com/dotnet/aspnetcore/issues/28596")] public async Task BlazorWasmStandaloneTemplate_IndividualAuth_Works(BrowserKind browserKind) { @@ -425,7 +419,6 @@ public TemplateInstance(string name, params string[] arguments) } [Theory] - [Retry] [MemberData(nameof(TemplateData))] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/30851")] public Task BlazorWasmHostedTemplate_AzureActiveDirectoryTemplate_Works(TemplateInstance instance) diff --git a/src/Testing/src/xunit/AspNetTestInvoker.cs b/src/Testing/src/xunit/AspNetTestInvoker.cs index 0d34db32f035..68c42a698626 100644 --- a/src/Testing/src/xunit/AspNetTestInvoker.cs +++ b/src/Testing/src/xunit/AspNetTestInvoker.cs @@ -81,6 +81,8 @@ protected async Task RetryAsync(RetryAttribute retryAttribute, object t } else if (attempts < retryAttribute.MaxRetries - 1) { + _testOutputHelper.WriteLine($"Retrying test, attempt {attempts} of {retryAttribute.MaxRetries} failed."); + await Task.Delay(5000); Aggregator.Clear(); } } From 6cc7b9b9275dc0987f1c5eb385be5778f09d3717 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Thu, 3 Jun 2021 17:49:56 -0700 Subject: [PATCH 08/11] Revert change --- src/ProjectTemplates/Shared/TemplatePackageInstaller.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs b/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs index 04a925408b53..9a6c698ffb33 100644 --- a/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs +++ b/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs @@ -80,7 +80,7 @@ public static async Task RunDotNetNew(ITestOutputHelper output, strin DotNetMuxer.MuxerPathOrDefault(), //--debug:disable-sdk-templates means, don't include C:\Program Files\dotnet\templates, aka. what comes with SDK, so we don't need to uninstall //--debug:custom-hive means, don't install templates on CI/developer machine, instead create new temporary instance - $"new {arguments} --force --debug:disable-sdk-templates --debug:custom-hive \"{CustomHivePath}\""); + $"new {arguments} --debug:disable-sdk-templates --debug:custom-hive \"{CustomHivePath}\""); await proc.Exited; From 57a1750a020b81e5a309c596bff54b73ab9b47c4 Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Mon, 7 Jun 2021 16:26:35 -0700 Subject: [PATCH 09/11] Update src/Testing/src/RetryAttribute.cs Co-authored-by: Pranav K --- src/Testing/src/RetryAttribute.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Testing/src/RetryAttribute.cs b/src/Testing/src/RetryAttribute.cs index eda5315dc214..2fb3ce51b337 100644 --- a/src/Testing/src/RetryAttribute.cs +++ b/src/Testing/src/RetryAttribute.cs @@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Testing /// [EditorBrowsable(EditorBrowsableState.Never)] [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = false)] - public class RetryAttribute : Attribute + public sealed class RetryAttribute : Attribute { public RetryAttribute(int maxRetries = 3) { From e45c0e5f7f82ed22cd77129739c0751bc938aa1e Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Mon, 7 Jun 2021 16:28:19 -0700 Subject: [PATCH 10/11] Use recursive delete --- src/ProjectTemplates/Shared/Project.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/ProjectTemplates/Shared/Project.cs b/src/ProjectTemplates/Shared/Project.cs index 362662b2da48..86fc0f64b363 100644 --- a/src/ProjectTemplates/Shared/Project.cs +++ b/src/ProjectTemplates/Shared/Project.cs @@ -106,15 +106,7 @@ internal async Task RunDotNetNewAsync( if (Directory.Exists(TemplateOutputDir)) { Output.WriteLine($"Template directory already exists, deleting contents of {TemplateOutputDir}"); - var di = new DirectoryInfo(TemplateOutputDir); - foreach (FileInfo file in di.EnumerateFiles()) - { - file.Delete(); - } - foreach (DirectoryInfo dir in di.EnumerateDirectories()) - { - dir.Delete(true); - } + Directory.Delete(TemplateOutputDir, recursive: true) } // Temporary while investigating why this process occasionally never runs or exits on Debian 9 From ab9701759411fa769490d557c66089924261fdbd Mon Sep 17 00:00:00 2001 From: Hao Kung Date: Mon, 7 Jun 2021 16:53:15 -0700 Subject: [PATCH 11/11] Update Project.cs --- src/ProjectTemplates/Shared/Project.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProjectTemplates/Shared/Project.cs b/src/ProjectTemplates/Shared/Project.cs index 86fc0f64b363..dfb6129f6aaf 100644 --- a/src/ProjectTemplates/Shared/Project.cs +++ b/src/ProjectTemplates/Shared/Project.cs @@ -106,7 +106,7 @@ internal async Task RunDotNetNewAsync( if (Directory.Exists(TemplateOutputDir)) { Output.WriteLine($"Template directory already exists, deleting contents of {TemplateOutputDir}"); - Directory.Delete(TemplateOutputDir, recursive: true) + Directory.Delete(TemplateOutputDir, recursive: true); } // Temporary while investigating why this process occasionally never runs or exits on Debian 9