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
# Visual Studio 15
VisualStudioVersion = 15.0.26228.4
VisualStudioVersion = 15.0.26228.10
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{49AB8AAA-8160-48DF-A18B-78F51E54E02A}"
ProjectSection(SolutionItems) = preProject
@ -13,6 +13,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerComparison.Functional
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerComparison.TestSites", "test\ServerComparison.TestSites\ServerComparison.TestSites.csproj", "{030225D8-4EE8-47E5-B692-2A96B3B51A38}"
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
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU

View File

@ -3,7 +3,7 @@
<AspNetCoreVersion>1.2.0-*</AspNetCoreVersion>
<InternalAspNetCoreSdkVersion>2.0.0-*</InternalAspNetCoreSdkVersion>
<ResponseCompressionVersion>1.1.0-*</ResponseCompressionVersion>
<AspNetCoreLabsVersion>0.3.0-*</AspNetCoreLabsVersion>
<AspNetCoreIntegrationTestingVersion>0.4.0-*</AspNetCoreIntegrationTestingVersion>
<AspNetCoreModuleVersion>1.0.0-*</AspNetCoreModuleVersion>
<CoreFxVersion>4.3.0</CoreFxVersion>
<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>
@ -11,4 +11,4 @@
<TestSdkVersion>15.0.0</TestSdkVersion>
<XunitVersion>2.2.0</XunitVersion>
</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.
using System;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
@ -14,7 +15,6 @@ using Xunit.Sdk;
namespace ServerComparison.FunctionalTests
{
// Uses ports ranging 5061 - 5069.
public class HelloWorldTests
{
private readonly ITestOutputHelper _output;
@ -28,59 +28,47 @@ namespace ServerComparison.FunctionalTests
[ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
//[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5061/", ApplicationType.Portable)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5062/", ApplicationType.Portable)]
//[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x86, "http://localhost:5063/", ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5064/", ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5065/", ApplicationType.Standalone)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5066/", ApplicationType.Portable)]
public Task HelloWorld_Windows(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
//[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, ApplicationType.Portable)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
//[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x86, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
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]
//[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5067/", ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5068/", ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5069/", ApplicationType.Standalone)]
public Task HelloWorld_Kestrel(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
//[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5070/", ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5071/", ApplicationType.Standalone)]
public Task HelloWorld_Nginx(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[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)
public async Task HelloWorld(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, ApplicationType applicationType, [CallerMemberName] string testName = null)
{
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)
{
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"))
using (logger.BeginScope("HelloWorld"))
{
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture)
{
ApplicationBaseUriHint = applicationBaseUrl,
EnvironmentName = "HelloWorld", // Will pick the Start class named 'StartupHelloWorld',
ServerConfigTemplateContent = Helpers.GetConfigContent(serverType, "Http.config", "nginx.conf"),
SiteName = "HttpTestSite", // This is configured in the Http.config
@ -88,16 +76,16 @@ namespace ServerComparison.FunctionalTests
ApplicationType = applicationType
};
if(applicationType == ApplicationType.Standalone)
if (applicationType == ApplicationType.Standalone)
{
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 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.
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
%IIS_BIN%\config\schema\IIS_schema.xml.
Please make a backup of this file before making any changes to it.
NOTE: The following environment variables are available to be used
@ -25,20 +25,20 @@
The <configSections> section controls the registration of sections.
Section is the basic unit of deployment, locking, searching and
containment for configuration settings.
Every section belongs to one section group.
A section group is a container of logically-related sections.
Sections cannot be nested.
Section groups may be nested.
<section
name="" [Required, Collection Key] [XML name of the section]
allowDefinition="Everywhere" [MachineOnly|MachineToApplication|AppHostOnly|Everywhere] [Level where it can be set]
overrideModeDefault="Allow" [Allow|Deny] [Default delegation mode]
allowLocation="true" [true|false] [Allowed in location tags]
/>
The recommended way to unlock sections is by using a location tag:
<location path="Default Web Site" overrideMode="Allow">
<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
%IIS_BIN%\config\schema\IIS_schema.xml.
Please make a backup of this file before making any changes to it.
NOTE: The following environment variables are available to be used
@ -25,20 +25,20 @@
The <configSections> section controls the registration of sections.
Section is the basic unit of deployment, locking, searching and
containment for configuration settings.
Every section belongs to one section group.
A section group is a container of logically-related sections.
Sections cannot be nested.
Section groups may be nested.
<section
name="" [Required, Collection Key] [XML name of the section]
allowDefinition="Everywhere" [MachineOnly|MachineToApplication|AppHostOnly|Everywhere] [Level where it can be set]
overrideModeDefault="Allow" [Allow|Deny] [Default delegation mode]
allowLocation="true" [true|false] [Allowed in location tags]
/>
The recommended way to unlock sections is by using a location tag:
<location path="Default Web Site" overrideMode="Allow">
<system.webServer>

View File

@ -5,6 +5,7 @@
using System;
using System.Net;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
@ -16,7 +17,6 @@ using Xunit.Sdk;
namespace ServerComparison.FunctionalTests
{
// Uses ports ranging 5050 - 5060.
public class NtlmAuthenticationTests
{
private readonly ITestOutputHelper _output;
@ -30,24 +30,23 @@ namespace ServerComparison.FunctionalTests
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
// TODO: https://github.com/aspnet/IISIntegration/issues/1
// [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, "http://localhost:5050/", ApplicationType.Portable)]
// [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5051/", ApplicationType.Portable)]
// [InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x86, "http://localhost:5052/", ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5052/", ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5053/", ApplicationType.Standalone)]
public async Task NtlmAuthentication(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
// [InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x86, ApplicationType.Portable)]
// [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
// [InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x86, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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);
Console.WriteLine("Running test for " + loggerName);
var logger = new LoggerFactory()
.AddXunit(_output)
.CreateLogger(loggerName);
var testName = $"NtlmAuthentication_{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);
using (logger.BeginScope("NtlmAuthenticationTest"))
{
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture)
{
ApplicationBaseUriHint = applicationBaseUrl,
EnvironmentName = "NtlmAuthentication", // Will pick the Start class named 'StartupNtlmAuthentication'
ServerConfigTemplateContent = Helpers.GetConfigContent(serverType, "NtlmAuthentication.config", nginxConfig: null),
SiteName = "NtlmAuthenticationTestSite", // This is configured in the NtlmAuthentication.config
@ -55,16 +54,16 @@ namespace ServerComparison.FunctionalTests
ApplicationType = applicationType
};
if(applicationType == ApplicationType.Standalone)
if (applicationType == ApplicationType.Standalone)
{
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 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.
var response = await RetryHelper.RetryRequest(() =>
@ -77,16 +76,19 @@ namespace ServerComparison.FunctionalTests
{
Assert.Equal("Hello World", responseText);
logger.LogInformation("Testing /Anonymous");
response = await httpClient.GetAsync("/Anonymous");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("Anonymous?True", responseText);
logger.LogInformation("Testing /Restricted");
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());
logger.LogInformation("Testing /RestrictedNTLM");
response = await httpClient.GetAsync("/RestrictedNTLM");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
@ -102,26 +104,32 @@ namespace ServerComparison.FunctionalTests
Assert.Contains("Negotiate", response.Headers.WwwAuthenticate.ToString());
}
logger.LogInformation("Testing /Forbidden");
response = await httpClient.GetAsync("/Forbidden");
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
logger.LogInformation("Enabling Default Credentials");
httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
httpClient = new HttpClient(httpClientHandler) { BaseAddress = new Uri(deploymentResult.ApplicationBaseUri) };
logger.LogInformation("Testing /AutoForbid");
response = await httpClient.GetAsync("/AutoForbid");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
logger.LogInformation("Testing /Restricted");
response = await httpClient.GetAsync("/Restricted");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Negotiate", responseText);
logger.LogInformation("Testing /RestrictedNegotiate");
response = await httpClient.GetAsync("/RestrictedNegotiate");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Negotiate", responseText);
logger.LogInformation("Testing /RestrictedNTLM");
if (serverType == ServerType.WebListener)
{
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.
using System;
@ -8,6 +8,7 @@ using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
@ -20,7 +21,6 @@ using Xunit.Sdk;
namespace ServerComparison.FunctionalTests
{
// Uses ports ranging 5100 - 5130.
public class ResponseCompressionTests
{
// NGinx's default min size is 20 bytes
@ -35,108 +35,107 @@ namespace ServerComparison.FunctionalTests
[ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5100/", ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5101/", ApplicationType.Portable)]
public Task ResponseCompression_Windows_NoCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
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]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5102/", ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5103/", ApplicationType.Standalone)]
public Task ResponseCompression_Kestrel_NoCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5103/", ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5104/", ApplicationType.Standalone)]
public Task ResponseCompression_Nginx_NoCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5105/", ApplicationType.Portable)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5106/", ApplicationType.Standalone)]
public Task ResponseCompression_Windows_HostCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5107/", ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5108/", ApplicationType.Standalone)]
public Task ResponseCompression_Nginx_HostCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5109/", ApplicationType.Standalone)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5110/", ApplicationType.Portable)]
public Task ResponseCompression_Windows_AppCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
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]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5111/", ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5112/", ApplicationType.Standalone)]
public Task ResponseCompression_Kestrel_AppCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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")]
[OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5113/", ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5114/", ApplicationType.Standalone)]
public Task ResponseCompression_Nginx_AppCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5115/", ApplicationType.Standalone)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5116/", ApplicationType.Portable)]
public Task ResponseCompression_Windows_AppAndHostCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
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]
[OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5117/", ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5118/", ApplicationType.Standalone)]
public Task ResponseCompression_Nginx_AppAndHostCompression(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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);
Console.WriteLine("Running test for " + loggerName);
var logger = new LoggerFactory()
.AddXunit(_output)
.CreateLogger(loggerName);
testName = $"{testName}_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}";
var loggerFactory = TestLoggingUtilities.SetUpLogging<ResponseCompressionTests>(_output, testName);
var logger = loggerFactory.CreateLogger("TestHarness");
Console.WriteLine($"Starting test: {testName}");
logger.LogInformation("Starting test: {testName}", testName);
using (logger.BeginScope("ResponseCompressionTest"))
using (logger.BeginScope("ResponseCompression"))
{
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture)
{
ApplicationBaseUriHint = applicationBaseUrl,
EnvironmentName = "ResponseCompression",
ServerConfigTemplateContent = Helpers.GetConfigContent(serverType,
hostCompression ? "http.config" : "NoCompression.config",
@ -151,12 +150,12 @@ namespace ServerComparison.FunctionalTests
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 };
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.
var response = await RetryHelper.RetryRequest(() =>
@ -179,10 +178,14 @@ namespace ServerComparison.FunctionalTests
await scenario(httpClient, logger);
}
}
Console.WriteLine($"Finished test: {testName}");
logger.LogInformation("Finished test: {testName}", testName);
}
private static async Task CheckNoCompressionAsync(HttpClient client, ILogger logger)
{
logger.LogInformation("Testing /NoAppCompression");
var request = new HttpRequestMessage(HttpMethod.Get, "NoAppCompression");
request.Headers.AcceptEncoding.ParseAdd("gzip,deflate");
var response = await client.SendAsync(request);
@ -214,6 +217,7 @@ namespace ServerComparison.FunctionalTests
private static async Task CheckCompressionAsync(HttpClient client, string url, ILogger logger)
{
// Manage the compression manually because HttpClient removes the Content-Encoding header when decompressing.
logger.LogInformation($"Testing /{url}");
var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.AcceptEncoding.ParseAdd("gzip,deflate");
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.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
@ -17,7 +18,6 @@ using Xunit.Sdk;
namespace ServerComparison.FunctionalTests
{
// Uses ports ranging 5080 - 5099.
public class ResponseTests
{
private readonly ITestOutputHelper _output;
@ -30,151 +30,150 @@ namespace ServerComparison.FunctionalTests
[ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5080/", ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5081/", ApplicationType.Portable)]
public Task ResponseFormats_Windows_ContentLength(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
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]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5082/", ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5083/", ApplicationType.Standalone)]
public Task ResponseFormats_Kestrel_ContentLength(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5084/", ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5085/", ApplicationType.Standalone)]
public Task ResponseFormats_Nginx_ContentLength(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Linux)]
[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
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]
[OSSkipCondition(OperatingSystems.Linux)]
[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
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]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5088/", ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5089/", ApplicationType.Standalone)]
public Task ResponseFormats_Kestrel_Http10ConnectionClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5088/", ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5089/", ApplicationType.Standalone)]
public Task ResponseFormats_Kestrel_Http11ConnectionClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5090/", ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5091/", ApplicationType.Portable)]
public Task ResponseFormats_Windows_Chunked(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
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]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5092/", ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5093/", ApplicationType.Standalone)]
public Task ResponseFormats_Kestrel_Chunked(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5094/", ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5095/", ApplicationType.Standalone)]
public Task ResponseFormats_Nginx_Chunked(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5096/", ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5097/", ApplicationType.Portable)]
public Task ResponseFormats_Windows_ManuallyChunk(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
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]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5098/", ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5099/", ApplicationType.Standalone)]
public Task ResponseFormats_Kestrel_ManuallyChunk(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Windows)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5100/", ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5101/", ApplicationType.Standalone)]
public Task ResponseFormats_Nginx_ManuallyChunk(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Nginx, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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]
[OSSkipCondition(OperatingSystems.Linux)]
[OSSkipCondition(OperatingSystems.MacOSX)]
// [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5102/", ApplicationType.Portable)] // https://github.com/aspnet/IISIntegration/issues/7
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, "http://localhost:5103/", ApplicationType.Portable)]
public Task ResponseFormats_Windows_ManuallyChunkAndClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
// [InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)] // https://github.com/aspnet/IISIntegration/issues/7
[InlineData(ServerType.WebListener, RuntimeFlavor.Clr, RuntimeArchitecture.x64, ApplicationType.Portable)]
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]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5104/", ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, "http://localhost:5104/", ApplicationType.Standalone)]
public Task ResponseFormats_Kestrel_ManuallyChunkAndClose(ServerType serverType, RuntimeFlavor runtimeFlavor, RuntimeArchitecture architecture, string applicationBaseUrl, ApplicationType applicationType)
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Portable)]
[InlineData(ServerType.Kestrel, RuntimeFlavor.CoreClr, RuntimeArchitecture.x64, ApplicationType.Standalone)]
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);
Console.WriteLine("Running test for " + loggerName);
var logger = new LoggerFactory()
.AddXunit(_output)
.CreateLogger(loggerName);
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);
using (logger.BeginScope("ResponseFormatsTest"))
using (logger.BeginScope("ResponseFormats"))
{
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture)
{
ApplicationBaseUriHint = applicationBaseUrl,
EnvironmentName = "Responses",
ServerConfigTemplateContent = Helpers.GetConfigContent(serverType, "Http.config", "nginx.conf"),
SiteName = "HttpTestSite", // This is configured in the Http.config
@ -187,11 +186,11 @@ namespace ServerComparison.FunctionalTests
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 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.
var response = await RetryHelper.RetryRequest(() =>
@ -214,10 +213,14 @@ namespace ServerComparison.FunctionalTests
await scenario(httpClient, logger);
}
}
Console.WriteLine($"Finished test: {testName}");
logger.LogInformation("Finished test: {testName}", testName);
}
private static async Task CheckContentLengthAsync(HttpClient client, ILogger logger)
{
logger.LogInformation("Testing ContentLength");
var response = await client.GetAsync("contentlength");
var responseText = await response.Content.ReadAsStringAsync();
try
@ -237,6 +240,7 @@ namespace ServerComparison.FunctionalTests
private static async Task CheckHttp11ConnectionCloseAsync(HttpClient client, ILogger logger)
{
logger.LogInformation("Testing Http11ConnectionClose");
var response = await client.GetAsync("connectionclose");
var responseText = await response.Content.ReadAsStringAsync();
try
@ -256,6 +260,7 @@ namespace ServerComparison.FunctionalTests
private static async Task CheckHttp10ConnectionCloseAsync(HttpClient client, ILogger logger)
{
logger.LogInformation("Testing Http10ConnectionClose");
var requestMessage = new HttpRequestMessage(HttpMethod.Get, "connectionclose")
{
Version = new Version(1, 0)
@ -280,6 +285,7 @@ namespace ServerComparison.FunctionalTests
private static async Task CheckChunkedAsync(HttpClient client, ILogger logger)
{
logger.LogInformation("Testing Chunked");
var response = await client.GetAsync("chunked");
var responseText = await response.Content.ReadAsStringAsync();
try
@ -299,6 +305,7 @@ namespace ServerComparison.FunctionalTests
private static async Task CheckManuallyChunkedAsync(HttpClient client, ILogger logger)
{
logger.LogInformation("Testing ManuallyChunked");
var response = await client.GetAsync("manuallychunked");
var responseText = await response.Content.ReadAsStringAsync();
try
@ -318,6 +325,7 @@ namespace ServerComparison.FunctionalTests
private static async Task CheckManuallyChunkedAndCloseAsync(HttpClient client, ILogger logger)
{
logger.LogInformation("Testing ManuallyChunkedAndClose");
var response = await client.GetAsync("manuallychunkedandclose");
var responseText = await response.Content.ReadAsStringAsync();
try

View File

@ -15,13 +15,15 @@
<ItemGroup>
<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.Testing" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Dotnet.PlatformAbstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.Net.Http.Headers" Version="$(AspNetCoreVersion)" />
<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.runner.visualstudio" Version="$(XunitVersion)" />
</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];
user [user];
error_log [errorlog];
worker_processes 4;
pid [pidFile];