From 6440545c4a1a170de19ca80c1cf24ff346a005b1 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 15 Aug 2018 16:47:47 -0700 Subject: [PATCH] Add hosting model switch tests (#1245) --- build/launchSettings.json | 4 +-- build/testsite.props | 4 +-- .../NativeIISSample/NativeIISSample.csproj | 5 +++- .../Properties/launchSettings.json | 4 +-- samples/NativeIISSample/Startup.cs | 18 +++++++++-- .../AspNetCore/HandlerResolver.cpp | 9 ++---- .../AspNetCore/applicationmanager.cpp | 30 +++++-------------- .../AspNetCore/applicationmanager.h | 2 -- .../CommonLib/GlobalVersionUtility.cpp | 4 +-- .../ConfigurationChangeTests.cs | 20 +++++++++++++ .../Utilities/Helpers.cs | 2 +- .../OutOfProcess/GlobalVersionTests.cs | 15 ++++++++++ .../Properties/launchSettings.json | 4 +-- .../Properties/launchSettings.json | 4 +-- .../Properties/launchSettings.json | 4 +-- .../Properties/launchSettings.json | 4 +-- .../Properties/launchSettings.json | 4 +-- 17 files changed, 83 insertions(+), 54 deletions(-) diff --git a/build/launchSettings.json b/build/launchSettings.json index 38ae6c9d32..9c963c0100 100644 --- a/build/launchSettings.json +++ b/build/launchSettings.json @@ -15,8 +15,8 @@ "nativeDebugging": true, "environmentVariables": { "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AncmPath)", - "ANCMV2_PATH": "$(AncmV2Path)", + "ANCM_PATH": "$(TargetDir)\\$(AncmPath)", + "ANCMV2_PATH": "$(TargetDir)\\$(AncmV2Path)", "LAUNCHER_ARGS": "$(TargetPath)", "ASPNETCORE_ENVIRONMENT": "Development", "LAUNCHER_PATH": "$(DotNetPath)", diff --git a/build/testsite.props b/build/testsite.props index 03aa0c9cff..1588b54226 100644 --- a/build/testsite.props +++ b/build/testsite.props @@ -36,8 +36,8 @@ /config:"$(IISExpressAppHostConfig)" /systray:false -h "$(IISAppHostConfig)" - $(AspNetCoreModuleV1ShimDll) - $(AspNetCoreModuleV2ShimDll) + $(NativePlatform)\aspnetcore.dll + $(NativePlatform)\aspnetcorev2.dll aspnetcorev2_inprocess.dll $(userprofile)\.dotnet\$(NativePlatform)\dotnet.exe diff --git a/samples/NativeIISSample/NativeIISSample.csproj b/samples/NativeIISSample/NativeIISSample.csproj index c1f4b88c89..cba368eafc 100644 --- a/samples/NativeIISSample/NativeIISSample.csproj +++ b/samples/NativeIISSample/NativeIISSample.csproj @@ -1,4 +1,4 @@ - + @@ -9,10 +9,13 @@ + + + diff --git a/samples/NativeIISSample/Properties/launchSettings.json b/samples/NativeIISSample/Properties/launchSettings.json index 38ae6c9d32..9c963c0100 100644 --- a/samples/NativeIISSample/Properties/launchSettings.json +++ b/samples/NativeIISSample/Properties/launchSettings.json @@ -15,8 +15,8 @@ "nativeDebugging": true, "environmentVariables": { "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AncmPath)", - "ANCMV2_PATH": "$(AncmV2Path)", + "ANCM_PATH": "$(TargetDir)\\$(AncmPath)", + "ANCMV2_PATH": "$(TargetDir)\\$(AncmV2Path)", "LAUNCHER_ARGS": "$(TargetPath)", "ASPNETCORE_ENVIRONMENT": "Development", "LAUNCHER_PATH": "$(DotNetPath)", diff --git a/samples/NativeIISSample/Startup.cs b/samples/NativeIISSample/Startup.cs index 0744ef4cf1..2b18ff895c 100644 --- a/samples/NativeIISSample/Startup.cs +++ b/samples/NativeIISSample/Startup.cs @@ -14,8 +14,15 @@ namespace NativeIISSample { public class Startup { + private readonly IAuthenticationSchemeProvider _authSchemeProvider; + + public Startup(IAuthenticationSchemeProvider authSchemeProvider = null) + { + _authSchemeProvider = authSchemeProvider; + } + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env, IAuthenticationSchemeProvider authSchemeProvider) + public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.Run(async (context) => { @@ -41,8 +48,11 @@ namespace NativeIISSample await context.Response.WriteAsync(Environment.NewLine); await context.Response.WriteAsync("User: " + context.User.Identity.Name + Environment.NewLine); - var scheme = await authSchemeProvider.GetSchemeAsync(IISServerDefaults.AuthenticationScheme); - await context.Response.WriteAsync("DisplayName: " + scheme?.DisplayName + Environment.NewLine); + if (_authSchemeProvider != null) + { + var scheme = await _authSchemeProvider.GetSchemeAsync(IISServerDefaults.AuthenticationScheme); + await context.Response.WriteAsync("DisplayName: " + scheme?.DisplayName + Environment.NewLine); + } await context.Response.WriteAsync(Environment.NewLine); @@ -98,7 +108,9 @@ namespace NativeIISSample public static void Main(string[] args) { var host = new WebHostBuilder() + .UseKestrel() .UseIIS() + .UseIISIntegration() .UseStartup() .Build(); diff --git a/src/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp b/src/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp index 1f5ede9f0e..6c78cc16a6 100644 --- a/src/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp +++ b/src/AspNetCoreModuleV2/AspNetCore/HandlerResolver.cpp @@ -157,13 +157,10 @@ HandlerResolver::FindNativeAssemblyFromGlobalLocation( } catch (...) { - STRU struEvent; - if (SUCCEEDED(struEvent.Copy(ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING_MSG))) - { - EventLog::Info( + EventLog::Info( ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING, - struEvent.QueryStr()); - } + ASPNETCORE_EVENT_OUT_OF_PROCESS_RH_MISSING_MSG, + pstrHandlerDllName); return OBSERVE_CAUGHT_EXCEPTION(); } diff --git a/src/AspNetCoreModuleV2/AspNetCore/applicationmanager.cpp b/src/AspNetCoreModuleV2/AspNetCore/applicationmanager.cpp index 8e62d9ef68..25d5966a3d 100644 --- a/src/AspNetCoreModuleV2/AspNetCore/applicationmanager.cpp +++ b/src/AspNetCoreModuleV2/AspNetCore/applicationmanager.cpp @@ -116,7 +116,7 @@ APPLICATION_MANAGER::FindConfigChangedApplication( BOOL fChanged = pstruConfigPath->StartsWith(pContext->pstrPath, true); if (fChanged) { - DWORD dwLen = (DWORD)wcslen(pContext->pstrPath); + auto dwLen = wcslen(pContext->pstrPath); WCHAR wChar = pstruConfigPath->QueryStr()[dwLen]; // We need to check that the last character of the config path @@ -189,12 +189,6 @@ APPLICATION_MANAGER::RecycleApplicationFromManager( // Removed the applications which are impacted by the configurtion change m_pApplicationInfoHash->DeleteIf(FindConfigChangedApplication, (PVOID)&context); - - if (m_pApplicationInfoHash->Count() == 0 && m_hostingModel == HOSTING_OUT_PROCESS) - { - // reuse current process - m_hostingModel = HOSTING_UNKNOWN; - } } // If we receive a request at this point. @@ -211,15 +205,10 @@ APPLICATION_MANAGER::RecycleApplicationFromManager( APPLICATION_INFO* pRecord; // Application got recycled. Log an event - STACK_STRU(strEventMsg, 256); - if (SUCCEEDED(strEventMsg.SafeSnwprintf( - ASPNETCORE_EVENT_RECYCLE_CONFIGURATION_MSG, - path))) - { - EventLog::Info( + EventLog::Info( ASPNETCORE_EVENT_RECYCLE_CONFIGURATION, - strEventMsg.QueryStr()); - } + ASPNETCORE_EVENT_RECYCLE_CONFIGURATION_MSG, + path); table->FindKey(path, &pRecord); DBG_ASSERT(pRecord != NULL); @@ -241,15 +230,10 @@ Finished: if (FAILED(hr)) { // Failed to recycle an application. Log an event - STACK_STRU(strEventMsg, 256); - if (SUCCEEDED(strEventMsg.SafeSnwprintf( - ASPNETCORE_EVENT_RECYCLE_FAILURE_CONFIGURATION_MSG, - pszApplicationId))) - { - EventLog::Error( + EventLog::Error( ASPNETCORE_EVENT_RECYCLE_APP_FAILURE, - strEventMsg.QueryStr()); - } + ASPNETCORE_EVENT_RECYCLE_FAILURE_CONFIGURATION_MSG, + pszApplicationId); // Need to recycle the process as we cannot recycle the application if (!g_fRecycleProcessCalled) { diff --git a/src/AspNetCoreModuleV2/AspNetCore/applicationmanager.h b/src/AspNetCoreModuleV2/AspNetCore/applicationmanager.h index 165f3c9d3e..e0f2025f04 100644 --- a/src/AspNetCoreModuleV2/AspNetCore/applicationmanager.h +++ b/src/AspNetCoreModuleV2/AspNetCore/applicationmanager.h @@ -112,7 +112,6 @@ public: private: APPLICATION_MANAGER(HMODULE hModule, IHttpServer& pHttpServer) : m_pApplicationInfoHash(NULL), - m_hostingModel(HOSTING_UNKNOWN), m_fDebugInitialize(FALSE), m_pHttpServer(pHttpServer), m_handlerResolver(hModule, pHttpServer) @@ -123,7 +122,6 @@ private: APPLICATION_INFO_HASH *m_pApplicationInfoHash; static APPLICATION_MANAGER *sm_pApplicationManager; SRWLOCK m_srwLock {}; - APP_HOSTING_MODEL m_hostingModel; BOOL m_fDebugInitialize; IHttpServer &m_pHttpServer; HandlerResolver m_handlerResolver; diff --git a/src/AspNetCoreModuleV2/CommonLib/GlobalVersionUtility.cpp b/src/AspNetCoreModuleV2/CommonLib/GlobalVersionUtility.cpp index 7cb185b0c3..15ce48b8c5 100644 --- a/src/AspNetCoreModuleV2/CommonLib/GlobalVersionUtility.cpp +++ b/src/AspNetCoreModuleV2/CommonLib/GlobalVersionUtility.cpp @@ -76,13 +76,13 @@ GlobalVersionUtility::FindHighestGlobalVersion(PCWSTR pwzAspNetCoreFolderPath) { if (pwzAspNetCoreFolderPath == NULL) { - throw new std::invalid_argument("pwzAspNetCoreFolderPath is NULL"); + throw std::invalid_argument("pwzAspNetCoreFolderPath is NULL"); } std::vector versionsInDirectory = GetRequestHandlerVersions(pwzAspNetCoreFolderPath); if (versionsInDirectory.empty()) { - throw new std::runtime_error("Cannot find request handler next to aspnetcorev2.dll. Verify a version of the request handler is installed in a version folder."); + throw std::runtime_error("Cannot find request handler next to aspnetcorev2.dll. Verify a version of the request handler is installed in a version folder."); } std::sort(versionsInDirectory.begin(), versionsInDirectory.end()); diff --git a/test/Common.FunctionalTests/ConfigurationChangeTests.cs b/test/Common.FunctionalTests/ConfigurationChangeTests.cs index b809bf42ca..064df80451 100644 --- a/test/Common.FunctionalTests/ConfigurationChangeTests.cs +++ b/test/Common.FunctionalTests/ConfigurationChangeTests.cs @@ -5,6 +5,7 @@ using System.Net; using System.Threading.Tasks; using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; using Microsoft.AspNetCore.Server.IntegrationTesting; +using Microsoft.AspNetCore.Server.IntegrationTesting.IIS; using Microsoft.AspNetCore.Testing.xunit; using Xunit; @@ -54,5 +55,24 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests // Verify that worker process gets restarted with new process id await deploymentResult.HttpClient.RetryRequestAsync("/ProcessId", async r => await r.Content.ReadAsStringAsync() != processBefore); } + + [ConditionalFact] + public async Task OutOfProcessToInProcessHostingModelSwitchWorks() + { + var deploymentParameters = _fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess, publish: true); + + var deploymentResult = await DeployAsync(deploymentParameters); + + await deploymentResult.AssertStarts(); + + deploymentResult.ModifyWebConfig(element => element + .GetOrAdd("system.webServer") + .GetOrAdd("aspNetCore") + .SetAttributeValue("hostingModel", "inprocess")); + + // Have to retry here to allow ANCM to receive notification and react to it + // Verify that worker process gets restarted with new process id + await deploymentResult.HttpClient.RetryRequestAsync("/HelloWorld", r => r.StatusCode == HttpStatusCode.InternalServerError); + } } } diff --git a/test/Common.FunctionalTests/Utilities/Helpers.cs b/test/Common.FunctionalTests/Utilities/Helpers.cs index 30c597a111..d0b1ebc109 100644 --- a/test/Common.FunctionalTests/Utilities/Helpers.cs +++ b/test/Common.FunctionalTests/Utilities/Helpers.cs @@ -79,7 +79,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests { var webConfigPath = Path.Combine(deploymentResult.ContentRoot, "web.config"); var document = XDocument.Load(webConfigPath); - + action(document.Root); document.Save(webConfigPath); } diff --git a/test/IISExpress.FunctionalTests/OutOfProcess/GlobalVersionTests.cs b/test/IISExpress.FunctionalTests/OutOfProcess/GlobalVersionTests.cs index fa859d614a..d1096738f1 100644 --- a/test/IISExpress.FunctionalTests/OutOfProcess/GlobalVersionTests.cs +++ b/test/IISExpress.FunctionalTests/OutOfProcess/GlobalVersionTests.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; +using System.Net; using System.Threading.Tasks; using System.Xml.Linq; using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities; @@ -144,6 +145,20 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests AssertLoadedVersion(version); } + [ConditionalFact] + public async Task DoesNotCrashWhenNoVersionsAvailable() + { + var deploymentParameters = GetGlobalVersionBaseDeploymentParameters(); + CopyShimToOutput(deploymentParameters); + var deploymentResult = await DeployAsync(deploymentParameters); + + var originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20); + Directory.Delete(originalANCMPath, true); + var response = await deploymentResult.HttpClient.GetAsync("HelloWorld"); + + Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); + } + private IISDeploymentParameters GetGlobalVersionBaseDeploymentParameters() { return _fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess, publish: true); diff --git a/test/WebSites/InProcessWebSite/Properties/launchSettings.json b/test/WebSites/InProcessWebSite/Properties/launchSettings.json index 38ae6c9d32..9c963c0100 100644 --- a/test/WebSites/InProcessWebSite/Properties/launchSettings.json +++ b/test/WebSites/InProcessWebSite/Properties/launchSettings.json @@ -15,8 +15,8 @@ "nativeDebugging": true, "environmentVariables": { "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AncmPath)", - "ANCMV2_PATH": "$(AncmV2Path)", + "ANCM_PATH": "$(TargetDir)\\$(AncmPath)", + "ANCMV2_PATH": "$(TargetDir)\\$(AncmV2Path)", "LAUNCHER_ARGS": "$(TargetPath)", "ASPNETCORE_ENVIRONMENT": "Development", "LAUNCHER_PATH": "$(DotNetPath)", diff --git a/test/WebSites/OutOfProcessWebSite/Properties/launchSettings.json b/test/WebSites/OutOfProcessWebSite/Properties/launchSettings.json index 38ae6c9d32..9c963c0100 100644 --- a/test/WebSites/OutOfProcessWebSite/Properties/launchSettings.json +++ b/test/WebSites/OutOfProcessWebSite/Properties/launchSettings.json @@ -15,8 +15,8 @@ "nativeDebugging": true, "environmentVariables": { "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AncmPath)", - "ANCMV2_PATH": "$(AncmV2Path)", + "ANCM_PATH": "$(TargetDir)\\$(AncmPath)", + "ANCMV2_PATH": "$(TargetDir)\\$(AncmV2Path)", "LAUNCHER_ARGS": "$(TargetPath)", "ASPNETCORE_ENVIRONMENT": "Development", "LAUNCHER_PATH": "$(DotNetPath)", diff --git a/test/WebSites/OverriddenServerWebSite/Properties/launchSettings.json b/test/WebSites/OverriddenServerWebSite/Properties/launchSettings.json index 38ae6c9d32..9c963c0100 100644 --- a/test/WebSites/OverriddenServerWebSite/Properties/launchSettings.json +++ b/test/WebSites/OverriddenServerWebSite/Properties/launchSettings.json @@ -15,8 +15,8 @@ "nativeDebugging": true, "environmentVariables": { "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AncmPath)", - "ANCMV2_PATH": "$(AncmV2Path)", + "ANCM_PATH": "$(TargetDir)\\$(AncmPath)", + "ANCMV2_PATH": "$(TargetDir)\\$(AncmV2Path)", "LAUNCHER_ARGS": "$(TargetPath)", "ASPNETCORE_ENVIRONMENT": "Development", "LAUNCHER_PATH": "$(DotNetPath)", diff --git a/test/WebSites/StartupExceptionWebSite/Properties/launchSettings.json b/test/WebSites/StartupExceptionWebSite/Properties/launchSettings.json index 38ae6c9d32..9c963c0100 100644 --- a/test/WebSites/StartupExceptionWebSite/Properties/launchSettings.json +++ b/test/WebSites/StartupExceptionWebSite/Properties/launchSettings.json @@ -15,8 +15,8 @@ "nativeDebugging": true, "environmentVariables": { "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AncmPath)", - "ANCMV2_PATH": "$(AncmV2Path)", + "ANCM_PATH": "$(TargetDir)\\$(AncmPath)", + "ANCMV2_PATH": "$(TargetDir)\\$(AncmV2Path)", "LAUNCHER_ARGS": "$(TargetPath)", "ASPNETCORE_ENVIRONMENT": "Development", "LAUNCHER_PATH": "$(DotNetPath)", diff --git a/test/WebSites/StressTestWebSite/Properties/launchSettings.json b/test/WebSites/StressTestWebSite/Properties/launchSettings.json index 38ae6c9d32..9c963c0100 100644 --- a/test/WebSites/StressTestWebSite/Properties/launchSettings.json +++ b/test/WebSites/StressTestWebSite/Properties/launchSettings.json @@ -15,8 +15,8 @@ "nativeDebugging": true, "environmentVariables": { "IIS_SITE_PATH": "$(MSBuildThisFileDirectory)", - "ANCM_PATH": "$(AncmPath)", - "ANCMV2_PATH": "$(AncmV2Path)", + "ANCM_PATH": "$(TargetDir)\\$(AncmPath)", + "ANCMV2_PATH": "$(TargetDir)\\$(AncmV2Path)", "LAUNCHER_ARGS": "$(TargetPath)", "ASPNETCORE_ENVIRONMENT": "Development", "LAUNCHER_PATH": "$(DotNetPath)",