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>

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

@ -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,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];