From 5647330be247043b7d74e0fea0e22a10cf60a0c7 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Tue, 5 May 2020 01:57:07 -0700 Subject: [PATCH 1/6] Move template specific helpers out of shared and into templates --- .../BlazorTemplates.Tests/BlazorTemplates.Tests.csproj | 3 ++- .../E2ETesting => ProjectTemplates/Shared}/AspNetProcess.cs | 0 .../E2ETesting => ProjectTemplates/Shared}/ErrorMessages.cs | 0 src/{Shared/E2ETesting => ProjectTemplates/Shared}/PageUrls.cs | 0 src/{Shared/E2ETesting => ProjectTemplates/Shared}/Project.cs | 0 .../Shared}/ProjectFactoryFixture.cs | 0 .../Shared}/TemplatePackageInstaller.cs | 0 src/ProjectTemplates/test/ProjectTemplates.Tests.csproj | 3 ++- 8 files changed, 4 insertions(+), 2 deletions(-) rename src/{Shared/E2ETesting => ProjectTemplates/Shared}/AspNetProcess.cs (100%) rename src/{Shared/E2ETesting => ProjectTemplates/Shared}/ErrorMessages.cs (100%) rename src/{Shared/E2ETesting => ProjectTemplates/Shared}/PageUrls.cs (100%) rename src/{Shared/E2ETesting => ProjectTemplates/Shared}/Project.cs (100%) rename src/{Shared/E2ETesting => ProjectTemplates/Shared}/ProjectFactoryFixture.cs (100%) rename src/{Shared/E2ETesting => ProjectTemplates/Shared}/TemplatePackageInstaller.cs (100%) diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj index 3118aac607e7..a3858977bb86 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorTemplates.Tests.csproj @@ -1,4 +1,4 @@ - + @@ -28,6 +28,7 @@ + diff --git a/src/Shared/E2ETesting/AspNetProcess.cs b/src/ProjectTemplates/Shared/AspNetProcess.cs similarity index 100% rename from src/Shared/E2ETesting/AspNetProcess.cs rename to src/ProjectTemplates/Shared/AspNetProcess.cs diff --git a/src/Shared/E2ETesting/ErrorMessages.cs b/src/ProjectTemplates/Shared/ErrorMessages.cs similarity index 100% rename from src/Shared/E2ETesting/ErrorMessages.cs rename to src/ProjectTemplates/Shared/ErrorMessages.cs diff --git a/src/Shared/E2ETesting/PageUrls.cs b/src/ProjectTemplates/Shared/PageUrls.cs similarity index 100% rename from src/Shared/E2ETesting/PageUrls.cs rename to src/ProjectTemplates/Shared/PageUrls.cs diff --git a/src/Shared/E2ETesting/Project.cs b/src/ProjectTemplates/Shared/Project.cs similarity index 100% rename from src/Shared/E2ETesting/Project.cs rename to src/ProjectTemplates/Shared/Project.cs diff --git a/src/Shared/E2ETesting/ProjectFactoryFixture.cs b/src/ProjectTemplates/Shared/ProjectFactoryFixture.cs similarity index 100% rename from src/Shared/E2ETesting/ProjectFactoryFixture.cs rename to src/ProjectTemplates/Shared/ProjectFactoryFixture.cs diff --git a/src/Shared/E2ETesting/TemplatePackageInstaller.cs b/src/ProjectTemplates/Shared/TemplatePackageInstaller.cs similarity index 100% rename from src/Shared/E2ETesting/TemplatePackageInstaller.cs rename to src/ProjectTemplates/Shared/TemplatePackageInstaller.cs diff --git a/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj b/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj index e54b80fa4cd5..9c49e2f2e362 100644 --- a/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj +++ b/src/ProjectTemplates/test/ProjectTemplates.Tests.csproj @@ -1,4 +1,4 @@ - + @@ -28,6 +28,7 @@ + From 73a535b539c6aa13cc6fab4e9eb067406fa3e6a0 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Tue, 5 May 2020 02:41:38 -0700 Subject: [PATCH 2/6] More debug info, fix casing issues --- .../BlazorServerTemplateTest.cs | 2 +- src/ProjectTemplates/Shared/AspNetProcess.cs | 41 +++++++++++-------- src/ProjectTemplates/test/yarn.lock | 8 ++-- 3 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs index 840af1cd8d9a..feb0a01c44f7 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs @@ -24,7 +24,7 @@ public BlazorServerTemplateTest(ProjectFactoryFixture projectFactory, BrowserFix public Project Project { get; private set; } - [ConditionalFact(Skip = "This test ran for over an hour")] + [Fact] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/20172")] public async Task BlazorServerTemplateWorks_NoAuth() { diff --git a/src/ProjectTemplates/Shared/AspNetProcess.cs b/src/ProjectTemplates/Shared/AspNetProcess.cs index 9c79788c522c..3c7e2b3be6e8 100644 --- a/src/ProjectTemplates/Shared/AspNetProcess.cs +++ b/src/ProjectTemplates/Shared/AspNetProcess.cs @@ -33,6 +33,7 @@ public class AspNetProcess : IDisposable private string _certificatePath; private string _certificatePassword = Guid.NewGuid().ToString(); + private string _certificateThumbprint; internal readonly Uri ListeningUri; internal ProcessEx Process { get; } @@ -52,7 +53,7 @@ public AspNetProcess( AllowAutoRedirect = true, UseCookies = true, CookieContainer = new CookieContainer(), - ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator, + ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) => certificate?.Thumbprint == _certificateThumbprint, }) { Timeout = TimeSpan.FromMinutes(2) @@ -70,8 +71,8 @@ public AspNetProcess( var finalEnvironmentVariables = new Dictionary(environmentVariables) { - ["ASPNETCORE_KESTREL__CERTIFICATES__DEFAULT__PATH"] = _certificatePath, - ["ASPNETCORE_KESTREL__CERTIFICATES__DEFAULT__PASSWORD"] = _certificatePassword + ["ASPNETCORE_Kestrel__Certificates__Default__Path"] = _certificatePath, + ["ASPNETCORE_Kestrel__Certificates__Default__Password"] = _certificatePassword }; Process = ProcessEx.Run(output, workingDirectory, DotNetMuxer.MuxerPathOrDefault(), arguments, envVars: finalEnvironmentVariables); @@ -81,8 +82,8 @@ public AspNetProcess( if (hasListeningUri) { logger?.LogInformation("AspNetProcess - Getting listening uri"); - ListeningUri = GetListeningUri(output) ?? throw new InvalidOperationException("Couldn't find the listening URL."); - logger?.LogInformation($"AspNetProcess - Got {ListeningUri.ToString()}"); + ListeningUri = ResolveListeningUrl(output); + logger?.LogInformation($"AspNetProcess - Got {ListeningUri}"); } } @@ -91,6 +92,7 @@ internal void EnsureDevelopmentCertificates() var now = DateTimeOffset.Now; var manager = CertificateManager.Instance; var certificate = manager.CreateAspNetCoreHttpsDevelopmentCertificate(now, now.AddYears(1)); + _certificateThumbprint = certificate.Thumbprint; manager.ExportCertificate(certificate, path: _certificatePath, includePrivateKey: true, _certificatePassword); } @@ -203,7 +205,7 @@ private async Task RequestWithRetries(Func> requester, throw new InvalidOperationException("Max retries reached."); } - private Uri GetListeningUri(ITestOutputHelper output) + private Uri ResolveListeningUrl(ITestOutputHelper output) { // Wait until the app is accepting HTTP requests output.WriteLine("Waiting until ASP.NET application is accepting connections..."); @@ -232,21 +234,27 @@ private Uri GetListeningUri(ITestOutputHelper output) private string GetListeningMessage() { + var buffer = new List(); try { - return Process - // This will timeout at most after 5 minutes. - .OutputLinesAsEnumerable - .Where(line => line != null) - // This used to do StartsWith, but this is less strict and can prevent issues (very rare) where - // console logging interleaves with other console output in a bad way. For example: - // dbugNow listening on: http://127.0.0.1:12857 - .FirstOrDefault(line => line.Trim().Contains(ListeningMessagePrefix, StringComparison.Ordinal)); + foreach (var line in Process.OutputLinesAsEnumerable) + { + if (line != null) + { + buffer.Add(line); + if (line.Trim().Contains(ListeningMessagePrefix, StringComparison.Ordinal)) + { + return line; + } + } + } } catch (OperationCanceledException) { - return null; } + + throw new InvalidOperationException(@$"Couldn't find listening url: +{string.Join(Environment.NewLine, buffer)}"); } private bool IsSuccessStatusCode(HttpResponseMessage response) @@ -267,7 +275,8 @@ internal Task SendRequest(string path) public async Task AssertStatusCode(string requestUrl, HttpStatusCode statusCode, string acceptContentType = null) { - var response = await RequestWithRetries(client => { + var response = await RequestWithRetries(client => + { var request = new HttpRequestMessage( HttpMethod.Get, new Uri(ListeningUri, requestUrl)); diff --git a/src/ProjectTemplates/test/yarn.lock b/src/ProjectTemplates/test/yarn.lock index de1c0d6edbee..e0d2d327e77f 100644 --- a/src/ProjectTemplates/test/yarn.lock +++ b/src/ProjectTemplates/test/yarn.lock @@ -427,10 +427,10 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -selenium-standalone@^6.15.4: - version "6.15.6" - resolved "https://registry.yarnpkg.com/selenium-standalone/-/selenium-standalone-6.15.6.tgz#55cc610e405dd74e312c77f3ac7336795ca2cd0c" - integrity sha512-iQJbjJyGY4+n9voj+QIxkjEKmk9csPL91pxjqYyX5/1jjJDw7ce0ZuTnLeNaFmFdjY/nAwcoMRvqpDPmmmyr5A== +selenium-standalone@^6.17.0: + version "6.17.0" + resolved "https://registry.yarnpkg.com/selenium-standalone/-/selenium-standalone-6.17.0.tgz#0f24b691836205ee9bc3d7a6f207ebcb28170cd9" + integrity sha512-5PSnDHwMiq+OCiAGlhwQ8BM9xuwFfvBOZ7Tfbw+ifkTnOy0PWbZmI1B9gPGuyGHpbQ/3J3CzIK7BYwrQ7EjtWQ== dependencies: async "^2.6.2" commander "^2.19.0" From b1b6fedee945260e4f16360a7761b48b54160335 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Tue, 5 May 2020 05:49:41 -0700 Subject: [PATCH 3/6] Keep test skipped --- .../BlazorTemplates.Tests/BlazorServerTemplateTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs index feb0a01c44f7..840af1cd8d9a 100644 --- a/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs +++ b/src/ProjectTemplates/BlazorTemplates.Tests/BlazorServerTemplateTest.cs @@ -24,7 +24,7 @@ public BlazorServerTemplateTest(ProjectFactoryFixture projectFactory, BrowserFix public Project Project { get; private set; } - [Fact] + [ConditionalFact(Skip = "This test ran for over an hour")] [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/20172")] public async Task BlazorServerTemplateWorks_NoAuth() { From 6558f4e2bcaafb21578d7f236f66459ddad301ce Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Tue, 5 May 2020 09:25:40 -0700 Subject: [PATCH 4/6] Undo lock changes --- src/ProjectTemplates/test/yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ProjectTemplates/test/yarn.lock b/src/ProjectTemplates/test/yarn.lock index e0d2d327e77f..de1c0d6edbee 100644 --- a/src/ProjectTemplates/test/yarn.lock +++ b/src/ProjectTemplates/test/yarn.lock @@ -427,10 +427,10 @@ safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -selenium-standalone@^6.17.0: - version "6.17.0" - resolved "https://registry.yarnpkg.com/selenium-standalone/-/selenium-standalone-6.17.0.tgz#0f24b691836205ee9bc3d7a6f207ebcb28170cd9" - integrity sha512-5PSnDHwMiq+OCiAGlhwQ8BM9xuwFfvBOZ7Tfbw+ifkTnOy0PWbZmI1B9gPGuyGHpbQ/3J3CzIK7BYwrQ7EjtWQ== +selenium-standalone@^6.15.4: + version "6.15.6" + resolved "https://registry.yarnpkg.com/selenium-standalone/-/selenium-standalone-6.15.6.tgz#55cc610e405dd74e312c77f3ac7336795ca2cd0c" + integrity sha512-iQJbjJyGY4+n9voj+QIxkjEKmk9csPL91pxjqYyX5/1jjJDw7ce0ZuTnLeNaFmFdjY/nAwcoMRvqpDPmmmyr5A== dependencies: async "^2.6.2" commander "^2.19.0" From 5170f8e74c710493aa26550341c76e4790f7188b Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Tue, 5 May 2020 12:02:56 -0700 Subject: [PATCH 5/6] Standarize retry logic --- src/ProjectTemplates/Shared/AspNetProcess.cs | 21 ++++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/ProjectTemplates/Shared/AspNetProcess.cs b/src/ProjectTemplates/Shared/AspNetProcess.cs index 3c7e2b3be6e8..82c43ddad8de 100644 --- a/src/ProjectTemplates/Shared/AspNetProcess.cs +++ b/src/ProjectTemplates/Shared/AspNetProcess.cs @@ -136,13 +136,13 @@ public async Task AssertPagesOk(IEnumerable pages) public async Task ContainsLinks(Page page) { - var response = await RequestWithRetries(client => + var response = await RetryHelper.RetryRequest(async () => { var request = new HttpRequestMessage( HttpMethod.Get, new Uri(ListeningUri, page.Url)); - return client.SendAsync(request); - }, _httpClient); + return await _httpClient.SendAsync(request); + }, logger: NullLogger.Instance); Assert.Equal(HttpStatusCode.OK, response.StatusCode); var parser = new HtmlParser(); @@ -175,7 +175,7 @@ public async Task ContainsLinks(Page page) Assert.True(string.Equals(anchor.Href, expectedLink), $"Expected next link to be {expectedLink} but it was {anchor.Href}."); var result = await RetryHelper.RetryRequest(async () => { - return await RequestWithRetries(client => client.GetAsync(anchor.Href), _httpClient); + return await _httpClient.GetAsync(anchor.Href); }, logger: NullLogger.Instance); Assert.True(IsSuccessStatusCode(result), $"{anchor.Href} is a broken link!"); @@ -268,14 +268,12 @@ public Task AssertOk(string requestUrl) public Task AssertNotFound(string requestUrl) => AssertStatusCode(requestUrl, HttpStatusCode.NotFound); - internal Task SendRequest(string path) - { - return RequestWithRetries(client => client.GetAsync(new Uri(ListeningUri, path)), _httpClient); - } + internal Task SendRequest(string path) => + RetryHelper.RetryRequest(() => _httpClient.GetAsync(new Uri(ListeningUri, path)), logger: NullLogger.Instance); public async Task AssertStatusCode(string requestUrl, HttpStatusCode statusCode, string acceptContentType = null) { - var response = await RequestWithRetries(client => + var response = await RetryHelper.RetryRequest(() => { var request = new HttpRequestMessage( HttpMethod.Get, @@ -286,8 +284,9 @@ public async Task AssertStatusCode(string requestUrl, HttpStatusCode statusCode, request.Headers.Add("Accept", acceptContentType); } - return client.SendAsync(request); - }, _httpClient); + return _httpClient.SendAsync(request); + }, logger: NullLogger.Instance); + Assert.True(statusCode == response.StatusCode, $"Expected {requestUrl} to have status '{statusCode}' but it was '{response.StatusCode}'."); } From a8a9593c3d685b7c0b90f1c834e79ae5d95bdf8e Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Tue, 5 May 2020 14:30:58 -0700 Subject: [PATCH 6/6] Tweak certificate validation code --- src/ProjectTemplates/Shared/AspNetProcess.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ProjectTemplates/Shared/AspNetProcess.cs b/src/ProjectTemplates/Shared/AspNetProcess.cs index 82c43ddad8de..0c392957b4a9 100644 --- a/src/ProjectTemplates/Shared/AspNetProcess.cs +++ b/src/ProjectTemplates/Shared/AspNetProcess.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Security; using System.Threading.Tasks; using AngleSharp.Dom.Html; using AngleSharp.Parser.Html; @@ -47,22 +48,21 @@ public AspNetProcess( bool hasListeningUri = true, ILogger logger = null) { + _certificatePath = Path.Combine(workingDirectory, $"{Guid.NewGuid()}.pfx"); + EnsureDevelopmentCertificates(); + _output = output; _httpClient = new HttpClient(new HttpClientHandler() { AllowAutoRedirect = true, UseCookies = true, CookieContainer = new CookieContainer(), - ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) => certificate?.Thumbprint == _certificateThumbprint, + ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) => (certificate.Subject != "CN=localhost" && errors == SslPolicyErrors.None) || certificate?.Thumbprint == _certificateThumbprint, }) { Timeout = TimeSpan.FromMinutes(2) }; - _certificatePath = Path.Combine(workingDirectory, $"{Guid.NewGuid()}.pfx"); - - EnsureDevelopmentCertificates(); - output.WriteLine("Running ASP.NET application..."); var arguments = published ? $"exec {dllPath}" : "run";