Merge pull request #1239 from dotnet-maestro-bot/merge/release/2.2-to-master

[automated] Merge branch 'release/2.2' => 'master'
This commit is contained in:
Pavel Krymets 2018-08-15 13:28:02 -07:00 committed by GitHub
commit 91d809753f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 200 additions and 1139 deletions

View File

@ -132,7 +132,6 @@ SERVER_PROCESS::SetupListenPort(
pEnvironmentVarTable->FindKey(ASPNETCORE_PORT_ENV_STR, &pEntry);
if (pEntry != NULL)
{
pEntry->Dereference();
if (pEntry->QueryValue() != NULL || pEntry->QueryValue()[0] != L'\0')
{
m_dwPort = (DWORD)_wtoi(pEntry->QueryValue());

View File

@ -176,9 +176,6 @@
</system.applicationHost>
<system.webServer>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" hostingModel="[HostingModel]" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
<serverRuntime />
<asp scriptErrorSentToBrowser="true">
@ -255,8 +252,6 @@
<add name="ManagedEngine64" image="%windir%\Microsoft.NET\Framework64\v2.0.50727\webengine.dll" preCondition="integratedMode,runtimeVersionv2.0,bitness64" />
<add name="ManagedEngineV4.0_32bit" image="%windir%\Microsoft.NET\Framework\v4.0.30319\webengine4.dll" preCondition="integratedMode,runtimeVersionv4.0,bitness32" />
<add name="ManagedEngineV4.0_64bit" image="%windir%\Microsoft.NET\Framework64\v4.0.30319\webengine4.dll" preCondition="integratedMode,runtimeVersionv4.0,bitness64" />
<add name="AspNetCoreModule" image="[ANCMPath]" />
<add name="AspNetCoreModuleV2" image="[ANCMV2Path]" />
</globalModules>
<httpCompression directory="%TEMP%\iisexpress\IIS Temporary Compressed Files">
@ -931,11 +926,8 @@
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="managedHandler,runtimeVersionv4.0" />
<add name="ScriptModule-4.0" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="managedHandler,runtimeVersionv4.0" />
<add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler,runtimeVersionv2.0" />
<add name="AspNetCoreModule" />
<add name="AspNetCoreModuleV2"/>
</modules>
<handlers accessPolicy="Read, Script">
<add name="aspNetCore" path="*" verb="*" modules="[AspNetCoreModule]" resourceType="Unspecified" />
<!-- <add name="WebDAV" path="*" verb="PROPFIND,PROPPATCH,MKCOL,PUT,COPY,DELETE,MOVE,LOCK,UNLOCK" modules="WebDAVModule" resourceType="Unspecified" requireAccess="None" /> -->
<add name="AXD-ISAPI-4.0_64bit" path="*.axd" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="PageHandlerFactory-ISAPI-4.0_64bit" path="*.aspx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
@ -1031,4 +1023,4 @@
</handlers>
</system.webServer>
</location>
</configuration>
</configuration>

View File

@ -276,32 +276,13 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
private void ConfigureAppHostConfig(XElement config, string contentRoot, int port)
{
var siteElement = config
.RequiredElement("system.applicationHost")
.RequiredElement("sites")
.RequiredElement("site");
siteElement
.RequiredElement("application")
.RequiredElement("virtualDirectory")
.SetAttributeValue("physicalPath", contentRoot);
siteElement
.RequiredElement("bindings")
.RequiredElement("binding")
.SetAttributeValue("bindingInformation", $"*:{port}:");
var ancmVersion = DeploymentParameters.AncmVersion.ToString();
config
.RequiredElement("system.webServer")
.RequiredElement("globalModules")
.GetOrAdd("add", "name", ancmVersion)
.SetAttributeValue("image", GetAncmLocation(DeploymentParameters.AncmVersion));
ConfigureModuleAndBinding(config, contentRoot, port);
// In IISExpress system.webServer/modules in under location element
config
.RequiredElement("system.webServer")
.RequiredElement("modules")
.GetOrAdd("add", "name", ancmVersion);
.GetOrAdd("add", "name", DeploymentParameters.AncmVersion.ToString());
var pool = config
.RequiredElement("system.applicationHost")

View File

@ -124,5 +124,30 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
.SetAttributeValue("value", handlerSetting.Value);
}
}
protected void ConfigureModuleAndBinding(XElement config, string contentRoot, int port)
{
var siteElement = config
.RequiredElement("system.applicationHost")
.RequiredElement("sites")
.RequiredElement("site");
siteElement
.RequiredElement("application")
.RequiredElement("virtualDirectory")
.SetAttributeValue("physicalPath", contentRoot);
siteElement
.RequiredElement("bindings")
.RequiredElement("binding")
.SetAttributeValue("bindingInformation", $":{port}:localhost");
var ancmVersion = DeploymentParameters.AncmVersion.ToString();
config
.RequiredElement("system.webServer")
.RequiredElement("globalModules")
.GetOrAdd("add", "name", ancmVersion)
.SetAttributeValue("image", GetAncmLocation(DeploymentParameters.AncmVersion));
}
}
}

View File

@ -91,6 +91,8 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
DeploymentParameters.EnvironmentVariables["ASPNETCORE_CONTENTROOT"] = DeploymentParameters.ApplicationPath;
}
RunWebConfigActions(contentRoot);
var testUri = TestUriHelper.BuildTestUri(ServerType.IISExpress, DeploymentParameters.ApplicationBaseUriHint);
// Launch the host process.
@ -260,40 +262,35 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
private void PrepareConfig(string contentRoot, int port)
{
var serverConfig = DeploymentParameters.ServerConfigTemplateContent;;
// Config is required. If not present then fall back to one we carry with us.
if (string.IsNullOrEmpty(DeploymentParameters.ServerConfigTemplateContent))
if (string.IsNullOrEmpty(serverConfig))
{
using (var stream = GetType().Assembly.GetManifestResourceStream("Microsoft.AspNetCore.Server.IntegrationTesting.IIS.Http.config"))
using (var reader = new StreamReader(stream))
{
DeploymentParameters.ServerConfigTemplateContent = reader.ReadToEnd();
serverConfig = reader.ReadToEnd();
}
}
var serverConfig = DeploymentParameters.ServerConfigTemplateContent;
XDocument config = XDocument.Parse(serverConfig);
// Pass on the applicationhost.config to iis express. With this don't need to pass in the /path /port switches as they are in the applicationHost.config
// We take a copy of the original specified applicationHost.Config to prevent modifying the one in the repo.
serverConfig = ModifyANCMPathInConfig(replaceFlag: "[ANCMPath]", AncmVersion.AspNetCoreModule, serverConfig);
serverConfig = ModifyANCMPathInConfig(replaceFlag: "[ANCMV2Path]", AncmVersion.AspNetCoreModuleV2, serverConfig);
serverConfig = ReplacePlaceholder(serverConfig, "[PORT]", port.ToString(CultureInfo.InvariantCulture));
serverConfig = ReplacePlaceholder(serverConfig, "[ApplicationPhysicalPath]", contentRoot);
config.Root
.RequiredElement("location")
.RequiredElement("system.webServer")
.RequiredElement("modules")
.GetOrAdd("add", "name", DeploymentParameters.AncmVersion.ToString());
if (DeploymentParameters.PublishApplicationBeforeDeployment)
{
serverConfig = RemoveRedundantElements(serverConfig);
}
else
ConfigureModuleAndBinding(config.Root, contentRoot, port);
if (!DeploymentParameters.PublishApplicationBeforeDeployment)
{
// The elements normally in the web.config are in the applicationhost.config for unpublished apps.
serverConfig = ReplacePlaceholder(serverConfig, "[HostingModel]", DeploymentParameters.HostingModel.ToString());
serverConfig = ReplacePlaceholder(serverConfig, "[AspNetCoreModule]", DeploymentParameters.AncmVersion.ToString());
AddAspNetCoreElement(config.Root);
}
RunWebConfigActions(contentRoot);
var config = XDocument.Parse(serverConfig);
RunServerConfigActions(config.Root, contentRoot);
serverConfig = config.ToString();
@ -303,14 +300,31 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
File.WriteAllText(DeploymentParameters.ServerConfigLocation, serverConfig);
}
private string ReplacePlaceholder(string content, string field, string value)
private void AddAspNetCoreElement(XElement config)
{
if (content.Contains(field))
{
content = content.Replace(field, value);
Logger.LogDebug("Writing {field} '{value}' to config", field, value);
}
return content;
var aspNetCore = config
.RequiredElement("system.webServer")
.GetOrAdd("aspNetCore");
aspNetCore.SetAttributeValue("hostingModel", DeploymentParameters.HostingModel.ToString());
aspNetCore.SetAttributeValue("arguments", "%LAUNCHER_ARGS%");
aspNetCore.SetAttributeValue("processPath", "%LAUNCHER_PATH%");
var handlers = config
.RequiredElement("location")
.RequiredElement("system.webServer")
.RequiredElement("handlers");
var aspNetCoreHandler = handlers
.GetOrAdd("add", "name", "aspNetCore");
aspNetCoreHandler.SetAttributeValue("path", "*");
aspNetCoreHandler.SetAttributeValue("verb", "*");
aspNetCoreHandler.SetAttributeValue("modules", DeploymentParameters.AncmVersion.ToString());
aspNetCoreHandler.SetAttributeValue("resourceType", "Unspecified");
// Make aspNetCore handler first
aspNetCoreHandler.Remove();
handlers.AddFirst(aspNetCoreHandler);
}
protected override IEnumerable<Action<XElement, string>> GetWebConfigActions()
@ -347,18 +361,6 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
}
}
private string ModifyANCMPathInConfig(string replaceFlag, AncmVersion version, string serverConfig)
{
if (serverConfig.Contains(replaceFlag))
{
var ancmFile = GetAncmLocation(version);
Logger.LogDebug($"Writing '{replaceFlag}' '{ancmFile}' to config");
return serverConfig.Replace(replaceFlag, ancmFile);
}
return serverConfig;
}
private string GetIISExpressPath()
{
var programFiles = "Program Files";
@ -477,21 +479,5 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting.IIS
throw new InvalidOperationException($"iisexpress Process {hostProcess.Id} crashed before shutdown was triggered.");
}
}
// These elements are duplicated in the web.config if you publish. Remove them from the host.config.
private string RemoveRedundantElements(string serverConfig)
{
var hostConfig = XDocument.Parse(serverConfig);
var coreElement = hostConfig.Descendants("aspNetCore").FirstOrDefault();
coreElement?.Remove();
var handlersElement = hostConfig.Descendants("handlers").First();
var handlerElement = handlersElement.Descendants("add")
.Where(x => x.Attribute("name").Value == "aspNetCore").FirstOrDefault();
handlerElement?.Remove();
return hostConfig.ToString();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
StopServer();
EventLogHelpers.VerifyEventLogEvent(TestSink, "Application '.+' started the coreclr in-process successfully.");
EventLogHelpers.VerifyEventLogEvent(deploymentResult, TestSink, "Application '.+' started the coreclr in-process successfully.");
}
[ConditionalFact]
@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
StopServer();
EventLogHelpers.VerifyEventLogEvent(TestSink, "Application '.+' has shutdown.");
EventLogHelpers.VerifyEventLogEvent(deploymentResult, TestSink, "Application '.+' has shutdown.");
}
}
}

View File

@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
Assert.Equal(200, (int)result1.StatusCode);
Assert.Equal(500, (int)result2.StatusCode);
StopServer();
EventLogHelpers.VerifyEventLogEvent(TestSink, "Only one inprocess application is allowed per IIS application pool");
EventLogHelpers.VerifyEventLogEvent(result, TestSink, "Only one inprocess application is allowed per IIS application pool");
}
[ConditionalTheory]
@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
Assert.Equal(200, (int)result1.StatusCode);
Assert.Equal(500, (int)result2.StatusCode);
StopServer();
EventLogHelpers.VerifyEventLogEvent(TestSink, "Mixed hosting model is not supported.");
EventLogHelpers.VerifyEventLogEvent(result, TestSink, "Mixed hosting model is not supported.");
}
private void SetHostingModel(string directory, HostingModel model)

View File

@ -0,0 +1,89 @@
// 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.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using Xunit;
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{
[Collection(PublishedSitesCollection.Name)]
public class AspNetCorePortTests : IISFunctionalTestBase
{
private static readonly Random _random = new Random();
private readonly PublishedSitesFixture _fixture;
public AspNetCorePortTests(PublishedSitesFixture fixture)
{
_fixture = fixture;
}
public static TestMatrix TestVariants
=> TestMatrix.ForServers(DeployerSelector.ServerType)
.WithTfms(Tfm.NetCoreApp22)
.WithApplicationTypes(ApplicationType.Portable)
.WithAllAncmVersions();
[ConditionalTheory]
[MemberData(nameof(TestVariants))]
public async Task EnvVarInWebConfig(TestVariant variant)
{
// Must publish to set env vars in web.config
var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant, publish: true);
var port = GetUnusedRandomPort();
deploymentParameters.WebConfigBasedEnvironmentVariables["ASPNETCORE_PORT"] = port.ToString();
var deploymentResult = await DeployAsync(deploymentParameters);
var response = await deploymentResult.HttpClient.GetAsync("/ServerAddresses");
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(port, new Uri(responseText).Port);
}
private static int GetUnusedRandomPort()
{
// Port range allowed by ANCM config
const int minPort = 1025;
const int maxPort = 48000;
// Large number of retries to prevent test failures due to port collisions, but not infinite
// to prevent infinite loop in case Bind() fails repeatedly for some other reason.
const int retries = 100;
List<Exception> exceptions = null;
for (var i = 0; i < retries; i++)
{
var port = _random.Next(minPort, maxPort);
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
try
{
socket.Bind(new IPEndPoint(IPAddress.Loopback, port));
return port;
}
catch (Exception e)
{
// Bind failed, most likely because port is in use. Save exception and retry.
if (exceptions == null)
{
exceptions = new List<Exception>(retries);
}
exceptions.Add(e);
}
}
}
throw new AggregateException($"Unable to find unused random port after {retries} retries.", exceptions);
}
}
}

View File

@ -2,9 +2,12 @@
// 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.Linq;
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;
@ -30,9 +33,16 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[MemberData(nameof(TestVariants))]
public async Task HelloWorld(TestVariant variant)
{
// The default in hosting sets windows auth to true.
// Set it to the IISExpress.config file
var deploymentParameters = _fixture.GetBaseDeploymentParameters(variant);
deploymentParameters.ServerConfigActionList.Add(
(element, _) => {
element
.RequiredElement("system.webServer")
.RequiredElement("security")
.RequiredElement("authentication")
.Element("windowsAuthentication")
?.SetAttributeValue("enabled", "false");
});
var deploymentResult = await DeployAsync(deploymentParameters);
@ -63,6 +73,9 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
$"WebRootPath {deploymentResult.ContentRoot}\\wwwroot" + Environment.NewLine +
$"CurrentDirectory {deploymentResult.ContentRoot}",
await deploymentResult.HttpClient.GetStringAsync("/HostingEnvironment"));
var expectedDll = variant.AncmVersion == AncmVersion.AspNetCoreModule ? "aspnetcore.dll" : "aspnetcorev2.dll";
Assert.Contains(deploymentResult.HostProcess.Modules.OfType<ProcessModule>(), m=> m.FileName.Contains(expectedDll));
}
}
}

View File

@ -49,7 +49,9 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
publisher,
new DeploymentParameters(publisher.ApplicationPath, DeployerSelector.ServerType, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64)
{
HostingModel = hostingModel
HostingModel = hostingModel,
TargetFramework = "netcoreapp2.2",
AncmVersion = AncmVersion.AspNetCoreModuleV2
},
publish);
}
@ -60,10 +62,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{
ApplicationPublisher = publisher,
ApplicationPath = publisher.ApplicationPath,
TargetFramework = Tfm.NetCoreApp22,
ApplicationType = ApplicationType.Portable,
AncmVersion = AncmVersion.AspNetCoreModuleV2,
PublishApplicationBeforeDeployment = publish,
PublishApplicationBeforeDeployment = publish
};
}
}

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
using Microsoft.Extensions.Logging.Testing;
using Xunit;
@ -9,8 +10,10 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{
public class EventLogHelpers
{
public static void VerifyEventLogEvent(ITestSink testSink, string expectedRegexMatchString)
public static void VerifyEventLogEvent(IISDeploymentResult deploymentResult, ITestSink testSink, string expectedRegexMatchString)
{
Assert.True(deploymentResult.HostProcess.HasExited);
var eventLogRegex = new Regex($"Event Log: {expectedRegexMatchString}");
int count = 0;

View File

@ -28,11 +28,6 @@ namespace Microsoft.AspNetCore.Server.IntegrationTesting
parameters.EnvironmentVariables[DebugEnvironmentVariable] = "console";
}
if (parameters.ServerType == ServerType.IISExpress)
{
parameters.ServerConfigTemplateContent = parameters.ServerConfigTemplateContent ?? File.ReadAllText("IISExpress.config");
}
if (parameters.ApplicationPublisher == null)
{
throw new InvalidOperationException("All tests should use ApplicationPublisher");

View File

@ -55,7 +55,9 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
EventLogHelpers.VerifyEventLogEvent(TestSink, @"Invalid or unknown processPath provided in web\.config: processPath = '.+', ErrorCode = '0x80070002'\.");
StopServer();
EventLogHelpers.VerifyEventLogEvent(deploymentResult, TestSink, @"Invalid or unknown processPath provided in web\.config: processPath = '.+', ErrorCode = '0x80070002'\.");
}
[ConditionalFact]
@ -158,7 +160,9 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
EventLogHelpers.VerifyEventLogEvent(TestSink, "Unknown hosting model 'bogus'. Please specify either hostingModel=\"inprocess\" or hostingModel=\"outofprocess\" in the web.config file.");
StopServer();
EventLogHelpers.VerifyEventLogEvent(deploymentResult, TestSink, "Unknown hosting model 'bogus'. Please specify either hostingModel=\"inprocess\" or hostingModel=\"outofprocess\" in the web.config file.");
}
}
}

View File

@ -11,6 +11,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.IISIntegration.FunctionalTests;
@ -22,9 +23,13 @@ namespace TestSites
{
public class Startup
{
private IServerAddressesFeature _serverAddresses;
public void Configure(IApplicationBuilder app)
{
TestStartup.Register(app, this);
_serverAddresses = app.ServerFeatures.Get<IServerAddressesFeature>();
}
public Task Path(HttpContext ctx) => ctx.Response.WriteAsync(ctx.Request.Path.Value);
@ -120,5 +125,10 @@ namespace TestSites
{
await context.Response.WriteAsync(Process.GetCurrentProcess().Id.ToString());
}
private async Task ServerAddresses(HttpContext context)
{
await context.Response.WriteAsync(string.Join(",", _serverAddresses.Addresses));
}
}
}