react to aspnet/Hosting#996 (#67)

This commit is contained in:
Andrew Stanton-Nurse 2017-03-31 13:22:09 -07:00 committed by GitHub
parent 1d1b255170
commit 9b598201ff
12 changed files with 293 additions and 199 deletions

View File

@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio 15
VisualStudioVersion = 15.0.26228.4 VisualStudioVersion = 15.0.26228.10
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{49AB8AAA-8160-48DF-A18B-78F51E54E02A}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{49AB8AAA-8160-48DF-A18B-78F51E54E02A}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
@ -13,6 +13,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerComparison.Functional
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerComparison.TestSites", "test\ServerComparison.TestSites\ServerComparison.TestSites.csproj", "{030225D8-4EE8-47E5-B692-2A96B3B51A38}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerComparison.TestSites", "test\ServerComparison.TestSites\ServerComparison.TestSites.csproj", "{030225D8-4EE8-47E5-B692-2A96B3B51A38}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{55694E45-5EDE-46F8-80AA-797DE5F8C5C3}"
ProjectSection(SolutionItems) = preProject
build\common.props = build\common.props
build\dependencies.props = build\dependencies.props
build\repo.props = build\repo.props
EndProjectSection
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU

View File

@ -3,7 +3,7 @@
<AspNetCoreVersion>1.2.0-*</AspNetCoreVersion> <AspNetCoreVersion>1.2.0-*</AspNetCoreVersion>
<InternalAspNetCoreSdkVersion>2.0.0-*</InternalAspNetCoreSdkVersion> <InternalAspNetCoreSdkVersion>2.0.0-*</InternalAspNetCoreSdkVersion>
<ResponseCompressionVersion>1.1.0-*</ResponseCompressionVersion> <ResponseCompressionVersion>1.1.0-*</ResponseCompressionVersion>
<AspNetCoreLabsVersion>0.3.0-*</AspNetCoreLabsVersion> <AspNetCoreIntegrationTestingVersion>0.4.0-*</AspNetCoreIntegrationTestingVersion>
<AspNetCoreModuleVersion>1.0.0-*</AspNetCoreModuleVersion> <AspNetCoreModuleVersion>1.0.0-*</AspNetCoreModuleVersion>
<CoreFxVersion>4.3.0</CoreFxVersion> <CoreFxVersion>4.3.0</CoreFxVersion>
<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion> <NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>
@ -11,4 +11,4 @@
<TestSdkVersion>15.0.0</TestSdkVersion> <TestSdkVersion>15.0.0</TestSdkVersion>
<XunitVersion>2.2.0</XunitVersion> <XunitVersion>2.2.0</XunitVersion>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View File

@ -1,8 +1,9 @@
// 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;
using System.Net.Http; using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit; using Microsoft.AspNetCore.Testing.xunit;
@ -14,7 +15,6 @@ using Xunit.Sdk;
namespace ServerComparison.FunctionalTests namespace ServerComparison.FunctionalTests
{ {
// Uses ports ranging 5061 - 5069.
public class HelloWorldTests public class HelloWorldTests
{ {
private readonly ITestOutputHelper _output; private readonly ITestOutputHelper _output;
@ -28,59 +28,47 @@ namespace ServerComparison.FunctionalTests
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.MacOSX)]
//[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5061/", ApplicationType.Portable)] //[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, ApplicationType.Portable)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5062/", ApplicationType.Portable)] [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
//[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x86, "http://localhost:5063/", ApplicationType.Portable)] //[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x86, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5064/", ApplicationType.Portable)] [InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5065/", ApplicationType.Standalone)] [InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5066/", ApplicationType.Portable)] [InlineData(ServerType.Kestrel, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
public Task HelloWorld_Windows(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task HelloWorld_Windows(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return HelloWorld(serverType, runtimeFlavor, architecture, applicationBaseUrl, applicationType); return HelloWorld(serverType, runtimeFlavor, architecture, applicationType);
} }
[Theory] [Theory]
//[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5067/", ApplicationType.Portable)] //[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5068/", ApplicationType.Portable)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5069/", ApplicationType.Standalone)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task HelloWorld_Kestrel(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task HelloWorld_Kestrel(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return HelloWorld(serverType, runtimeFlavor, architecture, applicationBaseUrl, applicationType); return HelloWorld(serverType, runtimeFlavor, architecture, applicationType);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Windows)] [OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5070/", ApplicationType.Portable)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5071/", ApplicationType.Standalone)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task HelloWorld_Nginx(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task HelloWorld_Nginx(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return HelloWorld(serverType, runtimeFlavor, architecture, applicationBaseUrl, applicationType); return HelloWorld(serverType, runtimeFlavor, architecture, applicationType);
} }
[ConditionalTheory] public async Task HelloWorld(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType, [CallerMemberName] string testName = null)
[SkipIfEnvironmentVariableNotEnabled("IIS_VARIATIONS_ENABLED")]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
[FrameworkSkipCondition(RuntimeFrameworks.CoreCLR)]
[InlineData(ServerType.IIS, RuntimeFlavor.Clr, RuntimeArchitecture.x86, "http://localhost:5072/", ApplicationType.Portable)]
//[InlineData(ServerType.IIS, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5073/", ApplicationType.Portable)]
public Task HelloWorld_IIS_X86(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
{ {
return HelloWorld(serverType, runtimeFlavor, architecture, applicationBaseUrl, applicationType); testName = $"{testName}_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}";
} var loggerFactory = TestLoggingUtilities.SetUpLogging<HelloWorldTests>(_output, testName);
var logger = loggerFactory.CreateLogger("TestHarness");
Console.WriteLine($"Starting test: {testName}");
logger.LogInformation("Starting test: {testName}", testName);
public async Task HelloWorld(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) using (logger.BeginScope("HelloWorld"))
{
var loggerName = string.Format("HelloWorld:{0}:{1}:{2}:{3}", serverType, runtimeFlavor, architecture, applicationType);
Console.WriteLine("Running test for " + loggerName);
var logger = new LoggerFactory()
.AddXunit(_output)
.CreateLogger(loggerName);
using (logger.BeginScope("HelloWorldTest"))
{ {
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture) var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture)
{ {
ApplicationBaseUriHint = applicationBaseUrl,
EnvironmentName = "HelloWorld", // Will pick the Start class named 'StartupHelloWorld', EnvironmentName = "HelloWorld", // Will pick the Start class named 'StartupHelloWorld',
ServerConfigTemplateContent = Helpers.GetConfigContent(serverType, "Http.config", "nginx.conf"), ServerConfigTemplateContent = Helpers.GetConfigContent(serverType, "Http.config", "nginx.conf"),
SiteName = "HttpTestSite", // This is configured in the Http.config SiteName = "HttpTestSite", // This is configured in the Http.config
@ -88,16 +76,16 @@ namespace ServerComparison.FunctionalTests
ApplicationType = applicationType ApplicationType = applicationType
}; };
if(applicationType == ApplicationType.Standalone) if (applicationType == ApplicationType.Standalone)
{ {
deploymentParameters.AdditionalPublishParameters = " -r " + RuntimeEnvironment.GetRuntimeIdentifier(); deploymentParameters.AdditionalPublishParameters = " -r " + RuntimeEnvironment.GetRuntimeIdentifier();
} }
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger)) using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
{ {
var deploymentResult = deployer.Deploy(); var deploymentResult = await deployer.DeployAsync();
var httpClientHandler = new HttpClientHandler(); var httpClientHandler = new HttpClientHandler();
var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) }; var httpClient = new HttpClient(new LoggingHandler(loggerFactory, httpClientHandler)) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) };
// 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 RetryHelper.RetryRequest(() =>
@ -118,6 +106,9 @@ namespace ServerComparison.FunctionalTests
} }
} }
} }
Console.WriteLine($"Finished test: {testName}");
logger.LogInformation("Finished test: {testName}", testName);
} }
} }
} }

View File

@ -5,7 +5,7 @@
For schema documentation, see For schema documentation, see
%IIS_BIN%\config\schema\IIS_schema.xml. %IIS_BIN%\config\schema\IIS_schema.xml.
Please make a backup of this file before making any changes to it. Please make a backup of this file before making any changes to it.
NOTE: The following environment variables are available to be used NOTE: The following environment variables are available to be used
@ -25,20 +25,20 @@
The <configSections> section controls the registration of sections. The <configSections> section controls the registration of sections.
Section is the basic unit of deployment, locking, searching and Section is the basic unit of deployment, locking, searching and
containment for configuration settings. containment for configuration settings.
Every section belongs to one section group. Every section belongs to one section group.
A section group is a container of logically-related sections. A section group is a container of logically-related sections.
Sections cannot be nested. Sections cannot be nested.
Section groups may be nested. Section groups may be nested.
<section <section
name="" [Required, Collection Key] [XML name of the section] name="" [Required, Collection Key] [XML name of the section]
allowDefinition="Everywhere" [MachineOnly|MachineToApplication|AppHostOnly|Everywhere] [Level where it can be set] allowDefinition="Everywhere" [MachineOnly|MachineToApplication|AppHostOnly|Everywhere] [Level where it can be set]
overrideModeDefault="Allow" [Allow|Deny] [Default delegation mode] overrideModeDefault="Allow" [Allow|Deny] [Default delegation mode]
allowLocation="true" [true|false] [Allowed in location tags] allowLocation="true" [true|false] [Allowed in location tags]
/> />
The recommended way to unlock sections is by using a location tag: The recommended way to unlock sections is by using a location tag:
<location path="Default Web Site" overrideMode="Allow"> <location path="Default Web Site" overrideMode="Allow">
<system.webServer> <system.webServer>

View File

@ -0,0 +1,25 @@
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace ServerComparison.FunctionalTests
{
internal class LoggingHandler : DelegatingHandler
{
private ILogger _logger;
public LoggingHandler(ILoggerFactory loggerFactory, HttpMessageHandler innerHandler) : base(innerHandler)
{
_logger = loggerFactory.CreateLogger<HttpClient>();
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
_logger.LogDebug("Sending {method} {url}", request.Method, request.RequestUri);
var response = await base.SendAsync(request, cancellationToken);
_logger.LogDebug("Received {statusCode} {reasonPhrase} {url}", response.StatusCode, response.ReasonPhrase, request.RequestUri);
return response;
}
}
}

View File

@ -5,7 +5,7 @@
For schema documentation, see For schema documentation, see
%IIS_BIN%\config\schema\IIS_schema.xml. %IIS_BIN%\config\schema\IIS_schema.xml.
Please make a backup of this file before making any changes to it. Please make a backup of this file before making any changes to it.
NOTE: The following environment variables are available to be used NOTE: The following environment variables are available to be used
@ -25,20 +25,20 @@
The <configSections> section controls the registration of sections. The <configSections> section controls the registration of sections.
Section is the basic unit of deployment, locking, searching and Section is the basic unit of deployment, locking, searching and
containment for configuration settings. containment for configuration settings.
Every section belongs to one section group. Every section belongs to one section group.
A section group is a container of logically-related sections. A section group is a container of logically-related sections.
Sections cannot be nested. Sections cannot be nested.
Section groups may be nested. Section groups may be nested.
<section <section
name="" [Required, Collection Key] [XML name of the section] name="" [Required, Collection Key] [XML name of the section]
allowDefinition="Everywhere" [MachineOnly|MachineToApplication|AppHostOnly|Everywhere] [Level where it can be set] allowDefinition="Everywhere" [MachineOnly|MachineToApplication|AppHostOnly|Everywhere] [Level where it can be set]
overrideModeDefault="Allow" [Allow|Deny] [Default delegation mode] overrideModeDefault="Allow" [Allow|Deny] [Default delegation mode]
allowLocation="true" [true|false] [Allowed in location tags] allowLocation="true" [true|false] [Allowed in location tags]
/> />
The recommended way to unlock sections is by using a location tag: The recommended way to unlock sections is by using a location tag:
<location path="Default Web Site" overrideMode="Allow"> <location path="Default Web Site" overrideMode="Allow">
<system.webServer> <system.webServer>

View File

@ -5,6 +5,7 @@
using System; using System;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit; using Microsoft.AspNetCore.Testing.xunit;
@ -16,7 +17,6 @@ using Xunit.Sdk;
namespace ServerComparison.FunctionalTests namespace ServerComparison.FunctionalTests
{ {
// Uses ports ranging 5050 - 5060.
public class NtlmAuthenticationTests public class NtlmAuthenticationTests
{ {
private readonly ITestOutputHelper _output; private readonly ITestOutputHelper _output;
@ -30,24 +30,23 @@ namespace ServerComparison.FunctionalTests
[OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.MacOSX)]
// TODO: https://github.com/aspnet/IISIntegration/issues/1 // TODO: https://github.com/aspnet/IISIntegration/issues/1
// [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5050/", ApplicationType.Portable)] // [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, ApplicationType.Portable)]
// [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5051/", ApplicationType.Portable)] // [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
// [InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x86, "http://localhost:5052/", ApplicationType.Portable)] // [InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x86, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5052/", ApplicationType.Portable)] [InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5053/", ApplicationType.Standalone)] [InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public async Task NtlmAuthentication(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public async Task NtlmAuthentication(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
var loggerName = string.Format("Ntlm:{0}:{1}:{2}:{3}", serverType, runtimeFlavor, architecture, applicationType); var testName = $"NtlmAuthentication_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}";
Console.WriteLine("Running test for " + loggerName); var loggerFactory = TestLoggingUtilities.SetUpLogging<HelloWorldTests>(_output, testName);
var logger = new LoggerFactory() var logger = loggerFactory.CreateLogger("TestHarness");
.AddXunit(_output) Console.WriteLine($"Starting test: {testName}");
.CreateLogger(loggerName); logger.LogInformation("Starting test: {testName}", testName);
using (logger.BeginScope("NtlmAuthenticationTest")) using (logger.BeginScope("NtlmAuthenticationTest"))
{ {
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture) var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture)
{ {
ApplicationBaseUriHint = applicationBaseUrl,
EnvironmentName = "NtlmAuthentication", // Will pick the Start class named 'StartupNtlmAuthentication' EnvironmentName = "NtlmAuthentication", // Will pick the Start class named 'StartupNtlmAuthentication'
ServerConfigTemplateContent = Helpers.GetConfigContent(serverType, "NtlmAuthentication.config", nginxConfig: null), ServerConfigTemplateContent = Helpers.GetConfigContent(serverType, "NtlmAuthentication.config", nginxConfig: null),
SiteName = "NtlmAuthenticationTestSite", // This is configured in the NtlmAuthentication.config SiteName = "NtlmAuthenticationTestSite", // This is configured in the NtlmAuthentication.config
@ -55,16 +54,16 @@ namespace ServerComparison.FunctionalTests
ApplicationType = applicationType ApplicationType = applicationType
}; };
if(applicationType == ApplicationType.Standalone) if (applicationType == ApplicationType.Standalone)
{ {
deploymentParameters.AdditionalPublishParameters = " -r " + RuntimeEnvironment.GetRuntimeIdentifier(); deploymentParameters.AdditionalPublishParameters = " -r " + RuntimeEnvironment.GetRuntimeIdentifier();
} }
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger)) using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
{ {
var deploymentResult = deployer.Deploy(); var deploymentResult = await deployer.DeployAsync();
var httpClientHandler = new HttpClientHandler(); var httpClientHandler = new HttpClientHandler();
var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) }; var httpClient = new HttpClient(new LoggingHandler(loggerFactory, httpClientHandler)) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) };
// 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 RetryHelper.RetryRequest(() =>
@ -77,16 +76,19 @@ namespace ServerComparison.FunctionalTests
{ {
Assert.Equal("Hello World", responseText); Assert.Equal("Hello World", responseText);
logger.LogInformation("Testing /Anonymous");
response = await httpClient.GetAsync("/Anonymous"); response = await httpClient.GetAsync("/Anonymous");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("Anonymous?True", responseText); Assert.Equal("Anonymous?True", responseText);
logger.LogInformation("Testing /Restricted");
response = await httpClient.GetAsync("/Restricted"); response = await httpClient.GetAsync("/Restricted");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString()); Assert.Contains("NTLM", response.Headers.WwwAuthenticate.ToString());
Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString()); Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString());
logger.LogInformation("Testing /RestrictedNTLM");
response = await httpClient.GetAsync("/RestrictedNTLM"); response = await httpClient.GetAsync("/RestrictedNTLM");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
@ -102,26 +104,32 @@ namespace ServerComparison.FunctionalTests
Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString()); Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString());
} }
logger.LogInformation("Testing /Forbidden");
response = await httpClient.GetAsync("/Forbidden"); response = await httpClient.GetAsync("/Forbidden");
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
logger.LogInformation("Enabling Default Credentials");
httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) }; httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) };
logger.LogInformation("Testing /AutoForbid");
response = await httpClient.GetAsync("/AutoForbid"); response = await httpClient.GetAsync("/AutoForbid");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
logger.LogInformation("Testing /Restricted");
response = await httpClient.GetAsync("/Restricted"); response = await httpClient.GetAsync("/Restricted");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Negotiate", responseText); Assert.Equal("Negotiate", responseText);
logger.LogInformation("Testing /RestrictedNegotiate");
response = await httpClient.GetAsync("/RestrictedNegotiate"); response = await httpClient.GetAsync("/RestrictedNegotiate");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Negotiate", responseText); Assert.Equal("Negotiate", responseText);
logger.LogInformation("Testing /RestrictedNTLM");
if (serverType == ServerType.WebListener) if (serverType == ServerType.WebListener)
{ {
response = await httpClient.GetAsync("/RestrictedNTLM"); response = await httpClient.GetAsync("/RestrictedNTLM");
@ -147,6 +155,9 @@ namespace ServerComparison.FunctionalTests
} }
} }
} }
Console.WriteLine($"Finished test: {testName}");
logger.LogInformation("Finished test: {testName}", testName);
} }
} }
} }

View File

@ -1,4 +1,4 @@
// 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;
@ -8,6 +8,7 @@ using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit; using Microsoft.AspNetCore.Testing.xunit;
@ -20,7 +21,6 @@ using Xunit.Sdk;
namespace ServerComparison.FunctionalTests namespace ServerComparison.FunctionalTests
{ {
// Uses ports ranging 5100 - 5130.
public class ResponseCompressionTests public class ResponseCompressionTests
{ {
// NGinx's default min size is 20 bytes // NGinx's default min size is 20 bytes
@ -35,108 +35,107 @@ namespace ServerComparison.FunctionalTests
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5100/", ApplicationType.Portable)] [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5101/", ApplicationType.Portable)] [InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
public Task ResponseCompression_Windows_NoCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseCompression_Windows_NoCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseCompression(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckNoCompressionAsync, applicationType, hostCompression: false); return ResponseCompression(serverType, runtimeFlavor, architecture, CheckNoCompressionAsync, applicationType, hostCompression: false);
} }
[Theory] [Theory]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5102/", ApplicationType.Portable)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5103/", ApplicationType.Standalone)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseCompression_Kestrel_NoCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseCompression_Kestrel_NoCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseCompression(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckNoCompressionAsync, applicationType, hostCompression: false); return ResponseCompression(serverType, runtimeFlavor, architecture, CheckNoCompressionAsync, applicationType, hostCompression: false);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Windows)] [OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5103/", ApplicationType.Portable)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5104/", ApplicationType.Standalone)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseCompression_Nginx_NoCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseCompression_Nginx_NoCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseCompression(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckNoCompressionAsync, applicationType, hostCompression: false); return ResponseCompression(serverType, runtimeFlavor, architecture, CheckNoCompressionAsync, applicationType, hostCompression: false);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5105/", ApplicationType.Portable)] [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5106/", ApplicationType.Standalone)] [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseCompression_Windows_HostCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseCompression_Windows_HostCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseCompression(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckHostCompressionAsync, applicationType, hostCompression: true); return ResponseCompression(serverType, runtimeFlavor, architecture, CheckHostCompressionAsync, applicationType, hostCompression: true);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Windows)] [OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5107/", ApplicationType.Portable)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5108/", ApplicationType.Standalone)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseCompression_Nginx_HostCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseCompression_Nginx_HostCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseCompression(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckHostCompressionAsync, applicationType, hostCompression: true); return ResponseCompression(serverType, runtimeFlavor, architecture, CheckHostCompressionAsync, applicationType, hostCompression: true);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5109/", ApplicationType.Standalone)] [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5110/", ApplicationType.Portable)] [InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
public Task ResponseCompression_Windows_AppCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseCompression_Windows_AppCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseCompression(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckAppCompressionAsync, applicationType, hostCompression: false); return ResponseCompression(serverType, runtimeFlavor, architecture, CheckAppCompressionAsync, applicationType, hostCompression: false);
} }
[Theory] [Theory]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5111/", ApplicationType.Portable)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5112/", ApplicationType.Standalone)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseCompression_Kestrel_AppCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseCompression_Kestrel_AppCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseCompression(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckAppCompressionAsync, applicationType, hostCompression: false); return ResponseCompression(serverType, runtimeFlavor, architecture, CheckAppCompressionAsync, applicationType, hostCompression: false);
} }
[ConditionalTheory(Skip = "No pass-through compression https://github.com/aspnet/BasicMiddleware/issues/123")] [ConditionalTheory(Skip = "No pass-through compression https://github.com/aspnet/BasicMiddleware/issues/123")]
[OSSkipCondition(OperatingSystems.Windows)] [OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5113/", ApplicationType.Portable)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5114/", ApplicationType.Standalone)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseCompression_Nginx_AppCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseCompression_Nginx_AppCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseCompression(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckHostCompressionAsync, applicationType, hostCompression: false); return ResponseCompression(serverType, runtimeFlavor, architecture, CheckHostCompressionAsync, applicationType, hostCompression: false);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5115/", ApplicationType.Standalone)] [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5116/", ApplicationType.Portable)] [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
public Task ResponseCompression_Windows_AppAndHostCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseCompression_Windows_AppAndHostCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseCompression(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckAppCompressionAsync, applicationType, hostCompression: true); return ResponseCompression(serverType, runtimeFlavor, architecture, CheckAppCompressionAsync, applicationType, hostCompression: true);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Windows)] [OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5117/", ApplicationType.Portable)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5118/", ApplicationType.Standalone)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseCompression_Nginx_AppAndHostCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseCompression_Nginx_AppAndHostCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseCompression(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckAppCompressionAsync, applicationType, hostCompression: true); return ResponseCompression(serverType, runtimeFlavor, architecture, CheckAppCompressionAsync, applicationType, hostCompression: true);
} }
public async Task ResponseCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, Func<HttpClient, ILogger, Task> scenario, ApplicationType applicationType, bool hostCompression) public async Task ResponseCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, Func<HttpClient, ILogger, Task> scenario, ApplicationType applicationType, bool hostCompression, [CallerMemberName] string testName = null)
{ {
var loggerName = string.Format("ResponseCompression:{0}:{1}:{2}:{3}", serverType, runtimeFlavor, architecture, applicationType); testName = $"{testName}_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}";
Console.WriteLine("Running test for " + loggerName); var loggerFactory = TestLoggingUtilities.SetUpLogging<ResponseCompressionTests>(_output, testName);
var logger = new LoggerFactory() var logger = loggerFactory.CreateLogger("TestHarness");
.AddXunit(_output) Console.WriteLine($"Starting test: {testName}");
.CreateLogger(loggerName); logger.LogInformation("Starting test: {testName}", testName);
using (logger.BeginScope("ResponseCompressionTest")) using (logger.BeginScope("ResponseCompression"))
{ {
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture) var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture)
{ {
ApplicationBaseUriHint = applicationBaseUrl,
EnvironmentName = "ResponseCompression", EnvironmentName = "ResponseCompression",
ServerConfigTemplateContent = Helpers.GetConfigContent(serverType, ServerConfigTemplateContent = Helpers.GetConfigContent(serverType,
hostCompression ? "http.config" : "NoCompression.config", hostCompression ? "http.config" : "NoCompression.config",
@ -151,12 +150,12 @@ namespace ServerComparison.FunctionalTests
deploymentParameters.AdditionalPublishParameters = " -r " + RuntimeEnvironment.GetRuntimeIdentifier(); deploymentParameters.AdditionalPublishParameters = " -r " + RuntimeEnvironment.GetRuntimeIdentifier();
} }
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger)) using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
{ {
var deploymentResult = deployer.Deploy(); var deploymentResult = await deployer.DeployAsync();
var httpClientHandler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.None }; var httpClientHandler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.None };
Assert.True(httpClientHandler.SupportsAutomaticDecompression); Assert.True(httpClientHandler.SupportsAutomaticDecompression);
var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) }; var httpClient = new HttpClient(new LoggingHandler(loggerFactory, httpClientHandler)) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) };
// 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 RetryHelper.RetryRequest(() =>
@ -179,10 +178,14 @@ namespace ServerComparison.FunctionalTests
await scenario(httpClient, logger); await scenario(httpClient, logger);
} }
} }
Console.WriteLine($"Finished test: {testName}");
logger.LogInformation("Finished test: {testName}", testName);
} }
private static async Task CheckNoCompressionAsync(HttpClient client, ILogger logger) private static async Task CheckNoCompressionAsync(HttpClient client, ILogger logger)
{ {
logger.LogInformation("Testing /NoAppCompression");
var request = new HttpRequestMessage(HttpMethod.Get, "NoAppCompression"); var request = new HttpRequestMessage(HttpMethod.Get, "NoAppCompression");
request.Headers.AcceptEncoding.ParseAdd("gzip,deflate"); request.Headers.AcceptEncoding.ParseAdd("gzip,deflate");
var response = await client.SendAsync(request); var response = await client.SendAsync(request);
@ -214,6 +217,7 @@ namespace ServerComparison.FunctionalTests
private static async Task CheckCompressionAsync(HttpClient client, string url, ILogger logger) private static async Task CheckCompressionAsync(HttpClient client, string url, ILogger logger)
{ {
// Manage the compression manually because HttpClient removes the Content-Encoding header when decompressing. // Manage the compression manually because HttpClient removes the Content-Encoding header when decompressing.
logger.LogInformation($"Testing /{url}");
var request = new HttpRequestMessage(HttpMethod.Get, url); var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.AcceptEncoding.ParseAdd("gzip,deflate"); request.Headers.AcceptEncoding.ParseAdd("gzip,deflate");
var response = await client.SendAsync(request); var response = await client.SendAsync(request);

View File

@ -1,10 +1,11 @@
// 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;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IntegrationTesting; using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit; using Microsoft.AspNetCore.Testing.xunit;
@ -17,7 +18,6 @@ using Xunit.Sdk;
namespace ServerComparison.FunctionalTests namespace ServerComparison.FunctionalTests
{ {
// Uses ports ranging 5080 - 5099.
public class ResponseTests public class ResponseTests
{ {
private readonly ITestOutputHelper _output; private readonly ITestOutputHelper _output;
@ -30,151 +30,150 @@ namespace ServerComparison.FunctionalTests
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5080/", ApplicationType.Portable)] [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5081/", ApplicationType.Portable)] [InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
public Task ResponseFormats_Windows_ContentLength(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Windows_ContentLength(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckContentLengthAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckContentLengthAsync, applicationType);
} }
[Theory] [Theory]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5082/", ApplicationType.Portable)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5083/", ApplicationType.Standalone)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseFormats_Kestrel_ContentLength(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Kestrel_ContentLength(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckContentLengthAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckContentLengthAsync, applicationType);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Windows)] [OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5084/", ApplicationType.Portable)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5085/", ApplicationType.Standalone)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseFormats_Nginx_ContentLength(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Nginx_ContentLength(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckContentLengthAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckContentLengthAsync, applicationType);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5087/", ApplicationType.Portable)] [InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
// IIS will remove the "Connection: close" header https://github.com/aspnet/IISIntegration/issues/7 // IIS will remove the "Connection: close" header https://github.com/aspnet/IISIntegration/issues/7
public Task ResponseFormats_Windows_Http10ConnectionClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Windows_Http10ConnectionClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckHttp10ConnectionCloseAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckHttp10ConnectionCloseAsync, applicationType);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5087/", ApplicationType.Portable)] // https://github.com/aspnet/WebListener/issues/259 [InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)] // https://github.com/aspnet/WebListener/issues/259
// IIS will remove the "Connection: close" header https://github.com/aspnet/IISIntegration/issues/7 // IIS will remove the "Connection: close" header https://github.com/aspnet/IISIntegration/issues/7
public Task ResponseFormats_Windows_Http11ConnectionClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Windows_Http11ConnectionClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckHttp11ConnectionCloseAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckHttp11ConnectionCloseAsync, applicationType);
} }
[Theory] [Theory]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5088/", ApplicationType.Portable)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5089/", ApplicationType.Standalone)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseFormats_Kestrel_Http10ConnectionClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Kestrel_Http10ConnectionClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckHttp10ConnectionCloseAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckHttp10ConnectionCloseAsync, applicationType);
} }
[Theory] [Theory]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5088/", ApplicationType.Portable)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5089/", ApplicationType.Standalone)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseFormats_Kestrel_Http11ConnectionClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Kestrel_Http11ConnectionClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckHttp11ConnectionCloseAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckHttp11ConnectionCloseAsync, applicationType);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5090/", ApplicationType.Portable)] [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5091/", ApplicationType.Portable)] [InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
public Task ResponseFormats_Windows_Chunked(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Windows_Chunked(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckChunkedAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckChunkedAsync, applicationType);
} }
[Theory] [Theory]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5092/", ApplicationType.Portable)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5093/", ApplicationType.Standalone)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseFormats_Kestrel_Chunked(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Kestrel_Chunked(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckChunkedAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckChunkedAsync, applicationType);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Windows)] [OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5094/", ApplicationType.Portable)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5095/", ApplicationType.Standalone)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseFormats_Nginx_Chunked(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Nginx_Chunked(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckChunkedAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckChunkedAsync, applicationType);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5096/", ApplicationType.Portable)] [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5097/", ApplicationType.Portable)] [InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
public Task ResponseFormats_Windows_ManuallyChunk(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Windows_ManuallyChunk(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckManuallyChunkedAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckManuallyChunkedAsync, applicationType);
} }
[Theory] [Theory]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5098/", ApplicationType.Portable)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5099/", ApplicationType.Standalone)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseFormats_Kestrel_ManuallyChunk(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Kestrel_ManuallyChunk(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckManuallyChunkedAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckManuallyChunkedAsync, applicationType);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Windows)] [OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5100/", ApplicationType.Portable)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5101/", ApplicationType.Standalone)] [InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseFormats_Nginx_ManuallyChunk(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Nginx_ManuallyChunk(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckManuallyChunkedAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckManuallyChunkedAsync, applicationType);
} }
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)] [OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.MacOSX)]
// [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5102/", ApplicationType.Portable)] // https://github.com/aspnet/IISIntegration/issues/7 // [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)] // https://github.com/aspnet/IISIntegration/issues/7
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5103/", ApplicationType.Portable)] [InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
public Task ResponseFormats_Windows_ManuallyChunkAndClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Windows_ManuallyChunkAndClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckManuallyChunkedAndCloseAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckManuallyChunkedAndCloseAsync, applicationType);
} }
[Theory] [Theory]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5104/", ApplicationType.Portable)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5104/", ApplicationType.Standalone)] [InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
public Task ResponseFormats_Kestrel_ManuallyChunkAndClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType) public Task ResponseFormats_Kestrel_ManuallyChunkAndClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return ResponseFormats(serverType, runtimeFlavor, architecture, applicationBaseUrl, CheckManuallyChunkedAndCloseAsync, applicationType); return ResponseFormats(serverType, runtimeFlavor, architecture, CheckManuallyChunkedAndCloseAsync, applicationType);
} }
public async Task ResponseFormats(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, Func<HttpClient, ILogger, Task> scenario, ApplicationType applicationType) public async Task ResponseFormats(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, Func<HttpClient, ILogger, Task> scenario, ApplicationType applicationType, [CallerMemberName] string testName = null)
{ {
var loggerName = string.Format("ResponseFormats:{0}:{1}:{2}:{3}", serverType, runtimeFlavor, architecture, applicationType); testName = $"{testName}_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}";
Console.WriteLine("Running test for " + loggerName); var loggerFactory = TestLoggingUtilities.SetUpLogging<HelloWorldTests>(_output, testName);
var logger = new LoggerFactory() var logger = loggerFactory.CreateLogger("TestHarness");
.AddXunit(_output) Console.WriteLine($"Starting test: {testName}");
.CreateLogger(loggerName); logger.LogInformation("Starting test: {testName}", testName);
using (logger.BeginScope("ResponseFormatsTest")) using (logger.BeginScope("ResponseFormats"))
{ {
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture) var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture)
{ {
ApplicationBaseUriHint = applicationBaseUrl,
EnvironmentName = "Responses", EnvironmentName = "Responses",
ServerConfigTemplateContent = Helpers.GetConfigContent(serverType, "Http.config", "nginx.conf"), ServerConfigTemplateContent = Helpers.GetConfigContent(serverType, "Http.config", "nginx.conf"),
SiteName = "HttpTestSite", // This is configured in the Http.config SiteName = "HttpTestSite", // This is configured in the Http.config
@ -187,11 +186,11 @@ namespace ServerComparison.FunctionalTests
deploymentParameters.AdditionalPublishParameters = " -r " + RuntimeEnvironment.GetRuntimeIdentifier(); deploymentParameters.AdditionalPublishParameters = " -r " + RuntimeEnvironment.GetRuntimeIdentifier();
} }
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, logger)) using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
{ {
var deploymentResult = deployer.Deploy(); var deploymentResult = await deployer.DeployAsync();
var httpClientHandler = new HttpClientHandler(); var httpClientHandler = new HttpClientHandler();
var httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) }; var httpClient = new HttpClient(new LoggingHandler(loggerFactory, httpClientHandler)) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) };
// 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 RetryHelper.RetryRequest(() =>
@ -214,10 +213,14 @@ namespace ServerComparison.FunctionalTests
await scenario(httpClient, logger); await scenario(httpClient, logger);
} }
} }
Console.WriteLine($"Finished test: {testName}");
logger.LogInformation("Finished test: {testName}", testName);
} }
private static async Task CheckContentLengthAsync(HttpClient client, ILogger logger) private static async Task CheckContentLengthAsync(HttpClient client, ILogger logger)
{ {
logger.LogInformation("Testing ContentLength");
var response = await client.GetAsync("contentlength"); var response = await client.GetAsync("contentlength");
var responseText = await response.Content.ReadAsStringAsync(); var responseText = await response.Content.ReadAsStringAsync();
try try
@ -237,6 +240,7 @@ namespace ServerComparison.FunctionalTests
private static async Task CheckHttp11ConnectionCloseAsync(HttpClient client, ILogger logger) private static async Task CheckHttp11ConnectionCloseAsync(HttpClient client, ILogger logger)
{ {
logger.LogInformation("Testing Http11ConnectionClose");
var response = await client.GetAsync("connectionclose"); var response = await client.GetAsync("connectionclose");
var responseText = await response.Content.ReadAsStringAsync(); var responseText = await response.Content.ReadAsStringAsync();
try try
@ -256,6 +260,7 @@ namespace ServerComparison.FunctionalTests
private static async Task CheckHttp10ConnectionCloseAsync(HttpClient client, ILogger logger) private static async Task CheckHttp10ConnectionCloseAsync(HttpClient client, ILogger logger)
{ {
logger.LogInformation("Testing Http10ConnectionClose");
var requestMessage = new HttpRequestMessage(HttpMethod.Get, "connectionclose") var requestMessage = new HttpRequestMessage(HttpMethod.Get, "connectionclose")
{ {
Version = new Version(1, 0) Version = new Version(1, 0)
@ -280,6 +285,7 @@ namespace ServerComparison.FunctionalTests
private static async Task CheckChunkedAsync(HttpClient client, ILogger logger) private static async Task CheckChunkedAsync(HttpClient client, ILogger logger)
{ {
logger.LogInformation("Testing Chunked");
var response = await client.GetAsync("chunked"); var response = await client.GetAsync("chunked");
var responseText = await response.Content.ReadAsStringAsync(); var responseText = await response.Content.ReadAsStringAsync();
try try
@ -299,6 +305,7 @@ namespace ServerComparison.FunctionalTests
private static async Task CheckManuallyChunkedAsync(HttpClient client, ILogger logger) private static async Task CheckManuallyChunkedAsync(HttpClient client, ILogger logger)
{ {
logger.LogInformation("Testing ManuallyChunked");
var response = await client.GetAsync("manuallychunked"); var response = await client.GetAsync("manuallychunked");
var responseText = await response.Content.ReadAsStringAsync(); var responseText = await response.Content.ReadAsStringAsync();
try try
@ -318,6 +325,7 @@ namespace ServerComparison.FunctionalTests
private static async Task CheckManuallyChunkedAndCloseAsync(HttpClient client, ILogger logger) private static async Task CheckManuallyChunkedAndCloseAsync(HttpClient client, ILogger logger)
{ {
logger.LogInformation("Testing ManuallyChunkedAndClose");
var response = await client.GetAsync("manuallychunkedandclose"); var response = await client.GetAsync("manuallychunkedandclose");
var responseText = await response.Content.ReadAsStringAsync(); var responseText = await response.Content.ReadAsStringAsync();
try try

View File

@ -15,13 +15,15 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.IntegrationTesting" Version="$(AspNetCoreLabsVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Server.IntegrationTesting" Version="$(AspNetCoreIntegrationTestingVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(AspNetCoreVersion)" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Testing" Version="$(AspNetCoreVersion)" /> <PackageReference Include="Microsoft.Extensions.Logging.Testing" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="$(AspNetCoreVersion)" /> <PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Dotnet.PlatformAbstractions" Version="$(AspNetCoreVersion)" /> <PackageReference Include="Microsoft.Dotnet.PlatformAbstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Net.Http.Headers" Version="$(AspNetCoreVersion)" /> <PackageReference Include="Microsoft.Net.Http.Headers" Version="$(AspNetCoreVersion)" />
<PackageReference Include="System.Net.Http" Version="$(SystemNetHttpVersion)" /> <PackageReference Include="System.Net.Http" Version="$(SystemNetHttpVersion)" />
<PackageReference Include="Serilog.Extensions.Logging" Version="1.4.0" />
<PackageReference Include="Serilog.Sinks.File" Version="3.2.0" />
<PackageReference Include="xunit" Version="$(XunitVersion)" /> <PackageReference Include="xunit" Version="$(XunitVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" /> <PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />
</ItemGroup> </ItemGroup>

View File

@ -0,0 +1,47 @@
using System;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.Extensions.Logging;
using Serilog;
using Xunit.Abstractions;
namespace ServerComparison.FunctionalTests
{
public static class TestLoggingUtilities
{
public static readonly string TestOutputRoot = Environment.GetEnvironmentVariable("ASPNETCORE_TEST_LOG_DIR");
public static ILoggerFactory SetUpLogging<TTestClass>(ITestOutputHelper output, [CallerMemberName] string testName = null)
{
var loggerFactory = new LoggerFactory();
loggerFactory.AddXunit(output, LogLevel.Debug);
if (!string.IsNullOrEmpty(TestOutputRoot))
{
var testClass = typeof(TTestClass).GetTypeInfo();
var testOutputDir = Path.Combine(TestOutputRoot, testClass.Assembly.GetName().Name, testClass.FullName);
if (!Directory.Exists(testOutputDir))
{
Directory.CreateDirectory(testOutputDir);
}
var testOutputFile = Path.Combine(testOutputDir, $"{testName}.log");
if (File.Exists(testOutputFile))
{
File.Delete(testOutputFile);
}
var serilogger = new LoggerConfiguration()
.Enrich.FromLogContext()
.MinimumLevel.Verbose()
.WriteTo.File(testOutputFile, flushToDiskInterval: TimeSpan.FromSeconds(1))
.CreateLogger();
loggerFactory.AddSerilog(serilogger);
}
return loggerFactory;
}
}
}

View File

@ -1,5 +1,4 @@
error_log [errorlog]; error_log [errorlog];
user [user];
worker_processes 4; worker_processes 4;
pid [pidFile]; pid [pidFile];