diff --git a/build/dependencies.props b/build/dependencies.props index f4a8fd8eff..f66a72c941 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -5,36 +5,36 @@ 0.10.13 2.2.0-preview1-17099 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 0.6.0-a-preview1-DeploymentParameters-17085 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 15.6.82 15.6.82 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 - 2.2.0-preview1-34694 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 + 2.2.0-preview1-34709 2.0.9 2.1.2 2.2.0-preview1-26618-02 - 2.2.0-preview1-34694 + 2.2.0-preview1-34709 15.6.1 11.1.0 2.0.3 diff --git a/src/AspNetCoreModuleV2/CommonLib/aspnetcore_msg.mc b/src/AspNetCoreModuleV2/CommonLib/aspnetcore_msg.mc index c15047b235..96172c6e24 100644 --- a/src/AspNetCoreModuleV2/CommonLib/aspnetcore_msg.mc +++ b/src/AspNetCoreModuleV2/CommonLib/aspnetcore_msg.mc @@ -224,6 +224,13 @@ Language=English %1 . + +Messageid=1033 +SymbolicName=ASPNETCORE_EVENT_APP_SHUTDOWN_SUCCESSFUL +Language=English +%1 +. + ; ;#endif // _ASPNETCORE_MODULE_MSG_H_ ; diff --git a/src/AspNetCoreModuleV2/CommonLib/resources.h b/src/AspNetCoreModuleV2/CommonLib/resources.h index 2956cce581..861619e5b2 100644 --- a/src/AspNetCoreModuleV2/CommonLib/resources.h +++ b/src/AspNetCoreModuleV2/CommonLib/resources.h @@ -26,6 +26,7 @@ #define ASPNETCORE_EVENT_SENT_SHUTDOWN_HTTP_REQUEST_MSG L"Sent shutdown HTTP message to process '%d' and received http status '%d'." #define ASPNETCORE_EVENT_APP_SHUTDOWN_FAILURE_MSG L"Failed to gracefully shutdown application '%s'." #define ASPNETCORE_EVENT_LOAD_CLR_FALIURE_MSG L"Application '%s' with physical root '%s' failed to load clr and managed application, ErrorCode = '0x%x." +#define ASPNETCORE_EVENT_APP_SHUTDOWN_SUCCESSFUL_MSG L"Application '%s' has shutdown." #define ASPNETCORE_EVENT_DUPLICATED_INPROCESS_APP_MSG L"Only one inprocess application is allowed per IIS application pool. Please assign the application '%s' to a different IIS application pool." #define ASPNETCORE_EVENT_MIXED_HOSTING_MODEL_ERROR_MSG L"Mixed hosting model is not supported. Application '%s' configured with different hostingModel value '%d' other than the one of running application(s)." #define ASPNETCORE_EVENT_ADD_APPLICATION_ERROR_MSG L"Failed to start application '%s', ErrorCode '0x%x'." diff --git a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp index baf73ec9c1..b52b08f833 100644 --- a/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp +++ b/src/AspNetCoreModuleV2/InProcessRequestHandler/inprocessapplication.cpp @@ -126,6 +126,14 @@ Finished: // exit(hr); } + else + { + UTILITY::LogEventF(g_hEventLog, + EVENTLOG_INFORMATION_TYPE, + ASPNETCORE_EVENT_APP_SHUTDOWN_SUCCESSFUL, + ASPNETCORE_EVENT_APP_SHUTDOWN_SUCCESSFUL_MSG, + m_pConfig->QueryConfigPath()->QueryStr()); + } } VOID diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/ApplicationDeployerFactory.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/ApplicationDeployerFactory.cs index aaec90971e..8fddbaede6 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/ApplicationDeployerFactory.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/ApplicationDeployerFactory.cs @@ -33,7 +33,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting switch (deploymentParameters.ServerType) { case ServerType.IISExpress: - return new IIS.IISExpressDeployer(deploymentParameters, loggerFactory); + return new IISExpressDeployer(deploymentParameters, loggerFactory); case ServerType.IIS: return new IISDeployer(deploymentParameters, loggerFactory); default: diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISApplication.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISApplication.cs index d0c0bfb153..c1a26d3181 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISApplication.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISApplication.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting /// internal class IISApplication { - private static readonly TimeSpan _timeout = TimeSpan.FromSeconds(5); + private static readonly TimeSpan _timeout = TimeSpan.FromSeconds(10); private static readonly TimeSpan _retryDelay = TimeSpan.FromMilliseconds(200); private readonly ServerManager _serverManager = new ServerManager(); private readonly DeploymentParameters _deploymentParameters; @@ -32,6 +32,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting "config", "applicationhost.config"); + public Process HostProcess { get; set; } + public IISApplication(DeploymentParameters deploymentParameters, ILogger logger) { _deploymentParameters = deploymentParameters; @@ -63,7 +65,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting } AddTemporaryAppHostConfig(); - ConfigureAppPool(contentRoot); + var apppool = ConfigureAppPool(contentRoot); ConfigureSite(contentRoot, port); @@ -76,7 +78,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting _serverManager.CommitChanges(); - await WaitUntilSiteStarted(); + await WaitUntilSiteStarted(apppool); } } @@ -89,7 +91,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting config.Save(webConfigFile); } - private async Task WaitUntilSiteStarted() + private async Task WaitUntilSiteStarted(ApplicationPool appPool) { var sw = Stopwatch.StartNew(); @@ -98,6 +100,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting try { var site = _serverManager.Sites.FirstOrDefault(s => s.Name.Equals(WebSiteName)); + if (site.State == ObjectState.Started) { _logger.LogInformation($"Site {WebSiteName} has started."); diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployer.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployer.cs index bb126a7fa5..c093ae3065 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployer.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployer.cs @@ -75,13 +75,13 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS // Warm up time for IIS setup. Logger.LogInformation("Successfully finished IIS application directory setup."); - - return new DeploymentResult( + return new IISDeploymentResult( LoggerFactory, IISDeploymentParameters, applicationBaseUri: uri.ToString(), contentRoot: contentRoot, - hostShutdownToken: _hostShutdownToken.Token + hostShutdownToken: _hostShutdownToken.Token, + hostProcess: _application.HostProcess ); } } diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployerBase.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployerBase.cs index 85e329b824..04e8448327 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployerBase.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeployerBase.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeploymentParameters.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeploymentParameters.cs index 9459fd7814..a22116d557 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeploymentParameters.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeploymentParameters.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS { @@ -43,6 +44,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS ServerConfigActionList = tempParameters.ServerConfigActionList; WebConfigBasedEnvironmentVariables = tempParameters.WebConfigBasedEnvironmentVariables; HandlerSettings = tempParameters.HandlerSettings; + GracefulShutdown = tempParameters.GracefulShutdown; } } @@ -59,6 +61,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS public IDictionary HandlerSettings { get; set; } = new Dictionary(); + public bool GracefulShutdown { get; set; } + private Action AddWebConfigEnvironmentVariables() { return xElement => diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeploymentResult.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeploymentResult.cs new file mode 100644 index 0000000000..4a9d881900 --- /dev/null +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISDeploymentResult.cs @@ -0,0 +1,57 @@ +// 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.Diagnostics; +using System.Net.Http; +using System.Threading; +using Microsoft.Extensions.Logging; + +namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS +{ + public class IISDeploymentResult : DeploymentResult + { + public ILogger Logger { get; set; } + public Process HostProcess { get; } + + public IISDeploymentResult(ILoggerFactory loggerFactory, + IISDeploymentParameters deploymentParameters, + string applicationBaseUri, + string contentRoot, + CancellationToken hostShutdownToken, + Process hostProcess) + : base(loggerFactory, + deploymentParameters, + applicationBaseUri, + contentRoot, + hostShutdownToken) + { + HostProcess = hostProcess; + Logger = loggerFactory.CreateLogger(deploymentParameters.SiteName); + // SocketsHttpHandler isn't available in netstandard2.0 + RetryingHttpClient = CreateRetryClient(new HttpClientHandler()); + HttpClient = CreateClient(new HttpClientHandler()); + } + + public HttpClient CreateRetryClient(HttpMessageHandler messageHandler) + { + var loggingHandler = new LoggingHandler(messageHandler, Logger); + var retryHandler = new RetryHandler(loggingHandler, Logger); + return new HttpClient(retryHandler) + { + BaseAddress = base.HttpClient.BaseAddress + }; + } + + public HttpClient CreateClient(HttpMessageHandler messageHandler) + { + return new HttpClient(new LoggingHandler(messageHandler, Logger)) + { + BaseAddress = base.HttpClient.BaseAddress + }; + } + + public HttpClient RetryingHttpClient { get; set; } + + public new HttpClient HttpClient { get; set; } + } +} diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISExpressDeployer.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISExpressDeployer.cs index ecdd536db5..729c5f870f 100644 --- a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISExpressDeployer.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/IISExpressDeployer.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -25,7 +26,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS private const string FailedToInitializeBindingsMessage = "Failed to initialize site bindings"; private const string UnableToStartIISExpressMessage = "Unable to start iisexpress."; private const int MaximumAttempts = 5; - + private readonly TimeSpan ShutdownTimeSpan = TimeSpan.FromSeconds(60); private static readonly Regex UrlDetectorRegex = new Regex(@"^\s*Successfully registered URL ""(?[^""]+)"" for site.*$"); private Process _hostProcess; @@ -97,12 +98,14 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS Logger.LogInformation("Application ready at URL: {appUrl}", actualUri); // Right now this works only for urls like http://localhost:5001/. Does not work for http://localhost:5001/subpath. - return new DeploymentResult( + + return new IISDeploymentResult( LoggerFactory, IISDeploymentParameters, applicationBaseUri: actualUri.ToString(), contentRoot: contentRoot, - hostShutdownToken: hostExitToken); + hostShutdownToken: hostExitToken, + hostProcess: _hostProcess); } } @@ -352,7 +355,14 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS { using (Logger.BeginScope("Dispose")) { - ShutDownIfAnyHostProcess(_hostProcess); + if (IISDeploymentParameters.GracefulShutdown) + { + GracefullyShutdownProcess(_hostProcess); + } + else + { + ShutDownIfAnyHostProcess(_hostProcess); + } if (!string.IsNullOrEmpty(DeploymentParameters.ServerConfigLocation) && File.Exists(DeploymentParameters.ServerConfigLocation)) @@ -388,6 +398,59 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS } } + private class WindowsNativeMethods + { + [DllImport("user32.dll")] + internal static extern IntPtr GetTopWindow(IntPtr hWnd); + [DllImport("user32.dll")] + internal static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); + [DllImport("user32.dll")] + internal static extern uint GetWindowThreadProcessId(IntPtr hwnd, out uint lpdwProcessId); + [DllImport("user32.dll")] + internal static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam); + } + + private static void SendStopMessageToProcess(int pid) + { + for (var ptr = WindowsNativeMethods.GetTopWindow(IntPtr.Zero); ptr != IntPtr.Zero; ptr = WindowsNativeMethods.GetWindow(ptr, 2)) + { + uint num; + WindowsNativeMethods.GetWindowThreadProcessId(ptr, out num); + if (pid == num) + { + var hWnd = new HandleRef(null, ptr); + WindowsNativeMethods.PostMessage(hWnd, 0x12, IntPtr.Zero, IntPtr.Zero); + return; + } + } + } + + private void GracefullyShutdownProcess(Process hostProcess) + { + if (hostProcess != null && !hostProcess.HasExited) + { + // Calling hostProcess.StandardInput.WriteLine("q") with StandardInput redirected + // for the process does not work when stopping IISExpress + // Also, hostProcess.CloseMainWindow() doesn't work either. + // Instead we have to send WM_QUIT to the iisexpress process via pInvokes. + // See: https://stackoverflow.com/questions/4772092/starting-and-stopping-iis-express-programmatically + + SendStopMessageToProcess(hostProcess.Id); + if (!hostProcess.WaitForExit((int)ShutdownTimeSpan.TotalMilliseconds)) + { + throw new InvalidOperationException($"iisexpress Process {hostProcess.Id} failed to gracefully shutdown."); + } + if (hostProcess.ExitCode != 0) + { + Logger.LogWarning($"IISExpress exit code is non-zero after graceful shutdown. Exit code: {hostProcess.ExitCode}"); + } + } + else + { + throw new InvalidOperationException($"iisexpress Process {hostProcess.Id} crashed before shutdown was triggered."); + } + } + private void ModifyDotNetExePathInWebConfig() { // We assume the x64 dotnet.exe is on the path so we need to provide an absolute path for x86 scenarios. diff --git a/test/Common.Tests/Utilities/LoggingHandler.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/LoggingHandler.cs similarity index 96% rename from test/Common.Tests/Utilities/LoggingHandler.cs rename to src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/LoggingHandler.cs index 9559d8106c..241991f62d 100644 --- a/test/Common.Tests/Utilities/LoggingHandler.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/LoggingHandler.cs @@ -4,7 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; -namespace Microsoft.AspNetCore.Server.IntegrationTesting +namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS { public class LoggingHandler: DelegatingHandler { diff --git a/test/Common.Tests/Utilities/RetryHandler.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/RetryHandler.cs similarity index 96% rename from test/Common.Tests/Utilities/RetryHandler.cs rename to src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/RetryHandler.cs index 00e1174c7a..4282c3afca 100644 --- a/test/Common.Tests/Utilities/RetryHandler.cs +++ b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/RetryHandler.cs @@ -8,7 +8,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; -namespace Microsoft.AspNetCore.Server.IntegrationTesting +namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS { public class RetryHandler : DelegatingHandler { diff --git a/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/TestUriHelper.cs b/src/Microsoft.AspNetCore.Server.IntegrationTesting.IIS/TestUriHelper.cs deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/test/Common.FunctionalTests/Inprocess/EventLogTests.cs b/test/Common.FunctionalTests/Inprocess/EventLogTests.cs index 176661189c..67483b0663 100644 --- a/test/Common.FunctionalTests/Inprocess/EventLogTests.cs +++ b/test/Common.FunctionalTests/Inprocess/EventLogTests.cs @@ -20,5 +20,18 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests EventLogHelpers.VerifyEventLogEvent(TestSink, "Application '.+' started the coreclr in-process successfully."); } + + [ConditionalFact] + public async Task CheckShutdownEventLogMessage() + { + var deploymentParameters = Helpers.GetBaseDeploymentParameters(publish: true); + deploymentParameters.GracefulShutdown = true; + var deploymentResult = await DeployAsync(deploymentParameters); + await Helpers.AssertStarts(deploymentResult); + + StopServer(); + + EventLogHelpers.VerifyEventLogEvent(TestSink, "Application '.+' has shutdown."); + } } } diff --git a/test/Common.FunctionalTests/Inprocess/LoggingTests.cs b/test/Common.FunctionalTests/Inprocess/LoggingTests.cs index 2b0b0c9ada..e8e303b429 100644 --- a/test/Common.FunctionalTests/Inprocess/LoggingTests.cs +++ b/test/Common.FunctionalTests/Inprocess/LoggingTests.cs @@ -68,7 +68,6 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests var deploymentResult = await DeployAsync(deploymentParameters); - await Helpers.AssertStarts(deploymentResult, "HelloWorld"); } diff --git a/test/Common.FunctionalTests/Utilities/FunctionalTestsBase.cs b/test/Common.FunctionalTests/Utilities/FunctionalTestsBase.cs index ed493f79ef..d23b7836e5 100644 --- a/test/Common.FunctionalTests/Utilities/FunctionalTestsBase.cs +++ b/test/Common.FunctionalTests/Utilities/FunctionalTestsBase.cs @@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting { } - private ApplicationDeployer _deployer; + protected ApplicationDeployer _deployer; protected virtual async Task DeployAsync(IISDeploymentParameters parameters) { @@ -31,11 +31,10 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting parameters.ServerConfigTemplateContent = parameters.ServerConfigTemplateContent ?? File.ReadAllText("IISExpress.config"); } + _deployer = IISApplicationDeployerFactory.Create(parameters, LoggerFactory); - var result = await _deployer.DeployAsync(); - - return new IISDeploymentResult(result, Logger); + return (IISDeploymentResult)await _deployer.DeployAsync(); } public override void Dispose() diff --git a/test/Common.FunctionalTests/Utilities/IISDeploymentResult.cs b/test/Common.FunctionalTests/Utilities/IISDeploymentResult.cs deleted file mode 100644 index 8e39634f2b..0000000000 --- a/test/Common.FunctionalTests/Utilities/IISDeploymentResult.cs +++ /dev/null @@ -1,42 +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.Net.Http; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.Server.IntegrationTesting -{ - public class IISDeploymentResult - { - public DeploymentResult DeploymentResult { get; } - public ILogger Logger { get; } - - public IISDeploymentResult(DeploymentResult deploymentResult, ILogger logger) - { - DeploymentResult = deploymentResult; - Logger = logger; - - RetryingHttpClient = CreateRetryClient(new SocketsHttpHandler()); - HttpClient = CreateClient(new SocketsHttpHandler()); - } - - public HttpClient CreateRetryClient(HttpMessageHandler messageHandler) - { - return new HttpClient(new RetryHandler(new LoggingHandler(messageHandler, Logger), Logger)) - { - BaseAddress = DeploymentResult.HttpClient.BaseAddress - }; - } - - public HttpClient CreateClient(HttpMessageHandler messageHandler) - { - return new HttpClient(new LoggingHandler(messageHandler, Logger)) - { - BaseAddress = DeploymentResult.HttpClient.BaseAddress - }; - } - - public HttpClient HttpClient { get; set; } - public HttpClient RetryingHttpClient { get; set; } - } -} diff --git a/test/IIS.Tests/Utilities/TestServer.cs b/test/IIS.Tests/Utilities/TestServer.cs index c64fe4fbe9..4adaaff776 100644 --- a/test/IIS.Tests/Utilities/TestServer.cs +++ b/test/IIS.Tests/Utilities/TestServer.cs @@ -15,6 +15,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; diff --git a/test/IISExpress.FunctionalTests/IISExpress.FunctionalTests.csproj b/test/IISExpress.FunctionalTests/IISExpress.FunctionalTests.csproj index cbd3d05b6b..3ae8fcffe8 100644 --- a/test/IISExpress.FunctionalTests/IISExpress.FunctionalTests.csproj +++ b/test/IISExpress.FunctionalTests/IISExpress.FunctionalTests.csproj @@ -29,7 +29,6 @@ - diff --git a/test/IISExpress.FunctionalTests/InProcess/AppOfflineTests.cs b/test/IISExpress.FunctionalTests/InProcess/AppOfflineTests.cs index b7e850cdb8..265907542f 100644 --- a/test/IISExpress.FunctionalTests/InProcess/AppOfflineTests.cs +++ b/test/IISExpress.FunctionalTests/InProcess/AppOfflineTests.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Testing.xunit; using Microsoft.Extensions.Logging; using Xunit; +using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.Inprocess { @@ -26,7 +27,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.Inprocess { var deploymentResult = await DeployApp(hostingModel); - AddAppOffline(deploymentResult.DeploymentResult.ContentRoot); + AddAppOffline(deploymentResult.ContentRoot); await AssertAppOffline(deploymentResult); } @@ -39,7 +40,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.Inprocess var expectedResponse = "The app is offline."; var deploymentResult = await DeployApp(hostingModel); - AddAppOffline(deploymentResult.DeploymentResult.ContentRoot, expectedResponse); + AddAppOffline(deploymentResult.ContentRoot, expectedResponse); await AssertAppOffline(deploymentResult, expectedResponse); } @@ -49,7 +50,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.Inprocess { var deploymentResult = await AssertStarts(HostingModel.InProcess); - AddAppOffline(deploymentResult.DeploymentResult.ContentRoot); + AddAppOffline(deploymentResult.ContentRoot); await AssertStopsProcess(deploymentResult); } @@ -62,9 +63,9 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.Inprocess // Repeat dropping file and restarting multiple times for (int i = 0; i < 5; i++) { - AddAppOffline(deploymentResult.DeploymentResult.ContentRoot); + AddAppOffline(deploymentResult.ContentRoot); await AssertAppOffline(deploymentResult); - RemoveAppOffline(deploymentResult.DeploymentResult.ContentRoot); + RemoveAppOffline(deploymentResult.ContentRoot); await AssertRunning(deploymentResult); } } @@ -76,11 +77,11 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.Inprocess { var deploymentResult = await DeployApp(hostingModel); - AddAppOffline(deploymentResult.DeploymentResult.ContentRoot); + AddAppOffline(deploymentResult.ContentRoot); await AssertAppOffline(deploymentResult); - RemoveAppOffline(deploymentResult.DeploymentResult.ContentRoot); + RemoveAppOffline(deploymentResult.ContentRoot); await AssertRunning(deploymentResult); } @@ -132,7 +133,7 @@ namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.Inprocess // dropping app_offline will kill the process } - var hostShutdownToken = deploymentResult.DeploymentResult.HostShutdownToken; + var hostShutdownToken = deploymentResult.HostShutdownToken; Assert.True(hostShutdownToken.WaitHandle.WaitOne(TimeoutExtensions.DefaultTimeout)); Assert.True(hostShutdownToken.IsCancellationRequested); diff --git a/test/IISExpress.FunctionalTests/InProcess/AuthenticationTests.cs b/test/IISExpress.FunctionalTests/InProcess/AuthenticationTests.cs index 0281116218..5105b753c8 100644 --- a/test/IISExpress.FunctionalTests/InProcess/AuthenticationTests.cs +++ b/test/IISExpress.FunctionalTests/InProcess/AuthenticationTests.cs @@ -46,7 +46,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; - var httpClient = deploymentResult.DeploymentResult.CreateHttpClient(httpClientHandler); + var httpClient = deploymentResult.CreateHttpClient(httpClientHandler); response = await httpClient.GetAsync("/AuthenticationAnonymous"); responseText = await response.Content.ReadAsStringAsync(); diff --git a/test/IISExpress.FunctionalTests/InProcess/ShutdownTests.cs b/test/IISExpress.FunctionalTests/InProcess/ShutdownTests.cs index 179c6bd198..b1ab071c5d 100644 --- a/test/IISExpress.FunctionalTests/InProcess/ShutdownTests.cs +++ b/test/IISExpress.FunctionalTests/InProcess/ShutdownTests.cs @@ -24,7 +24,30 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests var result = await DeployAsync(parameters); var response = await result.RetryingHttpClient.GetAsync("/Shutdown"); - Assert.True(result.DeploymentResult.HostShutdownToken.WaitHandle.WaitOne(TimeoutExtensions.DefaultTimeout)); + Assert.True(result.HostShutdownToken.WaitHandle.WaitOne(TimeoutExtensions.DefaultTimeout)); + } + + [ConditionalFact] + public async Task GracefulShutdown_DoesNotCrashProcess() + { + var parameters = Helpers.GetBaseDeploymentParameters(publish: true); + parameters.GracefulShutdown = true; + var result = await DeployAsync(parameters); + + var response = await result.RetryingHttpClient.GetAsync("/HelloWorld"); + StopServer(); + Assert.True(result.HostProcess.ExitCode == 0); + } + + [ConditionalFact] + public async Task ForcefulShutdown_DoesrashProcess() + { + var parameters = Helpers.GetBaseDeploymentParameters(publish: true); + var result = await DeployAsync(parameters); + + var response = await result.RetryingHttpClient.GetAsync("/HelloWorld"); + StopServer(); + Assert.True(result.HostProcess.ExitCode == 1); } } } diff --git a/test/IISExpress.FunctionalTests/OutOfProcess/GlobalVersionTests.cs b/test/IISExpress.FunctionalTests/OutOfProcess/GlobalVersionTests.cs index 84be58247c..8ad7a70665 100644 --- a/test/IISExpress.FunctionalTests/OutOfProcess/GlobalVersionTests.cs +++ b/test/IISExpress.FunctionalTests/OutOfProcess/GlobalVersionTests.cs @@ -152,8 +152,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests private string GetANCMRequestHandlerPath(IISDeploymentResult deploymentResult, string version) { - return Path.Combine(deploymentResult.DeploymentResult.ContentRoot, - deploymentResult.DeploymentResult.DeploymentParameters.RuntimeArchitecture.ToString(), + return Path.Combine(deploymentResult.ContentRoot, + deploymentResult.DeploymentParameters.RuntimeArchitecture.ToString(), version, _aspNetCoreDll); }