diff --git a/KestrelHttpServer.sln b/KestrelHttpServer.sln index baa0ee92f4..95188d12fc 100644 --- a/KestrelHttpServer.sln +++ b/KestrelHttpServer.sln @@ -114,8 +114,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Transport.Sockets.B EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Transport.Libuv.BindTests", "test\Kestrel.Transport.Libuv.BindTests\Kestrel.Transport.Libuv.BindTests.csproj", "{FB9C6B61-0A7B-4FFA-B772-A754316B262E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.H2Spec.FunctionalTests", "test\Kestrel.H2Spec.FunctionalTests\Kestrel.H2Spec.FunctionalTests.csproj", "{C4123E55-5760-4557-B89B-39E1258FD7F9}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionItems", "{B19F67B8-7635-42C3-B5BF-00D1CC47FA64}" ProjectSection(SolutionItems) = preProject .gitattributes = .gitattributes @@ -138,6 +136,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionIt version.props = version.props EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Kestrel.Interop.FunctionalTests", "test\Kestrel.Interop.FunctionalTests\Kestrel.Interop.FunctionalTests.csproj", "{DF5394AB-679B-4F2F-8E9C-5327AD053E91}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -424,18 +424,18 @@ Global {FB9C6B61-0A7B-4FFA-B772-A754316B262E}.Release|x64.Build.0 = Release|Any CPU {FB9C6B61-0A7B-4FFA-B772-A754316B262E}.Release|x86.ActiveCfg = Release|Any CPU {FB9C6B61-0A7B-4FFA-B772-A754316B262E}.Release|x86.Build.0 = Release|Any CPU - {C4123E55-5760-4557-B89B-39E1258FD7F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C4123E55-5760-4557-B89B-39E1258FD7F9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C4123E55-5760-4557-B89B-39E1258FD7F9}.Debug|x64.ActiveCfg = Debug|Any CPU - {C4123E55-5760-4557-B89B-39E1258FD7F9}.Debug|x64.Build.0 = Debug|Any CPU - {C4123E55-5760-4557-B89B-39E1258FD7F9}.Debug|x86.ActiveCfg = Debug|Any CPU - {C4123E55-5760-4557-B89B-39E1258FD7F9}.Debug|x86.Build.0 = Debug|Any CPU - {C4123E55-5760-4557-B89B-39E1258FD7F9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C4123E55-5760-4557-B89B-39E1258FD7F9}.Release|Any CPU.Build.0 = Release|Any CPU - {C4123E55-5760-4557-B89B-39E1258FD7F9}.Release|x64.ActiveCfg = Release|Any CPU - {C4123E55-5760-4557-B89B-39E1258FD7F9}.Release|x64.Build.0 = Release|Any CPU - {C4123E55-5760-4557-B89B-39E1258FD7F9}.Release|x86.ActiveCfg = Release|Any CPU - {C4123E55-5760-4557-B89B-39E1258FD7F9}.Release|x86.Build.0 = Release|Any CPU + {DF5394AB-679B-4F2F-8E9C-5327AD053E91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DF5394AB-679B-4F2F-8E9C-5327AD053E91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DF5394AB-679B-4F2F-8E9C-5327AD053E91}.Debug|x64.ActiveCfg = Debug|Any CPU + {DF5394AB-679B-4F2F-8E9C-5327AD053E91}.Debug|x64.Build.0 = Debug|Any CPU + {DF5394AB-679B-4F2F-8E9C-5327AD053E91}.Debug|x86.ActiveCfg = Debug|Any CPU + {DF5394AB-679B-4F2F-8E9C-5327AD053E91}.Debug|x86.Build.0 = Debug|Any CPU + {DF5394AB-679B-4F2F-8E9C-5327AD053E91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DF5394AB-679B-4F2F-8E9C-5327AD053E91}.Release|Any CPU.Build.0 = Release|Any CPU + {DF5394AB-679B-4F2F-8E9C-5327AD053E91}.Release|x64.ActiveCfg = Release|Any CPU + {DF5394AB-679B-4F2F-8E9C-5327AD053E91}.Release|x64.Build.0 = Release|Any CPU + {DF5394AB-679B-4F2F-8E9C-5327AD053E91}.Release|x86.ActiveCfg = Release|Any CPU + {DF5394AB-679B-4F2F-8E9C-5327AD053E91}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -466,7 +466,7 @@ Global {B5422347-E919-431D-9EF2-C352FFE4D6C1} = {D3273454-EA07-41D2-BF0B-FCC3675C2483} {9254C3EB-196B-402F-A059-34FEA6140500} = {D3273454-EA07-41D2-BF0B-FCC3675C2483} {FB9C6B61-0A7B-4FFA-B772-A754316B262E} = {D3273454-EA07-41D2-BF0B-FCC3675C2483} - {C4123E55-5760-4557-B89B-39E1258FD7F9} = {D3273454-EA07-41D2-BF0B-FCC3675C2483} + {DF5394AB-679B-4F2F-8E9C-5327AD053E91} = {D3273454-EA07-41D2-BF0B-FCC3675C2483} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2D10D020-6770-47CA-BB8D-2C23FE3AE071} diff --git a/build/dependencies.props b/build/dependencies.props index c89f6ff48e..32ab73e25b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -36,6 +36,8 @@ 4.10.0 2.0.3 11.0.2 + 2.43.0 + 3.12.1 4.5.0 4.5.2 4.5.1 diff --git a/test/Kestrel.Transport.FunctionalTests/ChromeTests.cs b/test/Kestrel.Interop.FunctionalTests/ChromeTests.cs similarity index 54% rename from test/Kestrel.Transport.FunctionalTests/ChromeTests.cs rename to test/Kestrel.Interop.FunctionalTests/ChromeTests.cs index 7f72b6d09d..a1b653530c 100644 --- a/test/Kestrel.Transport.FunctionalTests/ChromeTests.cs +++ b/test/Kestrel.Interop.FunctionalTests/ChromeTests.cs @@ -4,18 +4,19 @@ #if NETCOREAPP2_2 using System; -using System.Diagnostics; using System.IO; using System.Net; +using System.Reflection; using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Server.Kestrel.Core; -using Microsoft.AspNetCore.Server.Kestrel.FunctionalTests; using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing.xunit; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Testing; +using OpenQA.Selenium.Chrome; using Xunit; namespace Interop.FunctionalTests @@ -40,7 +41,7 @@ namespace Interop.FunctionalTests private string NetLogPath { get; set; } private string StartupLogPath { get; set; } private string ShutdownLogPath { get; set; } - private string ChromeArgs { get; set; } + private string[] ChromeArgs { get; set; } private void InitializeArgs() { @@ -48,17 +49,20 @@ namespace Interop.FunctionalTests StartupLogPath = Path.Combine(ResolvedLogOutputDirectory, $"{ResolvedTestMethodName}.su.json"); ShutdownLogPath = Path.Combine(ResolvedLogOutputDirectory, $"{ResolvedTestMethodName}.sd.json"); - ChromeArgs = $"--headless " + - $"--no-sandbox " + - $"--disable-gpu " + - $"--allow-insecure-localhost " + - $"--ignore-certificate-errors --enable-features=NetworkService " + - $"--enable-logging " + - $"--dump-dom " + - $"--virtual-time-budget=10000 " + - $"--log-net-log={NetLogPath} " + - $"--trace-startup --trace-startup-file={StartupLogPath} " + - $"--trace-shutdown --trace-shutdown-file={ShutdownLogPath}"; + ChromeArgs = new [] { + $"--headless", + $"--no-sandbox", + $"--disable-gpu", + $"--allow-insecure-localhost", + $"--ignore-certificate-errors", + $"--enable-features=NetworkService", + $"--enable-logging", + $"--log-net-log={NetLogPath}", + $"--trace-startup", + $"--trace-startup-file={StartupLogPath}", + $"--trace-shutdown", + $"--trace-shutdown-file={ShutdownLogPath}" + }; } [ConditionalTheory] @@ -70,54 +74,48 @@ namespace Interop.FunctionalTests { InitializeArgs(); - using (var server = new TestServer(async context => - { - if (string.Equals(context.Request.Query["TestMethod"], "POST", StringComparison.OrdinalIgnoreCase)) + var hostBuilder = new WebHostBuilder() + .UseKestrel(options => { - await context.Response.WriteAsync(_postHtml); - } - else + options.Listen(IPAddress.Loopback, 0, listenOptions => + { + listenOptions.Protocols = HttpProtocols.Http2; + listenOptions.UseHttps(TestResources.GetTestCertificate()); + }); + }) + .ConfigureServices(AddTestLogging) + .Configure(app => app.Run(async context => { - await context.Response.WriteAsync($"Interop {context.Request.Protocol} {context.Request.Method}"); - } - }, - new TestServiceContext(LoggerFactory), - options => options.Listen(IPAddress.Loopback, 0, listenOptions => + if (string.Equals(context.Request.Query["TestMethod"], "POST", StringComparison.OrdinalIgnoreCase)) + { + await context.Response.WriteAsync(_postHtml); + } + else + { + await context.Response.WriteAsync($"Interop {context.Request.Protocol} {context.Request.Method}"); + } + })); + + using (var host = hostBuilder.Build()) { - listenOptions.Protocols = HttpProtocols.Http2; - listenOptions.UseHttps(TestResources.GetTestCertificate()); - }))) - { - var chromeOutput = await RunHeadlessChrome($"https://localhost:{server.Port}/{requestSuffix}"); + await host.StartAsync(); + var chromeOutput = RunHeadlessChrome($"https://localhost:{host.GetPort()}/{requestSuffix}"); AssertExpectedResponseOrShowDebugInstructions(expectedResponse, chromeOutput); } } - private async Task RunHeadlessChrome(string testUrl) + private string RunHeadlessChrome(string testUrl) { - var chromeArgs = $"{ChromeArgs} {testUrl}"; - var chromeStartInfo = new ProcessStartInfo + var chromeOptions = new ChromeOptions(); + chromeOptions.AddArguments(ChromeArgs); + + using (var driver = new ChromeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), chromeOptions)) { - FileName = ChromeConstants.ExecutablePath, - Arguments = chromeArgs, - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardError = true, - RedirectStandardOutput = true - }; + driver.Navigate().GoToUrl(testUrl); - Logger.LogInformation($"Staring chrome: {ChromeConstants.ExecutablePath} {chromeArgs}"); - - var headlessChromeProcess = Process.Start(chromeStartInfo); - var chromeOutput = await headlessChromeProcess.StandardOutput.ReadToEndAsync(); - var chromeError = await headlessChromeProcess.StandardError.ReadToEndAsync(); - Logger.LogInformation($"Standard output: {chromeOutput}"); - Logger.LogInformation($"Standard error: {chromeError}"); - - headlessChromeProcess.WaitForExit(); - - return chromeOutput; + return driver.PageSource; + } } private void AssertExpectedResponseOrShowDebugInstructions(string expectedResponse, string actualResponse) diff --git a/test/Kestrel.H2Spec.FunctionalTests/H2SpecCommands.cs b/test/Kestrel.Interop.FunctionalTests/H2SpecCommands.cs similarity index 99% rename from test/Kestrel.H2Spec.FunctionalTests/H2SpecCommands.cs rename to test/Kestrel.Interop.FunctionalTests/H2SpecCommands.cs index 09b57d2990..0286f571f7 100644 --- a/test/Kestrel.H2Spec.FunctionalTests/H2SpecCommands.cs +++ b/test/Kestrel.Interop.FunctionalTests/H2SpecCommands.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; using System.Xml; using Microsoft.Extensions.Logging; -namespace H2Spec.FunctionalTests +namespace Interop.FunctionalTests { public static class H2SpecCommands { diff --git a/test/Kestrel.H2Spec.FunctionalTests/H2SpecTests.cs b/test/Kestrel.Interop.FunctionalTests/H2SpecTests.cs similarity index 91% rename from test/Kestrel.H2Spec.FunctionalTests/H2SpecTests.cs rename to test/Kestrel.Interop.FunctionalTests/H2SpecTests.cs index c2560335d3..84bd29b3d0 100644 --- a/test/Kestrel.H2Spec.FunctionalTests/H2SpecTests.cs +++ b/test/Kestrel.Interop.FunctionalTests/H2SpecTests.cs @@ -8,7 +8,6 @@ using System.Net; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Testing; @@ -17,7 +16,7 @@ using Microsoft.Extensions.Logging.Testing; using Xunit; using Xunit.Abstractions; -namespace H2Spec.FunctionalTests +namespace Interop.FunctionalTests { [OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Missing SslStream ALPN support: https://github.com/dotnet/corefx/issues/30492")] [MinimumOSVersion(OperatingSystems.Windows, WindowsVersions.Win81, @@ -47,7 +46,7 @@ namespace H2Spec.FunctionalTests { await host.StartAsync(); - H2SpecCommands.RunTest(testCase.Id, GetPort(host), testCase.Https, Logger); + H2SpecCommands.RunTest(testCase.Id, host.GetPort(), testCase.Https, Logger); } } @@ -130,13 +129,5 @@ namespace H2Spec.FunctionalTests await context.Response.WriteAsync("Hello World"); }); } - - private static int GetPort(IWebHost host) - { - return host.ServerFeatures.Get().Addresses - .Select(a => new Uri(a)) - .First() - .Port; - } } } diff --git a/test/Kestrel.H2Spec.FunctionalTests/Kestrel.H2Spec.FunctionalTests.csproj b/test/Kestrel.Interop.FunctionalTests/Kestrel.Interop.FunctionalTests.csproj similarity index 67% rename from test/Kestrel.H2Spec.FunctionalTests/Kestrel.H2Spec.FunctionalTests.csproj rename to test/Kestrel.Interop.FunctionalTests/Kestrel.Interop.FunctionalTests.csproj index 06e4138c78..7b77dca5da 100644 --- a/test/Kestrel.H2Spec.FunctionalTests/Kestrel.H2Spec.FunctionalTests.csproj +++ b/test/Kestrel.Interop.FunctionalTests/Kestrel.Interop.FunctionalTests.csproj @@ -1,16 +1,18 @@  - H2Spec.FunctionalTests - H2Spec.FunctionalTests + Interop.FunctionalTests + Interop.FunctionalTests $(DeveloperBuildTestTfms) true - H2Spec.FunctionalTests + Interop.FunctionalTests + CS8002;$(WarningsNotAsErrors) + @@ -24,6 +26,8 @@ + + diff --git a/test/Kestrel.Transport.FunctionalTests/ChromeConstants.cs b/test/Kestrel.Interop.FunctionalTests/SkipIfChromeUnavailableAttribute.cs similarity index 60% rename from test/Kestrel.Transport.FunctionalTests/ChromeConstants.cs rename to test/Kestrel.Interop.FunctionalTests/SkipIfChromeUnavailableAttribute.cs index 9e527a17b6..e01609be00 100644 --- a/test/Kestrel.Transport.FunctionalTests/ChromeConstants.cs +++ b/test/Kestrel.Interop.FunctionalTests/SkipIfChromeUnavailableAttribute.cs @@ -4,12 +4,16 @@ using System; using System.IO; using System.Runtime.InteropServices; +using Microsoft.AspNetCore.Testing.xunit; namespace Interop.FunctionalTests { - public static class ChromeConstants + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)] + public class SkipIfChromeUnavailableAttribute : Attribute, ITestCondition { - public static string ExecutablePath { get; } = ResolveChromeExecutablePath(); + public bool IsMet => string.IsNullOrEmpty(Environment.GetEnvironmentVariable("JENKINS_HOME")) && (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CI")) || File.Exists(ResolveChromeExecutablePath())); + + public string SkipReason => "This is running on Jenkins or Chrome/Chromium is not installed and this is a dev environment."; private static string ResolveChromeExecutablePath() { diff --git a/test/Kestrel.Transport.FunctionalTests/SkipIfChromeUnavailableAttribute.cs b/test/Kestrel.Transport.FunctionalTests/SkipIfChromeUnavailableAttribute.cs deleted file mode 100644 index 0820eab7d9..0000000000 --- a/test/Kestrel.Transport.FunctionalTests/SkipIfChromeUnavailableAttribute.cs +++ /dev/null @@ -1,17 +0,0 @@ -// 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.IO; -using Microsoft.AspNetCore.Testing.xunit; - -namespace Interop.FunctionalTests -{ - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)] - public class SkipIfChromeUnavailableAttribute : Attribute, ITestCondition - { - public bool IsMet => string.IsNullOrEmpty(Environment.GetEnvironmentVariable("JENKINS_HOME")) && (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("CI")) || File.Exists(ChromeConstants.ExecutablePath)); - - public string SkipReason => "This is running on Jenkins or Chrome/Chromium is not installed and this is a dev environment."; - } -} diff --git a/test/Kestrel.Transport.Sockets.FunctionalTests/Kestrel.Transport.Sockets.FunctionalTests.csproj b/test/Kestrel.Transport.Sockets.FunctionalTests/Kestrel.Transport.Sockets.FunctionalTests.csproj index 35be01d361..d9307fe2bc 100644 --- a/test/Kestrel.Transport.Sockets.FunctionalTests/Kestrel.Transport.Sockets.FunctionalTests.csproj +++ b/test/Kestrel.Transport.Sockets.FunctionalTests/Kestrel.Transport.Sockets.FunctionalTests.csproj @@ -26,7 +26,6 @@ -