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">
<BenchmarkDotNetPackageVersion>0.10.13</BenchmarkDotNetPackageVersion>
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview1-17055</InternalAspNetCoreSdkPackageVersion>
<MicrosoftAspNetCoreAllPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreAllPackageVersion>
<MicrosoftAspNetCoreAuthenticationCorePackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreAuthenticationCorePackageVersion>
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
<MicrosoftAspNetCoreHostingPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreHostingPackageVersion>
<MicrosoftAspNetCoreHttpExtensionsPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreHttpExtensionsPackageVersion>
<MicrosoftAspNetCoreHttpOverridesPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreHttpOverridesPackageVersion>
<MicrosoftAspNetCoreHttpPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreHttpPackageVersion>
<MicrosoftAspNetCoreHttpSysSourcesPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreHttpSysSourcesPackageVersion>
<MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>0.6.0-a-preview1-inttesting-17031</MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreServerKestrelPackageVersion>
<MicrosoftAspNetCoreTestHostPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreTestHostPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.2.0-preview1-34217</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
<MicrosoftAspNetCoreAllPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreAllPackageVersion>
<MicrosoftAspNetCoreAuthenticationCorePackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreAuthenticationCorePackageVersion>
<MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreBenchmarkRunnerSourcesPackageVersion>
<MicrosoftAspNetCoreHostingAbstractionsPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreHostingAbstractionsPackageVersion>
<MicrosoftAspNetCoreHostingPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreHostingPackageVersion>
<MicrosoftAspNetCoreHttpExtensionsPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreHttpExtensionsPackageVersion>
<MicrosoftAspNetCoreHttpOverridesPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreHttpOverridesPackageVersion>
<MicrosoftAspNetCoreHttpPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreHttpPackageVersion>
<MicrosoftAspNetCoreHttpSysSourcesPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreHttpSysSourcesPackageVersion>
<MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>0.6.0-preview1-34230</MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreServerKestrelPackageVersion>
<MicrosoftAspNetCoreTestHostPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreTestHostPackageVersion>
<MicrosoftAspNetCoreTestingPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreTestingPackageVersion>
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.2.0-preview1-34230</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
<MicrosoftBuildFrameworkPackageVersion>15.6.82</MicrosoftBuildFrameworkPackageVersion>
<MicrosoftBuildUtilitiesCorePackageVersion>15.6.82</MicrosoftBuildUtilitiesCorePackageVersion>
<MicrosoftExtensionsBuffersMemoryPoolSourcesPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsBuffersMemoryPoolSourcesPackageVersion>
<MicrosoftExtensionsBuffersSourcesPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsBuffersSourcesPackageVersion>
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTestingPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsLoggingTestingPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsSecurityHelperSourcesPackageVersion>2.2.0-preview1-34217</MicrosoftExtensionsSecurityHelperSourcesPackageVersion>
<MicrosoftExtensionsBuffersMemoryPoolSourcesPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsBuffersMemoryPoolSourcesPackageVersion>
<MicrosoftExtensionsBuffersSourcesPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsBuffersSourcesPackageVersion>
<MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsCommandLineUtilsSourcesPackageVersion>
<MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsConfigurationEnvironmentVariablesPackageVersion>
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsConfigurationJsonPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingConsolePackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsLoggingConsolePackageVersion>
<MicrosoftExtensionsLoggingDebugPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsLoggingDebugPackageVersion>
<MicrosoftExtensionsLoggingPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsLoggingPackageVersion>
<MicrosoftExtensionsLoggingTestingPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsLoggingTestingPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsSecurityHelperSourcesPackageVersion>2.2.0-preview1-34230</MicrosoftExtensionsSecurityHelperSourcesPackageVersion>
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
<MicrosoftNETCoreApp21PackageVersion>2.1.0-rc1</MicrosoftNETCoreApp21PackageVersion>
<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>
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
<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.
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Xml.Linq;
using IISIntegration.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.CommandLineUtils;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{
[SkipIfIISExpressSchemaMissingInProcess]
public class StartupTests : LoggedTest
public class StartupTests : IISFunctionalTestBase
{
public StartupTests(ITestOutputHelper output) : base(output)
{
}
[Fact]
public async Task ExpandEnvironmentVariableInWebConfig()
{
var dotnetLocation = DotNetMuxer.MuxerPathOrDefault();
using (StartLog(out var loggerFactory))
{
var logger = loggerFactory.CreateLogger("HelloWorldTest");
var deploymentParameters = GetBaseDeploymentParameters();
var deploymentParameters = GetBaseDeploymentParameters();
// Point to dotnet installed in user profile.
deploymentParameters.EnvironmentVariables["DotnetPath"] = dotnetLocation;
// Point to dotnet installed in user profile.
deploymentParameters.EnvironmentVariables["DotnetPath"] = dotnetLocation;
var deploymentResult = await DeployAsync(deploymentParameters);
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
{
var deploymentResult = await deployer.DeployAsync();
ModifyAspNetCoreSectionInWebConfig(deploymentResult, "processPath", "%DotnetPath%");
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 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;
}
}
}
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("Hello World", responseText);
}
[Fact]
public async Task InvalidProcessPath_ExpectServerError()
{
var dotnetLocation = "bogus";
using (StartLog(out var loggerFactory))
{
var logger = loggerFactory.CreateLogger("HelloWorldTest");
var deploymentParameters = GetBaseDeploymentParameters();
// Point to dotnet installed in user profile.
deploymentParameters.EnvironmentVariables["DotnetPath"] = Environment.ExpandEnvironmentVariables(dotnetLocation); // Path to dotnet.
var deploymentParameters = GetBaseDeploymentParameters();
// 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 deployer.DeployAsync();
var deploymentResult = await DeployAsync(deploymentParameters);
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.
var response = await RetryHelper.RetryRequest(() =>
{
return deploymentResult.HttpClient.GetAsync("HelloWorld");
}, logger, deploymentResult.HostShutdownToken, retryCount: 30);
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
var response = await deploymentResult.RetryingHttpClient.GetAsync("HelloWorld");
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();
deploymentParameters.ApplicationType = ApplicationType.Standalone;
var deploymentResult = await DeployAsync(deploymentParameters);
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
{
var deploymentResult = await deployer.DeployAsync();
var response = await deploymentResult.RetryingHttpClient.GetAsync("/HelloWorld");
var responseText = await response.Content.ReadAsStringAsync();
// 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]
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;
}
}
}
Assert.Equal("Hello World", responseText);
}
[Fact]
public async Task DetectsOveriddenServer()
{
var testSink = new TestSink();
using (StartLog(out var loggerFactory))
{
var testLoggerFactory = new TestLoggerFactory(testSink, true);
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"));
var deploymentResult = await DeployAsync(GetBaseDeploymentParameters("OverriddenServerWebSite"));
var response = await deploymentResult.HttpClient.GetAsync("/");
Assert.False(response.IsSuccessStatusCode);
Assert.Contains(TestSink.Writes, context => context.Message.Contains("Application is running inside IIS process but is not configured to use IIS server"));
}
private DeploymentParameters GetBaseDeploymentParameters(string site = null)
{
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,
ApplicationType = ApplicationType.Portable,
AncmVersion = AncmVersion.AspNetCoreModuleV2
};
}
private class TestLoggerProvider : ILoggerProvider
private static void ModifyAspNetCoreSectionInWebConfig(IISDeploymentResult deploymentResult, string key, string value)
{
private readonly TestLoggerFactory _loggerFactory;
public TestLoggerProvider(TestLoggerFactory loggerFactory)
{
_loggerFactory = loggerFactory;
}
public void Dispose()
{
}
public ILogger CreateLogger(string categoryName)
{
return _loggerFactory.CreateLogger(categoryName);
}
// modify the web.config after publish
var root = deploymentResult.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

@ -1,21 +1,18 @@
// 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.IO;
using System.Threading.Tasks;
using IISIntegration.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
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))]
public async Task HelloWorld(TestVariant variant)
{
var testName = $"HelloWorld_{variant.Tfm}";
using (StartLog(out var loggerFactory, testName))
var deploymentParameters = new DeploymentParameters(variant)
{
var logger = loggerFactory.CreateLogger("HelloWorldTest");
ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(),
};
var deploymentParameters = new DeploymentParameters(variant)
{
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
};
var deploymentResult = await DeployAsync(deploymentParameters);
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
{
var deploymentResult = await deployer.DeployAsync();
var response = await deploymentResult.RetryingHttpClient.GetAsync("/HelloWorld");
var responseText = await response.Content.ReadAsStringAsync();
// 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(string.Empty);
}, logger, deploymentResult.HostShutdownToken, retryCount: 30);
Assert.Equal("Hello World", responseText);
var responseText = await response.Content.ReadAsStringAsync();
try
{
Assert.Equal("Hello World", responseText);
response = await deploymentResult.HttpClient.GetAsync("/Path/%3F%3F?query");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("/??", responseText);
response = await deploymentResult.HttpClient.GetAsync("/Path%3F%3F?query");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("/Path??", responseText);
response = await deploymentResult.HttpClient.GetAsync("/Query/%3FPath?query?");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("?query?", responseText);
response = await deploymentResult.HttpClient.GetAsync("/Query%3FPath?query?");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("?query?", responseText);
response = await deploymentResult.HttpClient.GetAsync("/BodyLimit");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("null", responseText);
response = await deploymentResult.HttpClient.GetAsync("/BodyLimit");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("null", responseText);
response = await deploymentResult.HttpClient.GetAsync("/Auth");
responseText = await response.Content.ReadAsStringAsync();
response = await deploymentResult.HttpClient.GetAsync("/Auth");
responseText = await response.Content.ReadAsStringAsync();
// 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;
}
}
}
// 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");
}
}
}

View File

@ -1,25 +1,21 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using IISIntegration.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{
// 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
// 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)
{
@ -34,49 +30,23 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[MemberData(nameof(TestVariants))]
public async Task HttpsHelloWorld(TestVariant variant)
{
var applicationBaseUrl = $"https://localhost:44394/";
var testName = $"HttpsHelloWorld_{variant.Tfm}";
using (StartLog(out var loggerFactory, testName))
var deploymentParameters = new DeploymentParameters(variant)
{
var logger = loggerFactory.CreateLogger("HttpsHelloWorldTest");
ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(),
ApplicationBaseUriHint = "https://localhost:44394/",
ServerConfigTemplateContent = GetHttpsServerConfig()
};
var deploymentParameters = new DeploymentParameters(variant)
{
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
};
var deploymentResult = await DeployAsync(deploymentParameters);
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
{
var deploymentResult = await deployer.DeployAsync();
var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (a, b, c, d) => true;
var httpClient = deploymentResult.CreateHttpClient(handler);
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 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;
}
}
}
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (a, b, c, d) => true
};
var client = deploymentResult.CreateRetryClient(handler);
var response = await client.GetAsync("HttpsHelloWorld");
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("Scheme:https; Original:http", responseText);
}
[ConditionalTheory]
@ -97,60 +67,41 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
private async Task HttpsHelloWorldCerts(TestVariant variant, int port, bool sendClientCert)
{
var applicationBaseUrl = $"https://localhost:{port}/";
var testName = $"HttpsHelloWorldCerts_{variant.Tfm}_{sendClientCert}";
using (StartLog(out var loggerFactory, testName))
var deploymentParameters = new DeploymentParameters(variant)
{
var logger = loggerFactory.CreateLogger("HttpsHelloWorldTest");
ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(),
ApplicationBaseUriHint = $"https://localhost:{port}/",
ServerConfigTemplateContent = GetHttpsServerConfig()
};
var deploymentParameters = new DeploymentParameters(variant)
{
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
};
var deploymentResult = await DeployAsync(deploymentParameters);
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
{
var deploymentResult = await deployer.DeployAsync();
var handler = new HttpClientHandler();
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);
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (a, b, c, d) => true,
ClientCertificateOptions = ClientCertificateOption.Manual
};
// 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("checkclientcert");
}, logger, deploymentResult.HostShutdownToken);
if (sendClientCert)
{
X509Certificate2 clientCert = FindClientCert();
Assert.NotNull(clientCert);
handler.ClientCertificates.Add(clientCert);
}
var responseText = await response.Content.ReadAsStringAsync();
try
{
if (sendClientCert)
{
Assert.Equal("Scheme:https; Original:http; has cert? True", responseText);
}
else
{
Assert.Equal("Scheme:https; Original:http; has cert? False", responseText);
}
}
catch (XunitException)
{
logger.LogWarning(response.ToString());
logger.LogWarning(responseText);
throw;
}
}
var client = deploymentResult.CreateRetryClient(handler);
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
var response = await client.GetAsync("checkclientcert");
var responseText = await response.Content.ReadAsStringAsync();
if (sendClientCert)
{
Assert.Equal("Scheme:https; Original:http; has cert? True", responseText);
}
else
{
Assert.Equal("Scheme:https; Original:http; has cert? False", responseText);
}
}

View File

@ -1,22 +1,19 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using IISIntegration.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{
public class NtlmAuthenticationTests : LoggedTest
public class NtlmAuthenticationTests : IISFunctionalTestBase
{
public NtlmAuthenticationTests(ITestOutputHelper output) : base(output)
{
@ -31,81 +28,51 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[MemberData(nameof(TestVariants))]
public async Task NtlmAuthentication(TestVariant variant)
{
var testName = $"NtlmAuthentication_{variant.Tfm}_{variant.AncmVersion}";
using (StartLog(out var loggerFactory, testName))
var deploymentParameters = new DeploymentParameters(variant)
{
var logger = loggerFactory.CreateLogger("NtlmAuthenticationTest");
ApplicationPath = Helpers.GetOutOfProcessTestSitesPath(),
ApplicationBaseUriHint = "http://localhost:5052"
};
var deploymentParameters = new DeploymentParameters(variant)
{
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
};
var result = await DeployAsync(deploymentParameters);
var response = await result.RetryingHttpClient.GetAsync("/HelloWorld");
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
{
var deploymentResult = await deployer.DeployAsync();
var httpClient = deploymentResult.HttpClient;
httpClient.Timeout = TimeSpan.FromSeconds(5);
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Hello World", 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 httpClient = result.HttpClient;
response = await httpClient.GetAsync("/Anonymous");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Anonymous?True", responseText);
var responseText = await response.Content.ReadAsStringAsync();
try
{
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Hello World", responseText);
response = await httpClient.GetAsync("/Restricted");
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString());
Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString());
response = await httpClient.GetAsync("/Anonymous");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Anonymous?True", responseText);
response = await httpClient.GetAsync("/RestrictedNTLM");
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("/Restricted");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString());
Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString());
response = await httpClient.GetAsync("/Forbidden");
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
response = await httpClient.GetAsync("/RestrictedNTLM");
responseText = await response.Content.ReadAsStringAsync();
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());
var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
httpClient = result.CreateClient(httpClientHandler);
response = await httpClient.GetAsync("/Forbidden");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
response = await httpClient.GetAsync("/Anonymous");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Anonymous?True", responseText);
var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
httpClient = deploymentResult.CreateHttpClient(httpClientHandler);
response = await httpClient.GetAsync("/Anonymous");
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;
}
}
}
response = await httpClient.GetAsync("/Restricted");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.NotEmpty(responseText);
}
}
}

View File

@ -3,20 +3,18 @@
using System;
using System.IO;
using System.Threading;
using System.Linq;
using System.Threading.Tasks;
using IISIntegration.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
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)
{
@ -25,7 +23,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[Fact]
public Task UpgradeFeatureDetectionDisabled_InProcess_IISExpress()
{
return UpgradeFeatureDetectionDeployer("AppHostConfig/WebsocketsNotSupported.config",
return UpgradeFeatureDetectionDeployer(
disableWebSocket: true,
Helpers.GetInProcessTestSitesPath(),
"Disabled");
}
@ -33,7 +32,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[Fact]
public Task UpgradeFeatureDetectionEnabled_InProcess_IISExpress()
{
return UpgradeFeatureDetectionDeployer("AppHostConfig/Http.config",
return UpgradeFeatureDetectionDeployer(
disableWebSocket: false,
Helpers.GetInProcessTestSitesPath(),
_isWebsocketsSupported);
}
@ -41,7 +41,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[Fact]
public Task UpgradeFeatureDetectionDisabled_OutOfProcess_IISExpress()
{
return UpgradeFeatureDetectionDeployer("AppHostConfig/WebsocketsNotSupported.config",
return UpgradeFeatureDetectionDeployer(
disableWebSocket: true,
Helpers.GetOutOfProcessTestSitesPath(),
"Disabled");
}
@ -49,51 +50,34 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[Fact]
public Task UpgradeFeatureDetectionEnabled_OutOfProcess_IISExpress()
{
return UpgradeFeatureDetectionDeployer("AppHostConfig/Http.config",
return UpgradeFeatureDetectionDeployer(
disableWebSocket: false,
Helpers.GetOutOfProcessTestSitesPath(),
_isWebsocketsSupported);
}
private async Task UpgradeFeatureDetectionDeployer(string configPath, string sitePath, string expected)
private async Task UpgradeFeatureDetectionDeployer(bool disableWebSocket, string sitePath, string expected)
{
var testName = $"HelloWorld";
using (StartLog(out var loggerFactory, testName))
var deploymentParameters = new DeploymentParameters(sitePath, ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64)
{
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)
{
EnvironmentName = "UpgradeFeatureDetection", // Will pick the Start class named 'StartupHelloWorld',
ServerConfigTemplateContent = File.ReadAllText(configPath),
SiteName = "HttpTestSite", // This is configured in the Http.config
TargetFramework = Tfm.NetCoreApp22,
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;
}
}
if (disableWebSocket)
{
deploymentParameters.ServerConfigTemplateContent = GetServerConfig(
element => element.Descendants("webSocket")
.Single()
.SetAttributeValue("enabled", "false"));
}
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.
// 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.Linq;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.AspNetCore.Testing;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
{
public class Helpers
{
public static string GetTestWebSitePath(string name)
{
return Path.GetFullPath(
Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
"..", // tfm
"..", // debug
"..", // obj
"..", // projectfolder
"WebSites",
name));
{
return Path.Combine(TestPathUtilities.GetSolutionRootDirectory("IISIntegration"),"test", "WebSites", name);
}
public static string GetInProcessTestSitesPath() => GetTestWebSitePath("InProcessWebSite");
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 Xunit;
namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
namespace Microsoft.AspNetCore.Server.IntegrationTesting
{
/// <summary>
/// Summary description for TestConnection

View File

@ -4,13 +4,13 @@
using System;
using System.IO;
using System.Net;
using System.Reflection;
using System.Text;
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.IIS;
using Microsoft.Extensions.Primitives;
using Xunit;
@ -21,16 +21,7 @@ namespace IISTestSite
{
public void Configure(IApplicationBuilder app)
{
foreach (var method in GetType().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
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 }));
}
}
TestStartup.Register(app, this);
}
private void ServerVariable(IApplicationBuilder app)
@ -38,7 +29,7 @@ namespace IISTestSite
app.Run(async ctx =>
{
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" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\shared\**\*.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<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);
}
}
}
}
}
}