Cleanup functional tests (#851)

This commit is contained in:
Pavel Krymets 2018-05-18 15:09:50 -07:00 committed by GitHub
parent 8932383d67
commit 06591131cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 586 additions and 3777 deletions

View File

@ -5,38 +5,38 @@
<PropertyGroup Label="Package Versions"> <PropertyGroup Label="Package Versions">
<BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion> <BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion>
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview1-17055</InternalAspNetCoreSdkPackageVersion> <InternalAspNetCoreSdkPackageVersion>2.2.0-preview1-17055</InternalAspNetCoreSdkPackageVersion>
<MicrosoftAspNetCoreAllPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreAllPackageVersion> <MicrosoftAspNetCoreAllPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreAllPackageVersion>
<MicrosoftAspNetCoreAuthenticationCorePackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreAuthenticationCorePackageVersion> <MicrosoftAspNetCoreAuthenticationCorePackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreAuthenticationCorePackageVersion>
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion> <MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreHostingAbstractionsPackageVersion> <MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
<MicrosoftAspNetCoreHostingPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreHostingPackageVersion> <MicrosoftAspNetCoreHostingPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreHostingPackageVersion>
<MicrosoftAspNetCoreHttpExtensionsPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreHttpExtensionsPackageVersion> <MicrosoftAspNetCoreHttpExtensionsPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreHttpExtensionsPackageVersion>
<MicrosoftAspNetCoreHttpOverridesPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreHttpOverridesPackageVersion> <MicrosoftAspNetCoreHttpOverridesPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreHttpOverridesPackageVersion>
<MicrosoftAspNetCoreHttpPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreHttpPackageVersion> <MicrosoftAspNetCoreHttpPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreHttpPackageVersion>
<MicrosoftAspNetCoreHttpSysSourcesPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreHttpSysSourcesPackageVersion> <MicrosoftAspNetCoreHttpSysSourcesPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreHttpSysSourcesPackageVersion>
<MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>0.6.0-a-preview1-inttesting-17031</MicrosoftAspNetCoreServerIntegrationTestingPackageVersion> <MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>0.6.0-preview1-34230</MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreServerKestrelPackageVersion> <MicrosoftAspNetCoreServerKestrelPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreServerKestrelPackageVersion>
<MicrosoftAspNetCoreTestHostPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreTestHostPackageVersion> <MicrosoftAspNetCoreTestHostPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreTestHostPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreTestingPackageVersion> <MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreWebUtilitiesPackageVersion> <MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
<MicrosoftBuildFrameworkPackageVersion>15.6.82</MicrosoftBuildFrameworkPackageVersion> <MicrosoftBuildFrameworkPackageVersion>15.6.82</MicrosoftBuildFrameworkPackageVersion>
<MicrosoftBuildUtilitiesCorePackageVersion>15.6.82</MicrosoftBuildUtilitiesCorePackageVersion> <MicrosoftBuildUtilitiesCorePackageVersion>15.6.82</MicrosoftBuildUtilitiesCorePackageVersion>
<MicrosoftExtensionsBuffersMemoryPoolSourcesPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsBuffersMemoryPoolSourcesPackageVersion> <MicrosoftExtensionsBuffersMemoryPoolSourcesPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsBuffersMemoryPoolSourcesPackageVersion>
<MicrosoftExtensionsBuffersSourcesPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsBuffersSourcesPackageVersion> <MicrosoftExtensionsBuffersSourcesPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsBuffersSourcesPackageVersion>
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion> <MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion> <MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsConfigurationJsonPackageVersion> <MicrosoftExtensionsConfigurationJsonPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsLoggingAbstractionsPackageVersion> <MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsLoggingConsolePackageVersion> <MicrosoftExtensionsLoggingConsolePackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsLoggingDebugPackageVersion> <MicrosoftExtensionsLoggingDebugPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsLoggingPackageVersion> <MicrosoftExtensionsLoggingPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTestingPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsLoggingTestingPackageVersion> <MicrosoftExtensionsLoggingTestingPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsLoggingTestingPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsOptionsPackageVersion> <MicrosoftExtensionsOptionsPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsSecurityHelperSourcesPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsSecurityHelperSourcesPackageVersion> <MicrosoftExtensionsSecurityHelperSourcesPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsSecurityHelperSourcesPackageVersion>
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion> <MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
<MicrosoftNETCoreApp21PackageVersion>2.1.0-rc1</MicrosoftNETCoreApp21PackageVersion> <MicrosoftNETCoreApp21PackageVersion>2.1.0-rc1</MicrosoftNETCoreApp21PackageVersion>
<MicrosoftNETCoreApp22PackageVersion>2.2.0-preview1-26509-06</MicrosoftNETCoreApp22PackageVersion> <MicrosoftNETCoreApp22PackageVersion>2.2.0-preview1-26509-06</MicrosoftNETCoreApp22PackageVersion>
<MicrosoftNetHttpHeadersPackageVersion>2.2.0-preview1-34217</MicrosoftNetHttpHeadersPackageVersion> <MicrosoftNetHttpHeadersPackageVersion>2.2.0-preview1-34230</MicrosoftNetHttpHeadersPackageVersion>
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion> <MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion> <NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
<SystemBuffersPackageVersion>4.6.0-preview1-26508-04</SystemBuffersPackageVersion> <SystemBuffersPackageVersion>4.6.0-preview1-26508-04</SystemBuffersPackageVersion>

File diff suppressed because it is too large Load Diff

View File

@ -2,216 +2,116 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.IO; using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml.Linq;
using IISIntegration.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.CommandLineUtils; using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{ {
[SkipIfIISExpressSchemaMissingInProcess] [SkipIfIISExpressSchemaMissingInProcess]
public class StartupTests : LoggedTest public class StartupTests : IISFunctionalTestBase
{ {
public StartupTests(ITestOutputHelper output) : base(output) public StartupTests(ITestOutputHelper output) : base(output)
{ {
} }
[Fact] [Fact]
public async Task ExpandEnvironmentVariableInWebConfig() public async Task ExpandEnvironmentVariableInWebConfig()
{ {
var dotnetLocation = DotNetMuxer.MuxerPathOrDefault(); var dotnetLocation = DotNetMuxer.MuxerPathOrDefault();
using (StartLog(out var loggerFactory)) var deploymentParameters = GetBaseDeploymentParameters();
{
var logger = loggerFactory.CreateLogger("HelloWorldTest");
var deploymentParameters = GetBaseDeploymentParameters(); // Point to dotnet installed in user profile.
deploymentParameters.EnvironmentVariables["DotnetPath"] = dotnetLocation;
// Point to dotnet installed in user profile. var deploymentResult = await DeployAsync(deploymentParameters);
deploymentParameters.EnvironmentVariables["DotnetPath"] = dotnetLocation;
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%");
{
var deploymentResult = await deployer.DeployAsync();
Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%"); var response = await deploymentResult.RetryingHttpClient.GetAsync("HelloWorld");
// Request to base address and check if various parts of the body are rendered & measure the cold startup time. var responseText = await response.Content.ReadAsStringAsync();
var response = await RetryHelper.RetryRequest(() => Assert.Equal("Hello World", responseText);
{
return deploymentResult.HttpClient.GetAsync("HelloWorld");
}, logger, deploymentResult.HostShutdownToken, retryCount: 30);
var responseText = await response.Content.ReadAsStringAsync();
try
{
Assert.Equal("Hello World", responseText);
}
catch (XunitException)
{
logger.LogWarning(response.ToString());
logger.LogWarning(responseText);
throw;
}
}
}
} }
[Fact] [Fact]
public async Task InvalidProcessPath_ExpectServerError() public async Task InvalidProcessPath_ExpectServerError()
{ {
var dotnetLocation = "bogus"; var dotnetLocation = "bogus";
using (StartLog(out var loggerFactory))
{
var logger = loggerFactory.CreateLogger("HelloWorldTest");
var deploymentParameters = GetBaseDeploymentParameters();
// Point to dotnet installed in user profile. var deploymentParameters = GetBaseDeploymentParameters();
deploymentParameters.EnvironmentVariables["DotnetPath"] = Environment.ExpandEnvironmentVariables(dotnetLocation); // Path to dotnet. // Point to dotnet installed in user profile.
deploymentParameters.EnvironmentVariables["DotnetPath"] = Environment.ExpandEnvironmentVariables(dotnetLocation); // Path to dotnet.
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) var deploymentResult = await DeployAsync(deploymentParameters);
{
var deploymentResult = await deployer.DeployAsync();
Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%"); ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%");
// Request to base address and check if various parts of the body are rendered & measure the cold startup time. // Request to base address and check if various parts of the body are rendered & measure the cold startup time.
var response = await RetryHelper.RetryRequest(() => var response = await deploymentResult.RetryingHttpClient.GetAsync("HelloWorld");
{
return deploymentResult.HttpClient.GetAsync("HelloWorld");
}, logger, deploymentResult.HostShutdownToken, retryCount: 30);
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
}
}
} }
[Fact]
public async Task StandaloneApplication_ExpectCorrectPublish() public static TestMatrix TestVariants
=> TestMatrix.ForServers(ServerType.IISExpress)
.WithTfms(Tfm.NetCoreApp22)
.WithAllApplicationTypes()
.WithAncmV2InProcess();
[ConditionalTheory]
[MemberData(nameof(TestVariants))]
public async Task HelloWorld(TestVariant variant)
{ {
using (StartLog(out var loggerFactory)) var deploymentParameters = new DeploymentParameters(variant)
{ {
var logger = loggerFactory.CreateLogger("HelloWorldTest"); ApplicationPath = Helpers.GetInProcessTestSitesPath(),
};
var deploymentParameters = GetBaseDeploymentParameters(); var deploymentResult = await DeployAsync(deploymentParameters);
deploymentParameters.ApplicationType = ApplicationType.Standalone;
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) var response = await deploymentResult.RetryingHttpClient.GetAsync("/HelloWorld");
{ var responseText = await response.Content.ReadAsStringAsync();
var deploymentResult = await deployer.DeployAsync();
// Request to base address and check if various parts of the body are rendered & measure the cold startup time. Assert.Equal("Hello World", responseText);
var response = await RetryHelper.RetryRequest(() =>
{
return deploymentResult.HttpClient.GetAsync("HelloWorld");
}, logger, deploymentResult.HostShutdownToken, retryCount: 30);
var responseText = await response.Content.ReadAsStringAsync();
try
{
Assert.Equal("Hello World", responseText);
}
catch (XunitException)
{
logger.LogWarning(response.ToString());
logger.LogWarning(responseText);
throw;
}
}
}
}
[Fact]
public async Task StandaloneApplication_AbsolutePathToExe_ExpectCorrectPublish()
{
using (StartLog(out var loggerFactory))
{
var logger = loggerFactory.CreateLogger("HelloWorldTest");
var deploymentParameters = GetBaseDeploymentParameters();
deploymentParameters.ApplicationType = ApplicationType.Standalone;
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
{
var deploymentResult = await deployer.DeployAsync();
Helpers.ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", $"{deploymentResult.ContentRoot}\\InProcessWebSite.exe");
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
var response = await RetryHelper.RetryRequest(() =>
{
return deploymentResult.HttpClient.GetAsync("HelloWorld");
}, logger, deploymentResult.HostShutdownToken, retryCount: 30);
var responseText = await response.Content.ReadAsStringAsync();
try
{
Assert.Equal("Hello World", responseText);
}
catch (XunitException)
{
logger.LogWarning(response.ToString());
logger.LogWarning(responseText);
throw;
}
}
}
} }
[Fact] [Fact]
public async Task DetectsOveriddenServer() public async Task DetectsOveriddenServer()
{ {
var testSink = new TestSink(); var deploymentResult = await DeployAsync(GetBaseDeploymentParameters("OverriddenServerWebSite"));
using (StartLog(out var loggerFactory)) var response = await deploymentResult.HttpClient.GetAsync("/");
{ Assert.False(response.IsSuccessStatusCode);
var testLoggerFactory = new TestLoggerFactory(testSink, true); Assert.Contains(TestSink.Writes, context => context.Message.Contains("Application is running inside IIS process but is not configured to use IIS server"));
loggerFactory.AddProvider(new TestLoggerProvider(testLoggerFactory));
using (var deployer = ApplicationDeployerFactory.Create(GetBaseDeploymentParameters("OverriddenServerWebSite"), loggerFactory))
{
var deploymentResult = await deployer.DeployAsync();
var response = await deploymentResult.HttpClient.GetAsync("/");
Assert.False(response.IsSuccessStatusCode);
}
}
Assert.Contains(testSink.Writes, context => context.State.ToString().Contains("Application is running inside IIS process but is not configured to use IIS server"));
} }
private DeploymentParameters GetBaseDeploymentParameters(string site = null) private DeploymentParameters GetBaseDeploymentParameters(string site = null)
{ {
return new DeploymentParameters(Helpers.GetTestWebSitePath(site ?? "InProcessWebSite"), ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64) return new DeploymentParameters(Helpers.GetTestWebSitePath(site ?? "InProcessWebSite"), ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64)
{ {
ServerConfigTemplateContent = File.ReadAllText("AppHostConfig/Http.config"),
SiteName = "HttpTestSite", // This is configured in the Http.config
TargetFramework = Tfm.NetCoreApp22, TargetFramework = Tfm.NetCoreApp22,
ApplicationType = ApplicationType.Portable, ApplicationType = ApplicationType.Portable,
AncmVersion = AncmVersion.AspNetCoreModuleV2 AncmVersion = AncmVersion.AspNetCoreModuleV2
}; };
} }
private class TestLoggerProvider : ILoggerProvider private static void ModifyAspNetCoreSectionInWebConfig(IISDeploymentResult deploymentResult, string key, string value)
{ {
private readonly TestLoggerFactory _loggerFactory; // modify the web.config after publish
var root = deploymentResult.DeploymentResult.ContentRoot;
public TestLoggerProvider(TestLoggerFactory loggerFactory) var webConfigFile = $"{root}/web.config";
{ var config = XDocument.Load(webConfigFile);
_loggerFactory = loggerFactory; var element = config.Descendants("aspNetCore").FirstOrDefault();
} element.SetAttributeValue(key, value);
config.Save(webConfigFile);
public void Dispose()
{
}
public ILogger CreateLogger(string categoryName)
{
return _loggerFactory.CreateLogger(categoryName);
}
} }
} }
} }

View File

@ -1,21 +1,18 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using IISIntegration.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit; using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{ {
public class HelloWorldTests : LoggedTest public class HelloWorldTests : IISFunctionalTestBase
{ {
public HelloWorldTests(ITestOutputHelper output) : base(output) public HelloWorldTests(ITestOutputHelper output = null) : base(output)
{ {
} }
@ -29,61 +26,36 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[MemberData(nameof(TestVariants))] [MemberData(nameof(TestVariants))]
public async Task HelloWorld(TestVariant variant) public async Task HelloWorld(TestVariant variant)
{ {
var testName = $"HelloWorld_{variant.Tfm}"; var deploymentParameters = new DeploymentParameters(variant)
using (StartLog(out var loggerFactory, testName))
{ {
var logger = loggerFactory.CreateLogger("HelloWorldTest"); ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(),
};
var deploymentParameters = new DeploymentParameters(variant) var deploymentResult = await DeployAsync(deploymentParameters);
{
ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(),
EnvironmentName = "HelloWorld", // Will pick the Start class named 'StartupHelloWorld',
ServerConfigTemplateContent = File.ReadAllText("AppHostConfig/Http.config"),
SiteName = "HttpTestSite", // This is configured in the Http.config
};
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) var response = await deploymentResult.RetryingHttpClient.GetAsync("/HelloWorld");
{ var responseText = await response.Content.ReadAsStringAsync();
var deploymentResult = await deployer.DeployAsync();
// Request to base address and check if various parts of the body are rendered & measure the cold startup time. Assert.Equal("Hello World", responseText);
var response = await RetryHelper.RetryRequest(() =>
{
return deploymentResult.HttpClient.GetAsync(string.Empty);
}, logger, deploymentResult.HostShutdownToken, retryCount: 30);
var responseText = await response.Content.ReadAsStringAsync(); response = await deploymentResult.HttpClient.GetAsync("/Path/%3F%3F?query");
try responseText = await response.Content.ReadAsStringAsync();
{ Assert.Equal("/??", responseText);
Assert.Equal("Hello World", responseText);
response = await deploymentResult.HttpClient.GetAsync("/Path%3F%3F?query"); response = await deploymentResult.HttpClient.GetAsync("/Query/%3FPath?query?");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("/Path??", responseText); Assert.Equal("?query?", responseText);
response = await deploymentResult.HttpClient.GetAsync("/Query%3FPath?query?"); response = await deploymentResult.HttpClient.GetAsync("/BodyLimit");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("?query?", responseText); Assert.Equal("null", responseText);
response = await deploymentResult.HttpClient.GetAsync("/BodyLimit"); response = await deploymentResult.HttpClient.GetAsync("/Auth");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("null", responseText);
response = await deploymentResult.HttpClient.GetAsync("/Auth"); // We adapted the Http.config file to be used for inprocess too. We specify WindowsAuth is enabled
responseText = await response.Content.ReadAsStringAsync(); // We now expect that windows auth is enabled rather than disabled.
Assert.True("backcompat;Windows".Equals(responseText) || "latest;Windows".Equals(responseText), "Auth");
// We adapted the Http.config file to be used for inprocess too. We specify WindowsAuth is enabled
// We now expect that windows auth is enabled rather than disabled.
Assert.True("backcompat;Windows".Equals(responseText) || "latest;Windows".Equals(responseText), "Auth");
}
catch (XunitException)
{
logger.LogWarning(response.ToString());
logger.LogWarning(responseText);
throw;
}
}
}
} }
} }
} }

View File

@ -1,25 +1,21 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks; using System.Threading.Tasks;
using IISIntegration.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit; using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{ {
// IIS Express preregisteres 44300-44399 ports with SSL bindings. // IIS Express preregisteres 44300-44399 ports with SSL bindings.
// So these tests always have to use ports in this range, and we can't rely on OS-allocated ports without a whole lot of ceremony around // So these tests always have to use ports in this range, and we can't rely on OS-allocated ports without a whole lot of ceremony around
// creating self-signed certificates and registering SSL bindings with HTTP.sys // creating self-signed certificates and registering SSL bindings with HTTP.sys
public class HttpsTest : LoggedTest public class HttpsTest : IISFunctionalTestBase
{ {
public HttpsTest(ITestOutputHelper output) : base(output) public HttpsTest(ITestOutputHelper output) : base(output)
{ {
@ -34,49 +30,23 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[MemberData(nameof(TestVariants))] [MemberData(nameof(TestVariants))]
public async Task HttpsHelloWorld(TestVariant variant) public async Task HttpsHelloWorld(TestVariant variant)
{ {
var applicationBaseUrl = $"https://localhost:44394/"; var deploymentParameters = new DeploymentParameters(variant)
var testName = $"HttpsHelloWorld_{variant.Tfm}";
using (StartLog(out var loggerFactory, testName))
{ {
var logger = loggerFactory.CreateLogger("HttpsHelloWorldTest"); ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(),
ApplicationBaseUriHint = "https://localhost:44394/",
ServerConfigTemplateContent = GetHttpsServerConfig()
};
var deploymentParameters = new DeploymentParameters(variant) var deploymentResult = await DeployAsync(deploymentParameters);
{
ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(),
ApplicationBaseUriHint = applicationBaseUrl,
EnvironmentName = "HttpsHelloWorld", // Will pick the Start class named 'StartupHttpsHelloWorld',
ServerConfigTemplateContent = File.ReadAllText("AppHostConfig/Https.config"),
SiteName = "HttpsTestSite", // This is configured in the Https.config
};
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) var handler = new HttpClientHandler
{ {
var deploymentResult = await deployer.DeployAsync(); ServerCertificateCustomValidationCallback = (a, b, c, d) => true
};
var handler = new HttpClientHandler(); var client = deploymentResult.CreateRetryClient(handler);
handler.ServerCertificateCustomValidationCallback = (a, b, c, d) => true; var response = await client.GetAsync("HttpsHelloWorld");
var httpClient = deploymentResult.CreateHttpClient(handler); var responseText = await response.Content.ReadAsStringAsync();
httpClient.Timeout = TimeSpan.FromSeconds(5); Assert.Equal("Scheme:https; Original:http", responseText);
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
var response = await RetryHelper.RetryRequest(() =>
{
return httpClient.GetAsync(string.Empty);
}, logger, deploymentResult.HostShutdownToken, retryCount: 30);
var responseText = await response.Content.ReadAsStringAsync();
try
{
Assert.Equal("Scheme:https; Original:http", responseText);
}
catch (XunitException)
{
logger.LogWarning(response.ToString());
logger.LogWarning(responseText);
throw;
}
}
}
} }
[ConditionalTheory] [ConditionalTheory]
@ -97,60 +67,41 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
private async Task HttpsHelloWorldCerts(TestVariant variant, int port, bool sendClientCert) private async Task HttpsHelloWorldCerts(TestVariant variant, int port, bool sendClientCert)
{ {
var applicationBaseUrl = $"https://localhost:{port}/"; var deploymentParameters = new DeploymentParameters(variant)
var testName = $"HttpsHelloWorldCerts_{variant.Tfm}_{sendClientCert}";
using (StartLog(out var loggerFactory, testName))
{ {
var logger = loggerFactory.CreateLogger("HttpsHelloWorldTest"); ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(),
ApplicationBaseUriHint = $"https://localhost:{port}/",
ServerConfigTemplateContent = GetHttpsServerConfig()
};
var deploymentParameters = new DeploymentParameters(variant) var deploymentResult = await DeployAsync(deploymentParameters);
{
ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(),
ApplicationBaseUriHint = applicationBaseUrl,
EnvironmentName = "HttpsHelloWorld", // Will pick the Start class named 'StartupHttpsHelloWorld',
ServerConfigTemplateContent = File.ReadAllText("AppHostConfig/Https.config"),
SiteName = "HttpsTestSite", // This is configured in the Https.config
};
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) var handler = new HttpClientHandler
{ {
var deploymentResult = await deployer.DeployAsync(); ServerCertificateCustomValidationCallback = (a, b, c, d) => true,
var handler = new HttpClientHandler(); ClientCertificateOptions = ClientCertificateOption.Manual
handler.ServerCertificateCustomValidationCallback = (a, b, c, d) => true; };
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
if (sendClientCert)
{
X509Certificate2 clientCert = FindClientCert();
Assert.NotNull(clientCert);
handler.ClientCertificates.Add(clientCert);
}
var httpClient = deploymentResult.CreateHttpClient(handler);
// Request to base address and check if various parts of the body are rendered & measure the cold startup time. if (sendClientCert)
var response = await RetryHelper.RetryRequest(() => {
{ X509Certificate2 clientCert = FindClientCert();
return httpClient.GetAsync("checkclientcert"); Assert.NotNull(clientCert);
}, logger, deploymentResult.HostShutdownToken); handler.ClientCertificates.Add(clientCert);
}
var responseText = await response.Content.ReadAsStringAsync(); var client = deploymentResult.CreateRetryClient(handler);
try
{ // Request to base address and check if various parts of the body are rendered & measure the cold startup time.
if (sendClientCert) var response = await client.GetAsync("checkclientcert");
{
Assert.Equal("Scheme:https; Original:http; has cert? True", responseText); var responseText = await response.Content.ReadAsStringAsync();
} if (sendClientCert)
else {
{ Assert.Equal("Scheme:https; Original:http; has cert? True", responseText);
Assert.Equal("Scheme:https; Original:http; has cert? False", responseText); }
} else
} {
catch (XunitException) Assert.Equal("Scheme:https; Original:http; has cert? False", responseText);
{
logger.LogWarning(response.ToString());
logger.LogWarning(responseText);
throw;
}
}
} }
} }

View File

@ -1,22 +1,19 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using IISIntegration.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit; using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{ {
public class NtlmAuthenticationTests : LoggedTest public class NtlmAuthenticationTests : IISFunctionalTestBase
{ {
public NtlmAuthenticationTests(ITestOutputHelper output) : base(output) public NtlmAuthenticationTests(ITestOutputHelper output) : base(output)
{ {
@ -31,81 +28,51 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[MemberData(nameof(TestVariants))] [MemberData(nameof(TestVariants))]
public async Task NtlmAuthentication(TestVariant variant) public async Task NtlmAuthentication(TestVariant variant)
{ {
var testName = $"NtlmAuthentication_{variant.Tfm}_{variant.AncmVersion}"; var deploymentParameters = new DeploymentParameters(variant)
using (StartLog(out var loggerFactory, testName))
{ {
var logger = loggerFactory.CreateLogger("NtlmAuthenticationTest"); ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(),
ApplicationBaseUriHint = "http://localhost:5052"
};
var deploymentParameters = new DeploymentParameters(variant) var result = await DeployAsync(deploymentParameters);
{ var response = await result.RetryingHttpClient.GetAsync("/HelloWorld");
ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(),
ApplicationBaseUriHint = $"http://localhost:5052",
EnvironmentName = "NtlmAuthentication", // Will pick the Start class named 'StartupNtlmAuthentication'
ServerConfigTemplateContent = File.ReadAllText("AppHostConfig/NtlmAuthentation.config"),
SiteName = "NtlmAuthenticationTestSite", // This is configured in the NtlmAuthentication.config
};
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory)) var responseText = await response.Content.ReadAsStringAsync();
{ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var deploymentResult = await deployer.DeployAsync(); Assert.Equal("Hello World", responseText);
var httpClient = deploymentResult.HttpClient;
httpClient.Timeout = TimeSpan.FromSeconds(5);
// Request to base address and check if various parts of the body are rendered & measure the cold startup time. var httpClient = result.HttpClient;
var response = await RetryHelper.RetryRequest(() => response = await httpClient.GetAsync("/Anonymous");
{ responseText = await response.Content.ReadAsStringAsync();
return httpClient.GetAsync(string.Empty); Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}, logger, deploymentResult.HostShutdownToken, retryCount: 30); Assert.Equal("Anonymous?True", responseText);
var responseText = await response.Content.ReadAsStringAsync(); response = await httpClient.GetAsync("/Restricted");
try Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
{ Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString());
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString());
Assert.Equal("Hello World", responseText);
response = await httpClient.GetAsync("/Anonymous"); response = await httpClient.GetAsync("/RestrictedNTLM");
responseText = await response.Content.ReadAsStringAsync(); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString());
Assert.Equal("Anonymous?True", responseText); // Note we can't restrict a challenge to a specific auth type, the native auth modules always add themselves.
Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString());
response = await httpClient.GetAsync("/Restricted"); response = await httpClient.GetAsync("/Forbidden");
responseText = await response.Content.ReadAsStringAsync(); Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString());
Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString());
response = await httpClient.GetAsync("/RestrictedNTLM"); var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
responseText = await response.Content.ReadAsStringAsync(); httpClient = result.CreateClient(httpClientHandler);
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString());
// Note we can't restrict a challenge to a specific auth type, the native auth modules always add themselves.
Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString());
response = await httpClient.GetAsync("/Forbidden"); response = await httpClient.GetAsync("/Anonymous");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Anonymous?True", responseText);
var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; response = await httpClient.GetAsync("/Restricted");
httpClient = deploymentResult.CreateHttpClient(httpClientHandler); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
response = await httpClient.GetAsync("/Anonymous"); Assert.NotEmpty(responseText);
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Anonymous?True", responseText);
response = await httpClient.GetAsync("/Restricted");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.NotEmpty(responseText);
}
catch (XunitException)
{
logger.LogWarning(response.ToString());
logger.LogWarning(responseText);
throw;
}
}
}
} }
} }
} }

View File

@ -3,20 +3,18 @@
using System; using System;
using System.IO; using System.IO;
using System.Threading; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using IISIntegration.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit; using Xunit;
using Xunit.Abstractions; using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{ {
public class UpgradeFeatureDetectionTests : LoggedTest public class UpgradeFeatureDetectionTests : IISFunctionalTestBase
{ {
private string _isWebsocketsSupported = Environment.OSVersion.Version >= new Version(6, 2) ? "Enabled" : "Disabled"; private readonly string _isWebsocketsSupported = Environment.OSVersion.Version >= new Version(6, 2) ? "Enabled" : "Disabled";
public UpgradeFeatureDetectionTests(ITestOutputHelper output) : base(output) public UpgradeFeatureDetectionTests(ITestOutputHelper output) : base(output)
{ {
@ -25,7 +23,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[Fact] [Fact]
public Task UpgradeFeatureDetectionDisabled_InProcess_IISExpress() public Task UpgradeFeatureDetectionDisabled_InProcess_IISExpress()
{ {
return UpgradeFeatureDetectionDeployer("AppHostConfig/WebsocketsNotSupported.config", return UpgradeFeatureDetectionDeployer(
disableWebSocket: true,
Helpers.GetInProcessTestSitesPath(), Helpers.GetInProcessTestSitesPath(),
"Disabled"); "Disabled");
} }
@ -33,7 +32,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[Fact] [Fact]
public Task UpgradeFeatureDetectionEnabled_InProcess_IISExpress() public Task UpgradeFeatureDetectionEnabled_InProcess_IISExpress()
{ {
return UpgradeFeatureDetectionDeployer("AppHostConfig/Http.config", return UpgradeFeatureDetectionDeployer(
disableWebSocket: false,
Helpers.GetInProcessTestSitesPath(), Helpers.GetInProcessTestSitesPath(),
_isWebsocketsSupported); _isWebsocketsSupported);
} }
@ -41,7 +41,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[Fact] [Fact]
public Task UpgradeFeatureDetectionDisabled_OutOfProcess_IISExpress() public Task UpgradeFeatureDetectionDisabled_OutOfProcess_IISExpress()
{ {
return UpgradeFeatureDetectionDeployer("AppHostConfig/WebsocketsNotSupported.config", return UpgradeFeatureDetectionDeployer(
disableWebSocket: true,
Helpers.GetOutOfProcessTestSitesPath(), Helpers.GetOutOfProcessTestSitesPath(),
"Disabled"); "Disabled");
} }
@ -49,51 +50,34 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[Fact] [Fact]
public Task UpgradeFeatureDetectionEnabled_OutOfProcess_IISExpress() public Task UpgradeFeatureDetectionEnabled_OutOfProcess_IISExpress()
{ {
return UpgradeFeatureDetectionDeployer("AppHostConfig/Http.config", return UpgradeFeatureDetectionDeployer(
disableWebSocket: false,
Helpers.GetOutOfProcessTestSitesPath(), Helpers.GetOutOfProcessTestSitesPath(),
_isWebsocketsSupported); _isWebsocketsSupported);
} }
private async Task UpgradeFeatureDetectionDeployer(string configPath, string sitePath, string expected) private async Task UpgradeFeatureDetectionDeployer(bool disableWebSocket, string sitePath, string expected)
{ {
var testName = $"HelloWorld"; var deploymentParameters = new DeploymentParameters(sitePath, ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64)
using (StartLog(out var loggerFactory, testName))
{ {
var logger = loggerFactory.CreateLogger("HelloWorldTest"); TargetFramework = Tfm.NetCoreApp22,
ApplicationType = ApplicationType.Portable,
AncmVersion = AncmVersion.AspNetCoreModuleV2
};
var deploymentParameters = new DeploymentParameters(sitePath, ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64) if (disableWebSocket)
{ {
EnvironmentName = "UpgradeFeatureDetection", // Will pick the Start class named 'StartupHelloWorld', deploymentParameters.ServerConfigTemplateContent = GetServerConfig(
ServerConfigTemplateContent = File.ReadAllText(configPath), element => element.Descendants("webSocket")
SiteName = "HttpTestSite", // This is configured in the Http.config .Single()
TargetFramework = Tfm.NetCoreApp22, .SetAttributeValue("enabled", "false"));
ApplicationType = ApplicationType.Portable,
AncmVersion = AncmVersion.AspNetCoreModuleV2
};
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
{
var deploymentResult = await deployer.DeployAsync();
deploymentResult.HttpClient.Timeout = TimeSpan.FromSeconds(5);
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
var response = await RetryHelper.RetryRequest(() =>
{
return deploymentResult.HttpClient.GetAsync("UpgradeFeatureDetection");
}, logger, deploymentResult.HostShutdownToken, retryCount: 30);
var responseText = await response.Content.ReadAsStringAsync();
try
{
Assert.Equal(expected, responseText);
}
catch (XunitException)
{
logger.LogWarning(response.ToString());
logger.LogWarning(responseText);
throw;
}
}
} }
var deploymentResult = await DeployAsync(deploymentParameters);
var response = await deploymentResult.RetryingHttpClient.GetAsync("UpgradeFeatureDetection");
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(expected, responseText);
} }
} }
} }

View File

@ -0,0 +1,32 @@
// 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.Threading.Tasks;
using Microsoft.Extensions.Logging.Testing;
using Xunit.Abstractions;
namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
public class FunctionalTestsBase : LoggedTest
{
public FunctionalTestsBase(ITestOutputHelper output = null) : base(output)
{
}
private ApplicationDeployer _deployer;
protected virtual async Task<IISDeploymentResult> DeployAsync(DeploymentParameters parameters)
{
_deployer = ApplicationDeployerFactory.Create(parameters, LoggerFactory);
var result = await _deployer.DeployAsync();
return new IISDeploymentResult(result, Logger);
}
public override void Dispose()
{
_deployer?.Dispose();
}
}
}

View File

@ -1,42 +1,20 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Server.IntegrationTesting;
using System;
using System.IO; using System.IO;
using System.Linq; using Microsoft.AspNetCore.Testing;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{ {
public class Helpers public class Helpers
{ {
public static string GetTestWebSitePath(string name) public static string GetTestWebSitePath(string name)
{ {
return Path.GetFullPath( return Path.Combine(TestPathUtilities.GetSolutionRootDirectory("IISIntegration"),"test", "WebSites", name);
Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
"..", // tfm
"..", // debug
"..", // obj
"..", // projectfolder
"WebSites",
name));
} }
public static string GetInProcessTestSitesPath() => GetTestWebSitePath("InProcessWebSite"); public static string GetInProcessTestSitesPath() => GetTestWebSitePath("InProcessWebSite");
public static string GetOutOfProcessTestSitesPath() => GetTestWebSitePath("OutOfProcessWebSite"); public static string GetOutOfProcessTestSitesPath() => GetTestWebSitePath("OutOfProcessWebSite");
public static void ModifyAspNetCoreSectionInWebConfig(DeploymentResult deploymentResult, string key, string value)
{
// modify the web.config after publish
var root = deploymentResult.ContentRoot;
var webConfigFile = $"{root}/web.config";
var config = XDocument.Load(webConfigFile);
var element = config.Descendants("aspNetCore").FirstOrDefault();
element.SetAttributeValue(key, value);
config.Save(webConfigFile);
}
} }
} }

View File

@ -0,0 +1,39 @@
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; }
}
}

View File

@ -0,0 +1,53 @@
// 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.Linq;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Xunit.Abstractions;
namespace IISIntegration.FunctionalTests.Utilities
{
public class IISFunctionalTestBase : FunctionalTestsBase
{
public IISFunctionalTestBase(ITestOutputHelper output = null) : base(output)
{
}
protected override Task<IISDeploymentResult> DeployAsync(DeploymentParameters parameters)
{
if (parameters.SiteName == null)
{
parameters.SiteName = "HttpTestSite";
}
if (parameters.ServerConfigTemplateContent == null)
{
parameters.ServerConfigTemplateContent = GetServerConfig(null);
}
return base.DeployAsync(parameters);
}
protected string GetServerConfig(Action<XElement> transform)
{
var doc = XDocument.Load("AppHostConfig/Http.config");
transform?.Invoke(doc.Root);
return doc.ToString();
}
protected string GetHttpsServerConfig()
{
return GetServerConfig(
element => {
element.Descendants("binding")
.Single()
.SetAttributeValue("protocol", "https");
element.Descendants("access")
.Single()
.SetAttributeValue("sslFlags", "Ssl, SslNegotiateCert");
});
}
}
}

View File

@ -0,0 +1,51 @@
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
public class LoggingHandler: DelegatingHandler
{
private readonly int _maxBodyLogSize = 16 * 1024;
private readonly ILogger _logger;
public LoggingHandler(HttpMessageHandler innerHandler, ILogger logger)
: base(innerHandler)
{
_logger = logger;
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
_logger.LogDebug(request.ToString());
var response = await base.SendAsync(request, cancellationToken);
await LogResponse(response.IsSuccessStatusCode ? LogLevel.Debug : LogLevel.Warning, response);
return response;
}
private async Task LogResponse(LogLevel logLevel, HttpResponseMessage response)
{
_logger.Log(logLevel, response.ToString());
if (response.Content != null)
{
await response.Content.LoadIntoBufferAsync();
var readAsStreamAsync = await response.Content.ReadAsStreamAsync();
var buffer = new byte[_maxBodyLogSize];
var offset = 0;
var count = 0;
do
{
count = await readAsStreamAsync.ReadAsync(buffer, offset, buffer.Length - offset);
offset += count;
} while (count != 0 && offset != buffer.Length);
_logger.Log(logLevel, Encoding.ASCII.GetString(buffer, 0, offset));
}
}
}
}

View File

@ -0,0 +1,60 @@
// 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.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
public class RetryHandler : DelegatingHandler
{
private static readonly int MaxRetries = 5;
private static readonly TimeSpan RetryDelay = TimeSpan.FromSeconds(1);
private readonly ILogger _logger;
public RetryHandler(HttpMessageHandler innerHandler, ILogger logger)
: base(innerHandler)
{
_logger = logger;
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
HttpResponseMessage response = null;
for (int i = 0; i < MaxRetries; i++)
{
response = null;
try
{
response = await base.SendAsync(request, cancellationToken);
}
catch (Exception ex)
{
_logger.LogWarning("Error sending request", ex);
if (i == MaxRetries - 1)
{
throw;
}
}
// Retry only on 503 that is expected during IIS startup
if (response != null &&
(response.IsSuccessStatusCode || response.StatusCode != (HttpStatusCode)503))
{
break;
}
_logger.LogDebug($"Retrying {i+1}th time after {RetryDelay.Seconds} sec.");
await Task.Delay(RetryDelay, cancellationToken);
}
return response;
}
}
}

View File

@ -12,7 +12,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
using Xunit; using Xunit;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests namespace Microsoft.AspNetCore.Server.IntegrationTesting
{ {
/// <summary> /// <summary>
/// Summary description for TestConnection /// Summary description for TestConnection

View File

@ -4,13 +4,13 @@
using System; using System;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.IISIntegration.FunctionalTests;
using Microsoft.AspNetCore.Server.IIS; using Microsoft.AspNetCore.Server.IIS;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
using Xunit; using Xunit;
@ -21,16 +21,7 @@ namespace IISTestSite
{ {
public void Configure(IApplicationBuilder app) public void Configure(IApplicationBuilder app)
{ {
foreach (var method in GetType().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) TestStartup.Register(app, this);
{
var parameters = method.GetParameters();
if (method.Name != nameof(Configure) &&
parameters.Length == 1 &&
parameters[0].ParameterType == typeof(IApplicationBuilder))
{
app.Map("/" + method.Name, innerAppBuilder => method.Invoke(this, new[] { innerAppBuilder }));
}
}
} }
private void ServerVariable(IApplicationBuilder app) private void ServerVariable(IApplicationBuilder app)
@ -38,7 +29,7 @@ namespace IISTestSite
app.Run(async ctx => app.Run(async ctx =>
{ {
var varName = ctx.Request.Query["q"]; var varName = ctx.Request.Query["q"];
await ctx.Response.WriteAsync($"{varName}: {HttpContextExtensions.GetIISServerVariable(ctx, varName) ?? "(null)"}"); await ctx.Response.WriteAsync($"{varName}: {ctx.GetIISServerVariable(varName) ?? "(null)"}");
}); });
} }

View File

@ -10,6 +10,10 @@
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Server.IISIntegration\Microsoft.AspNetCore.Server.IISIntegration.csproj" /> <ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Server.IISIntegration\Microsoft.AspNetCore.Server.IISIntegration.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Include="..\shared\**\*.cs" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="$(MicrosoftAspNetCoreWebUtilitiesPackageVersion)" /> <PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="$(MicrosoftAspNetCoreWebUtilitiesPackageVersion)" />

View File

@ -0,0 +1,88 @@
// 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.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.IISIntegration.FunctionalTests;
using Microsoft.AspNetCore.Server.IISIntegration;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace TestSites
{
public class Startup
{
public void Configure(IApplicationBuilder app)
{
TestStartup.Register(app, this);
}
public Task Path(HttpContext ctx) => ctx.Response.WriteAsync(ctx.Request.Path.Value);
public Task Query(HttpContext ctx) => ctx.Response.WriteAsync(ctx.Request.QueryString.Value);
public Task BodyLimit(HttpContext ctx) => ctx.Response.WriteAsync(ctx.Features.Get<IHttpMaxRequestBodySizeFeature>()?.MaxRequestBodySize?.ToString() ?? "null");
public async Task Auth(HttpContext ctx)
{
var iisAuth = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_HTTPAUTH");
var authProvider = ctx.RequestServices.GetService<IAuthenticationSchemeProvider>();
var authScheme = (await authProvider.GetAllSchemesAsync()).SingleOrDefault();
if (string.IsNullOrEmpty(iisAuth))
{
await ctx.Response.WriteAsync("backcompat;" + (authScheme?.Name ?? "null"));
}
else
{
await ctx.Response.WriteAsync("latest;" + (authScheme?.Name ?? "null"));
}
}
public Task HelloWorld(HttpContext ctx) => ctx.Response.WriteAsync("Hello World");
public Task HttpsHelloWorld(HttpContext ctx) =>
ctx.Response.WriteAsync("Scheme:" + ctx.Request.Scheme + "; Original:" + ctx.Request.Headers["x-original-proto"]);
public Task CheckClientCert(HttpContext ctx) =>
ctx.Response.WriteAsync("Scheme:" + ctx.Request.Scheme + "; Original:" + ctx.Request.Headers["x-original-proto"]
+ "; has cert? " + (ctx.Connection.ClientCertificate != null));
public Task Anonymous(HttpContext context) => context.Response.WriteAsync("Anonymous?" + !context.User.Identity.IsAuthenticated);
public Task Restricted(HttpContext context)
{
if (context.User.Identity.IsAuthenticated)
{
Assert.IsType<WindowsPrincipal>(context.User);
return context.Response.WriteAsync(context.User.Identity.AuthenticationType);
}
else
{
return context.ChallengeAsync(IISDefaults.AuthenticationScheme);
}
}
public Task Forbidden(HttpContext context) => context.ForbidAsync(IISDefaults.AuthenticationScheme);
public Task RestrictedNTLM(HttpContext context)
{
if (string.Equals("NTLM", context.User.Identity.AuthenticationType, StringComparison.Ordinal))
{
return context.Response.WriteAsync("NTLM");
}
else
{
return context.ChallengeAsync(IISDefaults.AuthenticationScheme);
}
}
public Task UpgradeFeatureDetection(HttpContext context) =>
context.Response.WriteAsync(context.Features.Get<IHttpUpgradeFeature>() != null? "Enabled": "Disabled");
}
}

View File

@ -1,58 +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.Linq;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace TestSites
{
public class StartupHelloWorld
{
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.Run(async ctx =>
{
if (ctx.Request.Path.Value.StartsWith("/Path"))
{
await ctx.Response.WriteAsync(ctx.Request.Path.Value);
return;
}
if (ctx.Request.Path.Value.StartsWith("/Query"))
{
await ctx.Response.WriteAsync(ctx.Request.QueryString.Value);
return;
}
if (ctx.Request.Path.Value.StartsWith("/BodyLimit"))
{
await ctx.Response.WriteAsync(
ctx.Features.Get<IHttpMaxRequestBodySizeFeature>()?.MaxRequestBodySize?.ToString() ?? "null");
return;
}
if (ctx.Request.Path.StartsWithSegments("/Auth"))
{
var iisAuth = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_HTTPAUTH");
var authProvider = ctx.RequestServices.GetService<IAuthenticationSchemeProvider>();
var authScheme = (await authProvider.GetAllSchemesAsync()).SingleOrDefault();
if (string.IsNullOrEmpty(iisAuth))
{
await ctx.Response.WriteAsync("backcompat;" + (authScheme?.Name ?? "null"));
}
else
{
await ctx.Response.WriteAsync("latest;" + (authScheme?.Name ?? "null"));
}
return;
}
await ctx.Response.WriteAsync("Hello World");
});
}
}
}

View File

@ -1,25 +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 Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace TestSites
{
public class StartupHttpsHelloWorld
{
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.Run(ctx =>
{
if (ctx.Request.Path.Equals(new PathString("/checkclientcert")))
{
return ctx.Response.WriteAsync("Scheme:" + ctx.Request.Scheme + "; Original:" + ctx.Request.Headers["x-original-proto"]
+ "; has cert? " + (ctx.Connection.ClientCertificate != null));
}
return ctx.Response.WriteAsync("Scheme:" + ctx.Request.Scheme + "; Original:" + ctx.Request.Headers["x-original-proto"]);
});
}
}
}

View File

@ -1,80 +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.Security.Principal;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.IISIntegration;
using Microsoft.Extensions.Logging;
using Xunit;
namespace TestSites
{
public class StartupNtlmAuthentication
{
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
// Simple error page without depending on Diagnostics.
app.Use(async (context, next) =>
{
try
{
await next();
}
catch (Exception ex)
{
if (context.Response.HasStarted)
{
throw;
}
context.Response.Clear();
context.Response.StatusCode = 500;
await context.Response.WriteAsync(ex.ToString());
}
});
app.Use((context, next) =>
{
if (context.Request.Path.Equals("/Anonymous"))
{
return context.Response.WriteAsync("Anonymous?" + !context.User.Identity.IsAuthenticated);
}
if (context.Request.Path.Equals("/Restricted"))
{
if (context.User.Identity.IsAuthenticated)
{
Assert.IsType<WindowsPrincipal>(context.User);
return context.Response.WriteAsync(context.User.Identity.AuthenticationType);
}
else
{
return context.ChallengeAsync(IISDefaults.AuthenticationScheme);
}
}
if (context.Request.Path.Equals("/Forbidden"))
{
return context.ForbidAsync(IISDefaults.AuthenticationScheme);
}
if (context.Request.Path.Equals("/RestrictedNTLM"))
{
if (string.Equals("NTLM", context.User.Identity.AuthenticationType, StringComparison.Ordinal))
{
return context.Response.WriteAsync("NTLM");
}
else
{
return context.ChallengeAsync(IISDefaults.AuthenticationScheme);
}
}
return context.Response.WriteAsync("Hello World");
});
}
}
}

View File

@ -1,32 +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.Linq;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace TestSites
{
public class StartupUpgradeFeatureDetection
{
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
app.Run(async ctx =>
{
if (ctx.Features.Get<IHttpUpgradeFeature>() != null)
{
await ctx.Response.WriteAsync("Enabled");
}
else
{
await ctx.Response.WriteAsync("Disabled");
}
});
}
}
}

View File

@ -0,0 +1,38 @@
using System;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
namespace Microsoft.AspNetCore.IISIntegration.FunctionalTests
{
public static class TestStartup
{
public static void Register(IApplicationBuilder app, object startup)
{
var type = startup.GetType();
foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
var parameters = method.GetParameters();
if (method.Name != "Configure" &&
parameters.Length == 1)
{
Action<IApplicationBuilder> appfunc = null;
if (parameters[0].ParameterType == typeof(IApplicationBuilder))
{
appfunc = innerAppBuilder => method.Invoke(startup, new[] { innerAppBuilder });
}
else if (parameters[0].ParameterType == typeof(HttpContext))
{
appfunc = innerAppBuilder => innerAppBuilder.Run(ctx => (Task)method.Invoke(startup, new[] { ctx }));
}
if (appfunc != null)
{
app.Map("/" + method.Name, appfunc);
}
}
}
}
}
}