Merge remote-tracking branch 'ServerTests/rybrande/release22ToSrc' into rybrande/Mondo2.2
This commit is contained in:
commit
7a9e1f9ec9
|
|
@ -1,7 +1,10 @@
|
||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">$(MicrosoftNETCoreApp20PackageVersion)</RuntimeFrameworkVersion>
|
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">$(MicrosoftNETCoreApp20PackageVersion)</RuntimeFrameworkVersion>
|
||||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">$(MicrosoftNETCoreApp21PackageVersion)</RuntimeFrameworkVersion>
|
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">$(MicrosoftNETCoreApp21PackageVersion)</RuntimeFrameworkVersion>
|
||||||
|
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.2' ">$(MicrosoftNETCoreApp22PackageVersion)</RuntimeFrameworkVersion>
|
||||||
<NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
|
<NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
|
||||||
|
<!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->
|
||||||
|
<NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ VisualStudioVersion = 15.0.27130.2036
|
||||||
MinimumVisualStudioVersion = 15.0.26730.03
|
MinimumVisualStudioVersion = 15.0.26730.03
|
||||||
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
|
||||||
|
.appveyor.yml = .appveyor.yml
|
||||||
|
.travis.yml = .travis.yml
|
||||||
Directory.Build.props = Directory.Build.props
|
Directory.Build.props = Directory.Build.props
|
||||||
Directory.Build.targets = Directory.Build.targets
|
Directory.Build.targets = Directory.Build.targets
|
||||||
NuGet.config = NuGet.config
|
NuGet.config = NuGet.config
|
||||||
|
|
@ -20,6 +22,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{55694E45
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
build\dependencies.props = build\dependencies.props
|
build\dependencies.props = build\dependencies.props
|
||||||
build\repo.props = build\repo.props
|
build\repo.props = build\repo.props
|
||||||
|
build\sources.props = build\sources.props
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
|
|
|
||||||
|
|
@ -2,38 +2,33 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Label="Package Versions">
|
||||||
<!-- These package versions may be overridden or updated by automation. -->
|
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview2-20181004.6</InternalAspNetCoreSdkPackageVersion>
|
||||||
<PropertyGroup Label="Package Versions: Auto">
|
<MicrosoftAspNetCoreAspNetCoreModulePackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAspNetCoreModulePackageVersion>
|
||||||
<InternalAspNetCoreSdkPackageVersion>2.1.3-rtm-15802</InternalAspNetCoreSdkPackageVersion>
|
<MicrosoftAspNetCoreAspNetCoreModuleV2PackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAspNetCoreModuleV2PackageVersion>
|
||||||
<MicrosoftAspNetCoreAspNetCoreModulePackageVersion>2.1.1</MicrosoftAspNetCoreAspNetCoreModulePackageVersion>
|
<MicrosoftAspNetCoreResponseCompressionPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreResponseCompressionPackageVersion>
|
||||||
<MicrosoftAspNetCoreAspNetCoreModuleV1PackageVersion>2.1.1</MicrosoftAspNetCoreAspNetCoreModuleV1PackageVersion>
|
<MicrosoftAspNetCoreServerHttpSysPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerHttpSysPackageVersion>
|
||||||
<MicrosoftAspNetCoreResponseCompressionPackageVersion>2.1.1</MicrosoftAspNetCoreResponseCompressionPackageVersion>
|
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
|
||||||
<MicrosoftAspNetCoreServerHttpSysPackageVersion>2.1.1</MicrosoftAspNetCoreServerHttpSysPackageVersion>
|
<MicrosoftAspNetCoreServerIISPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerIISPackageVersion>
|
||||||
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.1.1</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
|
<MicrosoftAspNetCoreServerIntegrationTestingIISPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerIntegrationTestingIISPackageVersion>
|
||||||
<MicrosoftAspNetCoreServerIISPackageVersion>2.1.1</MicrosoftAspNetCoreServerIISPackageVersion>
|
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerKestrelPackageVersion>
|
||||||
<MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>0.5.1</MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>
|
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
|
||||||
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.1.2</MicrosoftAspNetCoreServerKestrelPackageVersion>
|
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||||
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.1.1</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
|
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.1.1</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
<MicrosoftExtensionsLoggingConsolePackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.1.1</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
<MicrosoftExtensionsLoggingPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingPackageVersion>
|
||||||
<MicrosoftExtensionsLoggingConsolePackageVersion>2.1.1</MicrosoftExtensionsLoggingConsolePackageVersion>
|
<MicrosoftExtensionsLoggingTestingPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||||
<MicrosoftExtensionsLoggingPackageVersion>2.1.1</MicrosoftExtensionsLoggingPackageVersion>
|
<MicrosoftNETCoreApp20PackageVersion>2.0.9</MicrosoftNETCoreApp20PackageVersion>
|
||||||
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.1</MicrosoftExtensionsLoggingTestingPackageVersion>
|
<MicrosoftNETCoreApp21PackageVersion>2.1.3</MicrosoftNETCoreApp21PackageVersion>
|
||||||
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
|
<MicrosoftNETCoreApp22PackageVersion>2.2.0-preview3-27001-02</MicrosoftNETCoreApp22PackageVersion>
|
||||||
<MicrosoftNETCoreApp21PackageVersion>2.1.2</MicrosoftNETCoreApp21PackageVersion>
|
<MicrosoftNetHttpHeadersPackageVersion>2.2.0-preview3-35425</MicrosoftNetHttpHeadersPackageVersion>
|
||||||
<MicrosoftNetHttpHeadersPackageVersion>2.1.1</MicrosoftNetHttpHeadersPackageVersion>
|
|
||||||
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
|
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
|
||||||
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
||||||
<SerilogExtensionsLoggingPackageVersion>1.4.0</SerilogExtensionsLoggingPackageVersion>
|
<SerilogExtensionsLoggingPackageVersion>1.4.0</SerilogExtensionsLoggingPackageVersion>
|
||||||
<SerilogSinksFilePackageVersion>3.2.0</SerilogSinksFilePackageVersion>
|
<SerilogSinksFilePackageVersion>4.0.0</SerilogSinksFilePackageVersion>
|
||||||
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
||||||
<XunitRunnerVisualStudioPackageVersion>2.4.0-beta.1.build3945</XunitRunnerVisualStudioPackageVersion>
|
<XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- This may import a generated file which may override the variables above. -->
|
|
||||||
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
|
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
|
||||||
|
|
||||||
<!-- These are package versions that should not be overridden or updated by automation. -->
|
|
||||||
<PropertyGroup Label="Package Versions: Pinned" />
|
<PropertyGroup Label="Package Versions: Pinned" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,12 @@
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- These properties are use by the automation that updates dependencies.props -->
|
<!-- These properties are use by the automation that updates dependencies.props -->
|
||||||
<LineupPackageId>Internal.AspNetCore.Universe.Lineup</LineupPackageId>
|
<LineupPackageId>Internal.AspNetCore.Universe.Lineup</LineupPackageId>
|
||||||
<LineupPackageVersion>2.1.0-rc1-*</LineupPackageVersion>
|
<LineupPackageVersion>2.2.0-*</LineupPackageVersion>
|
||||||
<LineupPackageRestoreSource>https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json</LineupPackageRestoreSource>
|
<LineupPackageRestoreSource>https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json</LineupPackageRestoreSource>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp20PackageVersion)" />
|
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp22PackageVersion)" />
|
||||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp21PackageVersion)" />
|
<DotNetCoreRuntime Condition="'$(OS)' == 'Windows_NT'" Include="$(MicrosoftNETCoreApp22PackageVersion)" Arch="x86" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
curl -sSL http://nginx.org/download/nginx-1.8.0.tar.gz | tar zxfv - -C /tmp && cd /tmp/nginx-1.8.0/
|
|
||||||
./configure --prefix=$HOME/nginxinstall --with-http_ssl_module
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
|
|
@ -1,118 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
|
||||||
using Microsoft.AspNetCore.Testing.xunit;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.Logging.Testing;
|
|
||||||
using Xunit;
|
|
||||||
using Xunit.Abstractions;
|
|
||||||
using Xunit.Sdk;
|
|
||||||
|
|
||||||
namespace ServerComparison.FunctionalTests
|
|
||||||
{
|
|
||||||
public class HelloWorldTests : LoggedTest
|
|
||||||
{
|
|
||||||
public HelloWorldTests(ITestOutputHelper output) : base(output)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task HelloWorld_WebListener(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return HelloWorld(ServerType.WebListener, runtimeFlavor, RuntimeArchitecture.x64, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V1", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
public Task HelloWorld_IISExpress(RuntimeFlavor runtimeFlavor, ApplicationType applicationType, HostingModel hostingModel, string additionalPublishParameters)
|
|
||||||
{
|
|
||||||
return HelloWorld(ServerType.IISExpress, runtimeFlavor, RuntimeArchitecture.x64, applicationType, hostingModel: hostingModel, additionalPublishParameters: additionalPublishParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable)]
|
|
||||||
public Task HelloWorld_Kestrel_Clr(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return HelloWorld(ServerType.Kestrel, runtimeFlavor, RuntimeArchitecture.x64, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task HelloWorld_Kestrel(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return HelloWorld(ServerType.Kestrel, runtimeFlavor, RuntimeArchitecture.x64, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Windows)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task HelloWorld_Nginx(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return HelloWorld(ServerType.Nginx, runtimeFlavor, RuntimeArchitecture.x64, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private async Task HelloWorld(ServerType serverType,
|
|
||||||
RuntimeFlavor runtimeFlavor,
|
|
||||||
RuntimeArchitecture architecture,
|
|
||||||
ApplicationType applicationType,
|
|
||||||
[CallerMemberName] string testName = null,
|
|
||||||
HostingModel hostingModel = HostingModel.OutOfProcess,
|
|
||||||
string additionalPublishParameters = "")
|
|
||||||
{
|
|
||||||
testName = $"{testName}_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}";
|
|
||||||
using (StartLog(out var loggerFactory, testName))
|
|
||||||
{
|
|
||||||
var logger = loggerFactory.CreateLogger("HelloWorld");
|
|
||||||
|
|
||||||
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture)
|
|
||||||
{
|
|
||||||
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
|
|
||||||
TargetFramework = Helpers.GetTargetFramework(runtimeFlavor),
|
|
||||||
ApplicationType = applicationType,
|
|
||||||
HostingModel = hostingModel,
|
|
||||||
AdditionalPublishParameters = additionalPublishParameters
|
|
||||||
};
|
|
||||||
|
|
||||||
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
|
|
||||||
{
|
|
||||||
var deploymentResult = await deployer.DeployAsync();
|
|
||||||
|
|
||||||
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
|
||||||
var response = await RetryHelper.RetryRequest(() =>
|
|
||||||
{
|
|
||||||
return deploymentResult.HttpClient.GetAsync(string.Empty);
|
|
||||||
}, logger, deploymentResult.HostShutdownToken);
|
|
||||||
|
|
||||||
var responseText = await response.Content.ReadAsStringAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assert.Equal("Hello World", responseText);
|
|
||||||
}
|
|
||||||
catch (XunitException)
|
|
||||||
{
|
|
||||||
logger.LogWarning(response.ToString());
|
|
||||||
logger.LogWarning(responseText);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,331 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
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;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.Logging.Testing;
|
|
||||||
using Microsoft.Net.Http.Headers;
|
|
||||||
using Xunit;
|
|
||||||
using Xunit.Abstractions;
|
|
||||||
using Xunit.Sdk;
|
|
||||||
|
|
||||||
namespace ServerComparison.FunctionalTests
|
|
||||||
{
|
|
||||||
public class ResponseCompressionTests : LoggedTest
|
|
||||||
{
|
|
||||||
// NGinx's default min size is 20 bytes
|
|
||||||
private static readonly string HelloWorldBody = "Hello World;" + new string('a', 20);
|
|
||||||
|
|
||||||
public ResponseCompressionTests(ITestOutputHelper output) : base(output)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// IIS Express
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
public Task ResponseCompression_IISExpress_NoCompression(RuntimeFlavor runtimeFlavor, ApplicationType applicationType, HostingModel hostingModel, string additionalPublishParameters)
|
|
||||||
{
|
|
||||||
return ResponseCompression(ServerType.IISExpress,
|
|
||||||
runtimeFlavor,
|
|
||||||
RuntimeArchitecture.x64,
|
|
||||||
CheckNoCompressionAsync,
|
|
||||||
applicationType,
|
|
||||||
hostCompression: false,
|
|
||||||
hostingModel: hostingModel,
|
|
||||||
additionalPublishParameters: additionalPublishParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
public Task ResponseCompression_IISExpress_HostCompression(RuntimeFlavor runtimeFlavor, ApplicationType applicationType, HostingModel hostingModel, string additionalPublishParameters)
|
|
||||||
{
|
|
||||||
return ResponseCompression(ServerType.IISExpress,
|
|
||||||
runtimeFlavor,
|
|
||||||
RuntimeArchitecture.x64,
|
|
||||||
CheckHostCompressionAsync,
|
|
||||||
applicationType,
|
|
||||||
hostCompression: true,
|
|
||||||
hostingModel: hostingModel,
|
|
||||||
additionalPublishParameters: additionalPublishParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory(Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
public Task ResponseCompression_IISExpress_AppCompression(RuntimeFlavor runtimeFlavor, ApplicationType applicationType, HostingModel hostingModel, string additionalPublishParameters)
|
|
||||||
{
|
|
||||||
return ResponseCompression(ServerType.IISExpress,
|
|
||||||
runtimeFlavor,
|
|
||||||
RuntimeArchitecture.x64,
|
|
||||||
CheckAppCompressionAsync,
|
|
||||||
applicationType,
|
|
||||||
hostCompression: true,
|
|
||||||
hostingModel: hostingModel,
|
|
||||||
additionalPublishParameters: additionalPublishParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
public Task ResponseCompression_IISExpress_AppAndHostCompression(RuntimeFlavor runtimeFlavor, ApplicationType applicationType, HostingModel hostingModel, string additionalPublishParameters)
|
|
||||||
{
|
|
||||||
return ResponseCompression(ServerType.IISExpress,
|
|
||||||
runtimeFlavor,
|
|
||||||
RuntimeArchitecture.x64,
|
|
||||||
CheckAppCompressionAsync,
|
|
||||||
applicationType,
|
|
||||||
hostCompression: true,
|
|
||||||
hostingModel: hostingModel,
|
|
||||||
additionalPublishParameters: additionalPublishParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebListener
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseCompression_WebListener_NoCompression(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseCompression(ServerType.WebListener, runtimeFlavor, RuntimeArchitecture.x64, CheckNoCompressionAsync, applicationType, hostCompression: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebListener doesn't support HostCompression
|
|
||||||
// "The archive entry was compressed using an unsupported compression method."
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseCompression_WebListener_AppCompression(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseCompression(ServerType.WebListener, runtimeFlavor, RuntimeArchitecture.x64, CheckAppCompressionAsync, applicationType, hostCompression: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseCompression_WebListener_AppAndHostCompression(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseCompression(ServerType.WebListener, runtimeFlavor, RuntimeArchitecture.x64, CheckAppCompressionAsync, applicationType, hostCompression: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kestrel
|
|
||||||
[Theory]
|
|
||||||
[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, CheckNoCompressionAsync, applicationType, hostCompression: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[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, CheckAppCompressionAsync, applicationType, hostCompression: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nginx
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Windows)]
|
|
||||||
[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, CheckNoCompressionAsync, applicationType, hostCompression: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Windows)]
|
|
||||||
[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, CheckHostCompressionAsync, applicationType, hostCompression: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory(Skip = "No pass-through compression https://github.com/aspnet/BasicMiddleware/issues/123")]
|
|
||||||
[OSSkipCondition(OperatingSystems.Windows)]
|
|
||||||
[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, CheckHostCompressionAsync, applicationType, hostCompression: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Windows)]
|
|
||||||
[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, CheckAppCompressionAsync, applicationType, hostCompression: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ResponseCompression(ServerType serverType,
|
|
||||||
RuntimeFlavor runtimeFlavor,
|
|
||||||
RuntimeArchitecture architecture,
|
|
||||||
Func<HttpClient, ILogger, Task> scenario,
|
|
||||||
ApplicationType applicationType,
|
|
||||||
bool hostCompression,
|
|
||||||
[CallerMemberName] string testName = null,
|
|
||||||
HostingModel hostingModel = HostingModel.OutOfProcess,
|
|
||||||
string additionalPublishParameters = "")
|
|
||||||
{
|
|
||||||
testName = $"{testName}_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}";
|
|
||||||
using (StartLog(out var loggerFactory, testName))
|
|
||||||
{
|
|
||||||
var logger = loggerFactory.CreateLogger("ResponseCompression");
|
|
||||||
|
|
||||||
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture)
|
|
||||||
{
|
|
||||||
EnvironmentName = "ResponseCompression",
|
|
||||||
ServerConfigTemplateContent = Helpers.GetConfigContent(serverType,
|
|
||||||
hostCompression ? "http.config" : "NoCompression.config",
|
|
||||||
hostCompression ? "nginx.conf" : "NoCompression.conf"),
|
|
||||||
SiteName = "HttpTestSite", // This is configured in the Http.config
|
|
||||||
TargetFramework = Helpers.GetTargetFramework(runtimeFlavor),
|
|
||||||
ApplicationType = applicationType,
|
|
||||||
HostingModel = hostingModel,
|
|
||||||
AdditionalPublishParameters = additionalPublishParameters
|
|
||||||
};
|
|
||||||
|
|
||||||
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
|
|
||||||
{
|
|
||||||
var deploymentResult = await deployer.DeployAsync();
|
|
||||||
var httpClientHandler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.None };
|
|
||||||
Assert.True(httpClientHandler.SupportsAutomaticDecompression);
|
|
||||||
var httpClient = deploymentResult.CreateHttpClient(httpClientHandler);
|
|
||||||
|
|
||||||
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
|
||||||
var response = await RetryHelper.RetryRequest(() =>
|
|
||||||
{
|
|
||||||
return httpClient.GetAsync(string.Empty);
|
|
||||||
}, logger, deploymentResult.HostShutdownToken);
|
|
||||||
|
|
||||||
var responseText = await response.Content.ReadAsStringAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assert.Equal("Running", responseText);
|
|
||||||
}
|
|
||||||
catch (XunitException)
|
|
||||||
{
|
|
||||||
logger.LogWarning(response.ToString());
|
|
||||||
logger.LogWarning(responseText);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
await scenario(httpClient, logger);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
var responseText = await response.Content.ReadAsStringAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assert.Equal(HelloWorldBody, responseText);
|
|
||||||
Assert.Equal(HelloWorldBody.Length.ToString(), GetContentLength(response));
|
|
||||||
Assert.Equal(0, response.Content.Headers.ContentEncoding.Count);
|
|
||||||
}
|
|
||||||
catch (XunitException)
|
|
||||||
{
|
|
||||||
logger.LogWarning(response.ToString());
|
|
||||||
logger.LogWarning(responseText);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Task CheckHostCompressionAsync(HttpClient client, ILogger logger)
|
|
||||||
{
|
|
||||||
return CheckCompressionAsync(client, "NoAppCompression", logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Task CheckAppCompressionAsync(HttpClient client, ILogger logger)
|
|
||||||
{
|
|
||||||
return CheckCompressionAsync(client, "AppCompression", 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.
|
|
||||||
logger.LogInformation($"Testing /{url}");
|
|
||||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
|
||||||
request.Headers.AcceptEncoding.ParseAdd("gzip,deflate");
|
|
||||||
var response = await client.SendAsync(request);
|
|
||||||
var responseText = await response.Content.ReadAsStringAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
responseText = await ReadCompressedAsStringAsync(response.Content);
|
|
||||||
Assert.Equal(HelloWorldBody, responseText);
|
|
||||||
Assert.Equal(1, response.Content.Headers.ContentEncoding.Count);
|
|
||||||
Assert.Equal("gzip", response.Content.Headers.ContentEncoding.First());
|
|
||||||
}
|
|
||||||
catch (XunitException)
|
|
||||||
{
|
|
||||||
logger.LogWarning(response.ToString());
|
|
||||||
logger.LogWarning(responseText);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetContentLength(HttpResponseMessage response)
|
|
||||||
{
|
|
||||||
// Don't use response.Content.Headers.ContentLength, it will dynamically calculate the value if it can.
|
|
||||||
return response.Content.Headers.TryGetValues(HeaderNames.ContentLength, out var values) ? values.FirstOrDefault() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<string> ReadCompressedAsStringAsync(HttpContent content)
|
|
||||||
{
|
|
||||||
using (var stream = await content.ReadAsStreamAsync())
|
|
||||||
using (var compressStream = new GZipStream(stream, CompressionMode.Decompress))
|
|
||||||
using (var reader = new StreamReader(compressStream))
|
|
||||||
{
|
|
||||||
return await reader.ReadToEndAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,406 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.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;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.Logging.Testing;
|
|
||||||
using Microsoft.Net.Http.Headers;
|
|
||||||
using Xunit;
|
|
||||||
using Xunit.Abstractions;
|
|
||||||
using Xunit.Sdk;
|
|
||||||
|
|
||||||
namespace ServerComparison.FunctionalTests
|
|
||||||
{
|
|
||||||
public class ResponseTests : LoggedTest
|
|
||||||
{
|
|
||||||
public ResponseTests(ITestOutputHelper output) : base(output)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// IIS Express
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable, HostingModel.OutOfProcess, "", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
public Task ResponseFormats_IISExpress_ContentLength(RuntimeFlavor runtimeFlavor, ApplicationType applicationType, HostingModel hostingModel, string additionalPublishParameters)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.IISExpress, runtimeFlavor, RuntimeArchitecture.x64, CheckContentLengthAsync, applicationType, hostingModel: hostingModel, additionalPublishParameters: additionalPublishParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable, HostingModel.OutOfProcess, "", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
public Task ResponseFormats_IISExpress_Chunked(RuntimeFlavor runtimeFlavor, ApplicationType applicationType, HostingModel hostingModel, string additionalPublishParameters)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.IISExpress, runtimeFlavor, RuntimeArchitecture.x64, CheckChunkedAsync, applicationType, hostingModel: hostingModel, additionalPublishParameters: additionalPublishParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable, HostingModel.OutOfProcess, "", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
public Task ResponseFormats_IIS_ManuallyChunk(RuntimeFlavor runtimeFlavor, ApplicationType applicationType, HostingModel hostingModel, string additionalPublishParameters)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.IISExpress, runtimeFlavor, RuntimeArchitecture.x64, CheckManuallyChunkedAsync, applicationType, hostingModel: hostingModel, additionalPublishParameters: additionalPublishParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Weblistener
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_WebListener_ContentLength(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.WebListener, runtimeFlavor, RuntimeArchitecture.x64, CheckContentLengthAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_WebListener_Chunked(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.WebListener, runtimeFlavor, RuntimeArchitecture.x64, CheckChunkedAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
// IIS will remove the "Connection: close" header https://github.com/aspnet/IISIntegration/issues/7
|
|
||||||
public Task ResponseFormats_WebListener_Http10ConnectionClose(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.WebListener, runtimeFlavor, RuntimeArchitecture.x64, CheckHttp10ConnectionCloseAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)] // https://github.com/aspnet/WebListener/issues/259
|
|
||||||
// IIS will remove the "Connection: close" header https://github.com/aspnet/IISIntegration/issues/7
|
|
||||||
public Task ResponseFormats_WebListener_Http11ConnectionClose(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.WebListener, runtimeFlavor, RuntimeArchitecture.x64, CheckHttp11ConnectionCloseAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_WebListener_ManuallyChunk(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.WebListener, runtimeFlavor, RuntimeArchitecture.x64, CheckManuallyChunkedAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
|
||||||
[InlineData(RuntimeFlavor.Clr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_WebListener_ManuallyChunkAndClose(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.WebListener, runtimeFlavor, RuntimeArchitecture.x64, CheckManuallyChunkedAndCloseAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kestrel
|
|
||||||
[Theory]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_Kestrel_ContentLength(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.Kestrel, runtimeFlavor, RuntimeArchitecture.x64, CheckContentLengthAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_Kestrel_Http10ConnectionClose(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.Kestrel, runtimeFlavor, RuntimeArchitecture.x64, CheckHttp10ConnectionCloseAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_Kestrel_Http11ConnectionClose(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.Kestrel, runtimeFlavor, RuntimeArchitecture.x64, CheckHttp11ConnectionCloseAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_Kestrel_Chunked(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.Kestrel, runtimeFlavor, RuntimeArchitecture.x64, CheckChunkedAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_Kestrel_ManuallyChunk(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.Kestrel, runtimeFlavor, RuntimeArchitecture.x64, CheckManuallyChunkedAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_Kestrel_ManuallyChunkAndClose(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.Kestrel, runtimeFlavor, RuntimeArchitecture.x64, CheckManuallyChunkedAndCloseAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nginx
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Windows)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_Nginx_ContentLength( RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.Nginx, runtimeFlavor, RuntimeArchitecture.x64, CheckContentLengthAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Windows)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_Nginx_Chunked(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.Nginx, runtimeFlavor, RuntimeArchitecture.x64, CheckChunkedAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[ConditionalTheory]
|
|
||||||
[OSSkipCondition(OperatingSystems.Windows)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Portable)]
|
|
||||||
[InlineData(RuntimeFlavor.CoreClr, ApplicationType.Standalone)]
|
|
||||||
public Task ResponseFormats_Nginx_ManuallyChunk(RuntimeFlavor runtimeFlavor, ApplicationType applicationType)
|
|
||||||
{
|
|
||||||
return ResponseFormats(ServerType.Nginx, runtimeFlavor, RuntimeArchitecture.x64, CheckManuallyChunkedAsync, applicationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ResponseFormats(ServerType serverType,
|
|
||||||
RuntimeFlavor runtimeFlavor,
|
|
||||||
RuntimeArchitecture architecture,
|
|
||||||
Func<HttpClient, ILogger, Task> scenario,
|
|
||||||
ApplicationType applicationType,
|
|
||||||
[CallerMemberName] string testName = null,
|
|
||||||
HostingModel hostingModel = HostingModel.OutOfProcess,
|
|
||||||
string additionalPublishParameters = "")
|
|
||||||
{
|
|
||||||
testName = $"{testName}_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}";
|
|
||||||
using (StartLog(out var loggerFactory, testName))
|
|
||||||
{
|
|
||||||
var logger = loggerFactory.CreateLogger("ResponseFormats");
|
|
||||||
|
|
||||||
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture)
|
|
||||||
{
|
|
||||||
EnvironmentName = "Responses",
|
|
||||||
ServerConfigTemplateContent = Helpers.GetConfigContent(serverType, "Http.config", "nginx.conf"),
|
|
||||||
SiteName = "HttpTestSite", // This is configured in the Http.config
|
|
||||||
TargetFramework = Helpers.GetTargetFramework(runtimeFlavor),
|
|
||||||
ApplicationType = applicationType,
|
|
||||||
HostingModel = hostingModel,
|
|
||||||
AdditionalPublishParameters = additionalPublishParameters
|
|
||||||
};
|
|
||||||
|
|
||||||
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
|
|
||||||
{
|
|
||||||
var deploymentResult = await deployer.DeployAsync();
|
|
||||||
|
|
||||||
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
|
||||||
var response = await RetryHelper.RetryRequest(() =>
|
|
||||||
{
|
|
||||||
return deploymentResult.HttpClient.GetAsync(string.Empty);
|
|
||||||
}, logger, deploymentResult.HostShutdownToken);
|
|
||||||
|
|
||||||
var responseText = await response.Content.ReadAsStringAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assert.Equal("Running", responseText);
|
|
||||||
}
|
|
||||||
catch (XunitException)
|
|
||||||
{
|
|
||||||
logger.LogWarning(response.ToString());
|
|
||||||
logger.LogWarning(responseText);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
await scenario(deploymentResult.HttpClient, logger);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task CheckContentLengthAsync(HttpClient client, ILogger logger)
|
|
||||||
{
|
|
||||||
logger.LogInformation("Testing ContentLength");
|
|
||||||
var requestMessage = new HttpRequestMessage(HttpMethod.Get, "contentlength")
|
|
||||||
{
|
|
||||||
Version = new Version(1, 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = await client.SendAsync(requestMessage);
|
|
||||||
var responseText = await response.Content.ReadAsStringAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assert.Equal("Content Length", responseText);
|
|
||||||
Assert.Null(response.Headers.TransferEncodingChunked);
|
|
||||||
Assert.Null(response.Headers.ConnectionClose);
|
|
||||||
Assert.Equal("14", GetContentLength(response));
|
|
||||||
}
|
|
||||||
catch (XunitException)
|
|
||||||
{
|
|
||||||
logger.LogWarning(response.ToString());
|
|
||||||
logger.LogWarning(responseText);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
Assert.Equal("Connnection Close", responseText);
|
|
||||||
Assert.True(response.Headers.ConnectionClose, "/connectionclose, closed?");
|
|
||||||
Assert.True(response.Headers.TransferEncodingChunked);
|
|
||||||
Assert.Null(GetContentLength(response));
|
|
||||||
}
|
|
||||||
catch (XunitException)
|
|
||||||
{
|
|
||||||
logger.LogWarning(response.ToString());
|
|
||||||
logger.LogWarning(responseText);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = await client.SendAsync(requestMessage);
|
|
||||||
var responseText = await response.Content.ReadAsStringAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assert.Equal("Connnection Close", responseText);
|
|
||||||
Assert.True(response.Headers.ConnectionClose, "/connectionclose, closed?");
|
|
||||||
Assert.Null(response.Headers.TransferEncodingChunked);
|
|
||||||
Assert.Null(GetContentLength(response));
|
|
||||||
}
|
|
||||||
catch (XunitException)
|
|
||||||
{
|
|
||||||
logger.LogWarning(response.ToString());
|
|
||||||
logger.LogWarning(responseText);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task CheckChunkedAsync(HttpClient client, ILogger logger)
|
|
||||||
{
|
|
||||||
logger.LogInformation("Testing Chunked");
|
|
||||||
var requestMessage = new HttpRequestMessage(HttpMethod.Get, "chunked")
|
|
||||||
{
|
|
||||||
Version = new Version(1, 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = await client.SendAsync(requestMessage);
|
|
||||||
var responseText = await response.Content.ReadAsStringAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assert.Equal("Chunked", responseText);
|
|
||||||
Assert.True(response.Headers.TransferEncodingChunked, "/chunked, chunked?");
|
|
||||||
Assert.Null(response.Headers.ConnectionClose);
|
|
||||||
Assert.Null(GetContentLength(response));
|
|
||||||
}
|
|
||||||
catch (XunitException)
|
|
||||||
{
|
|
||||||
logger.LogWarning(response.ToString());
|
|
||||||
logger.LogWarning(responseText);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task CheckManuallyChunkedAsync(HttpClient client, ILogger logger)
|
|
||||||
{
|
|
||||||
logger.LogInformation("Testing ManuallyChunked");
|
|
||||||
var requestMessage = new HttpRequestMessage(HttpMethod.Get, "manuallychunked")
|
|
||||||
{
|
|
||||||
Version = new Version(1, 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = await client.SendAsync(requestMessage);
|
|
||||||
var responseText = await response.Content.ReadAsStringAsync();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Assert.Equal("Manually Chunked", responseText);
|
|
||||||
Assert.True(response.Headers.TransferEncodingChunked, "/manuallychunked, chunked?");
|
|
||||||
Assert.Null(response.Headers.ConnectionClose);
|
|
||||||
Assert.Null(GetContentLength(response));
|
|
||||||
}
|
|
||||||
catch (XunitException)
|
|
||||||
{
|
|
||||||
logger.LogWarning(response.ToString());
|
|
||||||
logger.LogWarning(responseText);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
{
|
|
||||||
Assert.Equal("Manually Chunked and Close", responseText);
|
|
||||||
Assert.True(response.Headers.TransferEncodingChunked, "/manuallychunkedandclose, chunked?");
|
|
||||||
Assert.True(response.Headers.ConnectionClose, "/manuallychunkedandclose, closed?");
|
|
||||||
Assert.Null(GetContentLength(response));
|
|
||||||
}
|
|
||||||
catch (XunitException)
|
|
||||||
{
|
|
||||||
logger.LogWarning(response.ToString());
|
|
||||||
logger.LogWarning(responseText);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetContentLength(HttpResponseMessage response)
|
|
||||||
{
|
|
||||||
// Don't use response.Content.Headers.ContentLength, it will dynamically calculate the value if it can.
|
|
||||||
IEnumerable<string> values;
|
|
||||||
return response.Content.Headers.TryGetValues(HeaderNames.ContentLength, out values) ? values.FirstOrDefault() : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<configuration>
|
|
||||||
<system.webServer>
|
|
||||||
<handlers>
|
|
||||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
|
|
||||||
</handlers>
|
|
||||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="true"/>
|
|
||||||
</system.webServer>
|
|
||||||
</configuration>
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<Project>
|
<Project>
|
||||||
<Import Project="..\Directory.Build.props" />
|
<Import Project="..\Directory.Build.props" />
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<DeveloperBuildTestTfms>netcoreapp2.1;netcoreapp2.0</DeveloperBuildTestTfms>
|
<DeveloperBuildTestTfms>netcoreapp2.2</DeveloperBuildTestTfms>
|
||||||
<StandardTestTfms>$(DeveloperBuildTestTfms)</StandardTestTfms>
|
<StandardTestTfms>$(DeveloperBuildTestTfms)</StandardTestTfms>
|
||||||
<StandardTestTfms Condition=" '$(DeveloperBuild)' != 'true' AND '$(OS)' == 'Windows_NT' ">$(StandardTestTfms);net461</StandardTestTfms>
|
<StandardTestTfms Condition=" '$(DeveloperBuild)' != 'true' AND '$(OS)' == 'Windows_NT' ">$(StandardTestTfms);net461</StandardTestTfms>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
// 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.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace ServerComparison.FunctionalTests
|
||||||
|
{
|
||||||
|
public class HelloWorldTests : LoggedTest
|
||||||
|
{
|
||||||
|
public HelloWorldTests(ITestOutputHelper output) : base(output)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TestMatrix TestVariants
|
||||||
|
=> TestMatrix.ForServers(ServerType.IISExpress, ServerType.Kestrel, ServerType.Nginx, ServerType.HttpSys)
|
||||||
|
.WithTfms(Tfm.NetCoreApp22, Tfm.Net461)
|
||||||
|
.WithAllApplicationTypes()
|
||||||
|
.WithAllAncmVersions()
|
||||||
|
.WithAllHostingModels()
|
||||||
|
.WithAllArchitectures();
|
||||||
|
|
||||||
|
[ConditionalTheory]
|
||||||
|
[MemberData(nameof(TestVariants))]
|
||||||
|
public async Task HelloWorld(TestVariant variant)
|
||||||
|
{
|
||||||
|
var testName = $"HelloWorld_{variant.Server}_{variant.Tfm}_{variant.Architecture}_{variant.ApplicationType}";
|
||||||
|
using (StartLog(out var loggerFactory, testName))
|
||||||
|
{
|
||||||
|
var logger = loggerFactory.CreateLogger("HelloWorld");
|
||||||
|
|
||||||
|
var deploymentParameters = new DeploymentParameters(variant)
|
||||||
|
{
|
||||||
|
ApplicationPath = Helpers.GetApplicationPath()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (variant.Server == ServerType.Nginx)
|
||||||
|
{
|
||||||
|
deploymentParameters.ServerConfigTemplateContent = Helpers.GetNginxConfigContent("nginx.conf");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var deployer = IISApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
|
||||||
|
{
|
||||||
|
var deploymentResult = await deployer.DeployAsync();
|
||||||
|
|
||||||
|
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
||||||
|
var response = await RetryHelper.RetryRequest(() =>
|
||||||
|
{
|
||||||
|
return deploymentResult.HttpClient.GetAsync(string.Empty);
|
||||||
|
}, logger, deploymentResult.HostShutdownToken);
|
||||||
|
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (variant.Architecture == RuntimeArchitecture.x64)
|
||||||
|
{
|
||||||
|
Assert.Equal("Hello World X64", responseText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.Equal("Hello World X86", responseText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (XunitException)
|
||||||
|
{
|
||||||
|
logger.LogWarning(response.ToString());
|
||||||
|
logger.LogWarning(responseText);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure it was the right server.
|
||||||
|
var serverHeader = response.Headers.Server.ToString();
|
||||||
|
switch (variant.Server)
|
||||||
|
{
|
||||||
|
case ServerType.HttpSys:
|
||||||
|
Assert.Equal("Microsoft-HTTPAPI/2.0", serverHeader);
|
||||||
|
break;
|
||||||
|
case ServerType.Nginx:
|
||||||
|
Assert.StartsWith("nginx/", serverHeader);
|
||||||
|
break;
|
||||||
|
case ServerType.Kestrel:
|
||||||
|
Assert.Equal("Kestrel", serverHeader);
|
||||||
|
break;
|
||||||
|
case ServerType.IIS:
|
||||||
|
case ServerType.IISExpress:
|
||||||
|
if (variant.HostingModel == HostingModel.OutOfProcess)
|
||||||
|
{
|
||||||
|
Assert.Equal("Kestrel", serverHeader);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.StartsWith("Microsoft-IIS/", serverHeader);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException(variant.Server.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,7 +9,7 @@ namespace ServerComparison.FunctionalTests
|
||||||
{
|
{
|
||||||
public class Helpers
|
public class Helpers
|
||||||
{
|
{
|
||||||
public static string GetApplicationPath(ApplicationType applicationType)
|
public static string GetApplicationPath()
|
||||||
{
|
{
|
||||||
var applicationBasePath = AppContext.BaseDirectory;
|
var applicationBasePath = AppContext.BaseDirectory;
|
||||||
|
|
||||||
|
|
@ -29,41 +29,11 @@ namespace ServerComparison.FunctionalTests
|
||||||
throw new Exception($"Solution root could not be found using {applicationBasePath}");
|
throw new Exception($"Solution root could not be found using {applicationBasePath}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetConfigContent(ServerType serverType, string iisConfig, string nginxConfig)
|
public static string GetNginxConfigContent(string nginxConfig)
|
||||||
{
|
{
|
||||||
var applicationBasePath = AppContext.BaseDirectory;
|
var applicationBasePath = AppContext.BaseDirectory;
|
||||||
|
var content = File.ReadAllText(Path.Combine(applicationBasePath, nginxConfig));
|
||||||
string content = null;
|
|
||||||
if (serverType == ServerType.IISExpress)
|
|
||||||
{
|
|
||||||
content = File.ReadAllText(Path.Combine(applicationBasePath, iisConfig));
|
|
||||||
}
|
|
||||||
else if (serverType == ServerType.Nginx)
|
|
||||||
{
|
|
||||||
content = File.ReadAllText(Path.Combine(applicationBasePath, nginxConfig));
|
|
||||||
}
|
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetTargetFramework(RuntimeFlavor runtimeFlavor)
|
|
||||||
{
|
|
||||||
if (runtimeFlavor == RuntimeFlavor.Clr)
|
|
||||||
{
|
|
||||||
return "net461";
|
|
||||||
}
|
|
||||||
else if (runtimeFlavor == RuntimeFlavor.CoreClr)
|
|
||||||
{
|
|
||||||
#if NETCOREAPP2_0
|
|
||||||
return "netcoreapp2.0";
|
|
||||||
#elif NETCOREAPP2_1 || NET461
|
|
||||||
return "netcoreapp2.1";
|
|
||||||
#else
|
|
||||||
#error Target frameworks need to be updated.
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new ArgumentException($"Unknown RuntimeFlavor '{runtimeFlavor}'");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -20,46 +20,28 @@ namespace ServerComparison.FunctionalTests
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TestMatrix TestVariants
|
||||||
|
=> TestMatrix.ForServers(ServerType.IISExpress, ServerType.HttpSys)
|
||||||
|
.WithTfms(Tfm.NetCoreApp22, Tfm.Net461)
|
||||||
|
.WithAllAncmVersions()
|
||||||
|
.WithAllHostingModels();
|
||||||
|
|
||||||
[ConditionalTheory]
|
[ConditionalTheory]
|
||||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
[MemberData(nameof(TestVariants))]
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.Clr, "net461", RuntimeArchitecture.x64, ApplicationType.Portable, HostingModel.OutOfProcess, "V2", Skip = "Websdk issue with full framework publish. See https://github.com/aspnet/websdk/pull/322")]
|
public async Task NtlmAuthentication(TestVariant variant)
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, "netcoreapp2.1", RuntimeArchitecture.x64, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, "netcoreapp2.1", RuntimeArchitecture.x64, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, "netcoreapp2.1", RuntimeArchitecture.x64, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, "netcoreapp2.1", RuntimeArchitecture.x64, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, "netcoreapp2.0", RuntimeArchitecture.x64, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, "netcoreapp2.0", RuntimeArchitecture.x64, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V2")]
|
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, "netcoreapp2.0", RuntimeArchitecture.x64, ApplicationType.Portable, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(ServerType.IISExpress, RuntimeFlavor.CoreClr, "netcoreapp2.0", RuntimeArchitecture.x64, ApplicationType.Standalone, HostingModel.OutOfProcess, "/p:ANCMVersion=V1")]
|
|
||||||
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, "netcoreapp2.0", RuntimeArchitecture.x64, ApplicationType.Portable)]
|
|
||||||
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, "netcoreapp2.1", RuntimeArchitecture.x64, ApplicationType.Portable)]
|
|
||||||
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, "netcoreapp2.0", RuntimeArchitecture.x64, ApplicationType.Standalone)]
|
|
||||||
[InlineData(ServerType.WebListener, RuntimeFlavor.CoreClr, "netcoreapp2.1", RuntimeArchitecture.x64, ApplicationType.Standalone)]
|
|
||||||
public async Task NtlmAuthentication(ServerType serverType,
|
|
||||||
RuntimeFlavor runtimeFlavor,
|
|
||||||
string targetFramework,
|
|
||||||
RuntimeArchitecture architecture,
|
|
||||||
ApplicationType applicationType,
|
|
||||||
HostingModel hostingModel = HostingModel.OutOfProcess,
|
|
||||||
string additionalPublishParameters = "")
|
|
||||||
{
|
{
|
||||||
var testName = $"NtlmAuthentication_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}";
|
var testName = $"NtlmAuthentication_{variant.Server}_{variant.Tfm}_{variant.Architecture}_{variant.ApplicationType}";
|
||||||
using (StartLog(out var loggerFactory, testName))
|
using (StartLog(out var loggerFactory, testName))
|
||||||
{
|
{
|
||||||
var logger = loggerFactory.CreateLogger("NtlmAuthenticationTest");
|
var logger = loggerFactory.CreateLogger("NtlmAuthenticationTest");
|
||||||
|
|
||||||
var deploymentParameters = new DeploymentParameters(Helpers.GetApplicationPath(applicationType), serverType, runtimeFlavor, architecture)
|
var deploymentParameters = new DeploymentParameters(variant)
|
||||||
{
|
{
|
||||||
|
ApplicationPath = Helpers.GetApplicationPath(),
|
||||||
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),
|
|
||||||
SiteName = "NtlmAuthenticationTestSite", // This is configured in the NtlmAuthentication.config
|
|
||||||
TargetFramework = targetFramework,
|
|
||||||
ApplicationType = applicationType,
|
|
||||||
HostingModel = hostingModel,
|
|
||||||
AdditionalPublishParameters = additionalPublishParameters
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using (var deployer = ApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
|
using (var deployer = IISApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
|
||||||
{
|
{
|
||||||
var deploymentResult = await deployer.DeployAsync();
|
var deploymentResult = await deployer.DeployAsync();
|
||||||
var httpClient = deploymentResult.HttpClient;
|
var httpClient = deploymentResult.HttpClient;
|
||||||
|
|
@ -0,0 +1,234 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||||
|
using Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
|
||||||
|
using Microsoft.AspNetCore.Testing.xunit;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace ServerComparison.FunctionalTests
|
||||||
|
{
|
||||||
|
public class ResponseCompressionTests : LoggedTest
|
||||||
|
{
|
||||||
|
// NGinx's default min size is 20 bytes
|
||||||
|
private static readonly string HelloWorldBody = "Hello World;" + new string('a', 20);
|
||||||
|
|
||||||
|
public ResponseCompressionTests(ITestOutputHelper output) : base(output)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TestMatrix NoCompressionTestVariants
|
||||||
|
=> TestMatrix.ForServers(ServerType.IISExpress, ServerType.Kestrel, ServerType.Nginx, ServerType.HttpSys)
|
||||||
|
.WithTfms(Tfm.NetCoreApp22, Tfm.Net461)
|
||||||
|
.WithAllAncmVersions()
|
||||||
|
.WithAllHostingModels();
|
||||||
|
|
||||||
|
[ConditionalTheory]
|
||||||
|
[MemberData(nameof(NoCompressionTestVariants))]
|
||||||
|
public Task ResponseCompression_NoCompression(TestVariant variant)
|
||||||
|
{
|
||||||
|
return ResponseCompression(variant, CheckNoCompressionAsync, hostCompression: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TestMatrix HostCompressionTestVariants
|
||||||
|
=> TestMatrix.ForServers(ServerType.IISExpress, ServerType.Nginx)
|
||||||
|
.WithTfms(Tfm.NetCoreApp22, Tfm.Net461)
|
||||||
|
.WithAllAncmVersions()
|
||||||
|
.WithAllHostingModels();
|
||||||
|
|
||||||
|
[ConditionalTheory]
|
||||||
|
[MemberData(nameof(HostCompressionTestVariants))]
|
||||||
|
public Task ResponseCompression_HostCompression(TestVariant variant)
|
||||||
|
{
|
||||||
|
return ResponseCompression(variant, CheckHostCompressionAsync, hostCompression: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TestMatrix AppCompressionTestVariants
|
||||||
|
=> TestMatrix.ForServers(ServerType.IISExpress, ServerType.Kestrel, ServerType.HttpSys) // No pass-through compression for nginx
|
||||||
|
.WithTfms(Tfm.NetCoreApp22, Tfm.Net461)
|
||||||
|
.WithAllAncmVersions()
|
||||||
|
.WithAllHostingModels();
|
||||||
|
|
||||||
|
[ConditionalTheory]
|
||||||
|
[MemberData(nameof(AppCompressionTestVariants))]
|
||||||
|
public Task ResponseCompression_AppCompression(TestVariant variant)
|
||||||
|
{
|
||||||
|
return ResponseCompression(variant, CheckAppCompressionAsync, hostCompression: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TestMatrix HostAndAppCompressionTestVariants
|
||||||
|
=> TestMatrix.ForServers(ServerType.IISExpress, ServerType.Kestrel, ServerType.Nginx, ServerType.HttpSys)
|
||||||
|
.WithTfms(Tfm.NetCoreApp22, Tfm.Net461)
|
||||||
|
.WithAllAncmVersions()
|
||||||
|
.WithAllHostingModels();
|
||||||
|
|
||||||
|
[ConditionalTheory]
|
||||||
|
[MemberData(nameof(HostAndAppCompressionTestVariants))]
|
||||||
|
public Task ResponseCompression_AppAndHostCompression(TestVariant variant)
|
||||||
|
{
|
||||||
|
return ResponseCompression(variant, CheckAppCompressionAsync, hostCompression: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ResponseCompression(TestVariant variant,
|
||||||
|
Func<HttpClient, ILogger, Task> scenario,
|
||||||
|
bool hostCompression,
|
||||||
|
[CallerMemberName] string testName = null)
|
||||||
|
{
|
||||||
|
testName = $"{testName}_{variant.Server}_{variant.Tfm}_{variant.Architecture}_{variant.ApplicationType}";
|
||||||
|
using (StartLog(out var loggerFactory, testName))
|
||||||
|
{
|
||||||
|
var logger = loggerFactory.CreateLogger("ResponseCompression");
|
||||||
|
|
||||||
|
var deploymentParameters = new DeploymentParameters(variant)
|
||||||
|
{
|
||||||
|
ApplicationPath = Helpers.GetApplicationPath(),
|
||||||
|
EnvironmentName = "ResponseCompression",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (variant.Server == ServerType.Nginx)
|
||||||
|
{
|
||||||
|
deploymentParameters.ServerConfigTemplateContent = hostCompression
|
||||||
|
? Helpers.GetNginxConfigContent("nginx.conf")
|
||||||
|
: Helpers.GetNginxConfigContent("NoCompression.conf");
|
||||||
|
}
|
||||||
|
else if (variant.Server == ServerType.IISExpress && !hostCompression)
|
||||||
|
{
|
||||||
|
var iisDeploymentParameters = new IISDeploymentParameters(deploymentParameters);
|
||||||
|
iisDeploymentParameters.ServerConfigActionList.Add(
|
||||||
|
(element, _) => {
|
||||||
|
var compressionElement = element
|
||||||
|
.RequiredElement("system.webServer")
|
||||||
|
.RequiredElement("httpCompression");
|
||||||
|
|
||||||
|
compressionElement
|
||||||
|
.RequiredElement("dynamicTypes")
|
||||||
|
.Elements()
|
||||||
|
.SkipLast(1)
|
||||||
|
.Remove();
|
||||||
|
|
||||||
|
compressionElement
|
||||||
|
.RequiredElement("staticTypes")
|
||||||
|
.Elements()
|
||||||
|
.SkipLast(1)
|
||||||
|
.Remove();
|
||||||
|
// last element in both dynamicTypes and staticTypes disables compression
|
||||||
|
// <add mimeType="*/*" enabled="false" />
|
||||||
|
});
|
||||||
|
deploymentParameters = iisDeploymentParameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var deployer = IISApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
|
||||||
|
{
|
||||||
|
var deploymentResult = await deployer.DeployAsync();
|
||||||
|
var httpClientHandler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.None };
|
||||||
|
Assert.True(httpClientHandler.SupportsAutomaticDecompression);
|
||||||
|
var httpClient = deploymentResult.CreateHttpClient(httpClientHandler);
|
||||||
|
|
||||||
|
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
||||||
|
var response = await RetryHelper.RetryRequest(() =>
|
||||||
|
{
|
||||||
|
return httpClient.GetAsync(string.Empty);
|
||||||
|
}, logger, deploymentResult.HostShutdownToken);
|
||||||
|
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assert.Equal("Running", responseText);
|
||||||
|
}
|
||||||
|
catch (XunitException)
|
||||||
|
{
|
||||||
|
logger.LogWarning(response.ToString());
|
||||||
|
logger.LogWarning(responseText);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
await scenario(httpClient, logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assert.Equal(HelloWorldBody, responseText);
|
||||||
|
Assert.Equal(HelloWorldBody.Length.ToString(), GetContentLength(response));
|
||||||
|
Assert.Equal(0, response.Content.Headers.ContentEncoding.Count);
|
||||||
|
}
|
||||||
|
catch (XunitException)
|
||||||
|
{
|
||||||
|
logger.LogWarning(response.ToString());
|
||||||
|
logger.LogWarning(responseText);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Task CheckHostCompressionAsync(HttpClient client, ILogger logger)
|
||||||
|
{
|
||||||
|
return CheckCompressionAsync(client, "NoAppCompression", logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Task CheckAppCompressionAsync(HttpClient client, ILogger logger)
|
||||||
|
{
|
||||||
|
return CheckCompressionAsync(client, "AppCompression", 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.
|
||||||
|
logger.LogInformation($"Testing /{url}");
|
||||||
|
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
||||||
|
request.Headers.AcceptEncoding.ParseAdd("gzip,deflate");
|
||||||
|
var response = await client.SendAsync(request);
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
responseText = await ReadCompressedAsStringAsync(response.Content);
|
||||||
|
Assert.Equal(HelloWorldBody, responseText);
|
||||||
|
Assert.Equal(1, response.Content.Headers.ContentEncoding.Count);
|
||||||
|
Assert.Equal("gzip", response.Content.Headers.ContentEncoding.First());
|
||||||
|
}
|
||||||
|
catch (XunitException)
|
||||||
|
{
|
||||||
|
logger.LogWarning(response.ToString());
|
||||||
|
logger.LogWarning(responseText);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetContentLength(HttpResponseMessage response)
|
||||||
|
{
|
||||||
|
// Don't use response.Content.Headers.ContentLength, it will dynamically calculate the value if it can.
|
||||||
|
return response.Content.Headers.TryGetValues(HeaderNames.ContentLength, out var values) ? values.FirstOrDefault() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<string> ReadCompressedAsStringAsync(HttpContent content)
|
||||||
|
{
|
||||||
|
using (var stream = await content.ReadAsStreamAsync())
|
||||||
|
using (var compressStream = new GZipStream(stream, CompressionMode.Decompress))
|
||||||
|
using (var reader = new StreamReader(compressStream))
|
||||||
|
{
|
||||||
|
return await reader.ReadToEndAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,272 @@
|
||||||
|
// 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;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using Xunit.Sdk;
|
||||||
|
|
||||||
|
namespace ServerComparison.FunctionalTests
|
||||||
|
{
|
||||||
|
public class ResponseTests : LoggedTest
|
||||||
|
{
|
||||||
|
public ResponseTests(ITestOutputHelper output) : base(output)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TestMatrix TestVariants
|
||||||
|
=> TestMatrix.ForServers(ServerType.IISExpress, ServerType.Kestrel, ServerType.Nginx, ServerType.HttpSys)
|
||||||
|
.WithTfms(Tfm.NetCoreApp22)
|
||||||
|
.WithAllAncmVersions()
|
||||||
|
.WithAllHostingModels();
|
||||||
|
|
||||||
|
[ConditionalTheory]
|
||||||
|
[MemberData(nameof(TestVariants))]
|
||||||
|
public Task ResponseFormats_ContentLength(TestVariant variant)
|
||||||
|
{
|
||||||
|
return ResponseFormats(variant, CheckContentLengthAsync);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConditionalTheory]
|
||||||
|
[MemberData(nameof(TestVariants))]
|
||||||
|
public Task ResponseFormats_Chunked(TestVariant variant)
|
||||||
|
{
|
||||||
|
return ResponseFormats(variant, CheckChunkedAsync);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConditionalTheory]
|
||||||
|
[MemberData(nameof(TestVariants))]
|
||||||
|
public Task ResponseFormats_ManuallyChunk(TestVariant variant)
|
||||||
|
{
|
||||||
|
return ResponseFormats(variant, CheckManuallyChunkedAsync);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TestMatrix SelfhostTestVariants
|
||||||
|
=> TestMatrix.ForServers(ServerType.Kestrel, ServerType.HttpSys)
|
||||||
|
.WithTfms(Tfm.NetCoreApp22);
|
||||||
|
|
||||||
|
// Connection Close tests do not work through reverse proxies
|
||||||
|
[ConditionalTheory]
|
||||||
|
[MemberData(nameof(SelfhostTestVariants))]
|
||||||
|
public Task ResponseFormats_Http10ConnectionClose(TestVariant variant)
|
||||||
|
{
|
||||||
|
return ResponseFormats(variant, CheckHttp10ConnectionCloseAsync);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConditionalTheory]
|
||||||
|
[MemberData(nameof(SelfhostTestVariants))]
|
||||||
|
public Task ResponseFormats_Http11ConnectionClose(TestVariant variant)
|
||||||
|
{
|
||||||
|
return ResponseFormats(variant, CheckHttp11ConnectionCloseAsync);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ConditionalTheory]
|
||||||
|
[MemberData(nameof(SelfhostTestVariants))]
|
||||||
|
public Task ResponseFormats_ManuallyChunkAndClose(TestVariant variant)
|
||||||
|
{
|
||||||
|
return ResponseFormats(variant, CheckManuallyChunkedAndCloseAsync);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ResponseFormats(TestVariant variant, Func<HttpClient, ILogger, Task> scenario, [CallerMemberName] string testName = null)
|
||||||
|
{
|
||||||
|
testName = $"{testName}_{variant.Server}_{variant.Tfm}_{variant.Architecture}_{variant.ApplicationType}";
|
||||||
|
using (StartLog(out var loggerFactory, testName))
|
||||||
|
{
|
||||||
|
var logger = loggerFactory.CreateLogger("ResponseFormats");
|
||||||
|
|
||||||
|
var deploymentParameters = new DeploymentParameters(variant)
|
||||||
|
{
|
||||||
|
ApplicationPath = Helpers.GetApplicationPath(),
|
||||||
|
EnvironmentName = "Responses"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (variant.Server == ServerType.Nginx)
|
||||||
|
{
|
||||||
|
deploymentParameters.ServerConfigTemplateContent = Helpers.GetNginxConfigContent("nginx.conf");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (var deployer = IISApplicationDeployerFactory.Create(deploymentParameters, loggerFactory))
|
||||||
|
{
|
||||||
|
var deploymentResult = await deployer.DeployAsync();
|
||||||
|
|
||||||
|
// Request to base address and check if various parts of the body are rendered & measure the cold startup time.
|
||||||
|
var response = await RetryHelper.RetryRequest(() =>
|
||||||
|
{
|
||||||
|
return deploymentResult.HttpClient.GetAsync(string.Empty);
|
||||||
|
}, logger, deploymentResult.HostShutdownToken);
|
||||||
|
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assert.Equal("Running", responseText);
|
||||||
|
}
|
||||||
|
catch (XunitException)
|
||||||
|
{
|
||||||
|
logger.LogWarning(response.ToString());
|
||||||
|
logger.LogWarning(responseText);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
await scenario(deploymentResult.HttpClient, logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task CheckContentLengthAsync(HttpClient client, ILogger logger)
|
||||||
|
{
|
||||||
|
logger.LogInformation("Testing ContentLength");
|
||||||
|
var requestMessage = new HttpRequestMessage(HttpMethod.Get, "contentlength")
|
||||||
|
{
|
||||||
|
Version = new Version(1, 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await client.SendAsync(requestMessage);
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assert.Equal("Content Length", responseText);
|
||||||
|
Assert.Null(response.Headers.TransferEncodingChunked);
|
||||||
|
Assert.Null(response.Headers.ConnectionClose);
|
||||||
|
Assert.Equal("14", GetContentLength(response));
|
||||||
|
}
|
||||||
|
catch (XunitException)
|
||||||
|
{
|
||||||
|
logger.LogWarning(response.ToString());
|
||||||
|
logger.LogWarning(responseText);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
Assert.Equal("Connnection Close", responseText);
|
||||||
|
Assert.True(response.Headers.ConnectionClose, "/connectionclose, closed?");
|
||||||
|
Assert.True(response.Headers.TransferEncodingChunked);
|
||||||
|
Assert.Null(GetContentLength(response));
|
||||||
|
}
|
||||||
|
catch (XunitException)
|
||||||
|
{
|
||||||
|
logger.LogWarning(response.ToString());
|
||||||
|
logger.LogWarning(responseText);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await client.SendAsync(requestMessage);
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assert.Equal("Connnection Close", responseText);
|
||||||
|
Assert.True(response.Headers.ConnectionClose, "/connectionclose, closed?");
|
||||||
|
Assert.Null(response.Headers.TransferEncodingChunked);
|
||||||
|
Assert.Null(GetContentLength(response));
|
||||||
|
}
|
||||||
|
catch (XunitException)
|
||||||
|
{
|
||||||
|
logger.LogWarning(response.ToString());
|
||||||
|
logger.LogWarning(responseText);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task CheckChunkedAsync(HttpClient client, ILogger logger)
|
||||||
|
{
|
||||||
|
logger.LogInformation("Testing Chunked");
|
||||||
|
var requestMessage = new HttpRequestMessage(HttpMethod.Get, "chunked")
|
||||||
|
{
|
||||||
|
Version = new Version(1, 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await client.SendAsync(requestMessage);
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assert.Equal("Chunked", responseText);
|
||||||
|
Assert.True(response.Headers.TransferEncodingChunked, "/chunked, chunked?");
|
||||||
|
Assert.Null(response.Headers.ConnectionClose);
|
||||||
|
Assert.Null(GetContentLength(response));
|
||||||
|
}
|
||||||
|
catch (XunitException)
|
||||||
|
{
|
||||||
|
logger.LogWarning(response.ToString());
|
||||||
|
logger.LogWarning(responseText);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task CheckManuallyChunkedAsync(HttpClient client, ILogger logger)
|
||||||
|
{
|
||||||
|
logger.LogInformation("Testing ManuallyChunked");
|
||||||
|
var requestMessage = new HttpRequestMessage(HttpMethod.Get, "manuallychunked")
|
||||||
|
{
|
||||||
|
Version = new Version(1, 1)
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await client.SendAsync(requestMessage);
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assert.Equal("Manually Chunked", responseText);
|
||||||
|
Assert.True(response.Headers.TransferEncodingChunked, "/manuallychunked, chunked?");
|
||||||
|
Assert.Null(response.Headers.ConnectionClose);
|
||||||
|
Assert.Null(GetContentLength(response));
|
||||||
|
}
|
||||||
|
catch (XunitException)
|
||||||
|
{
|
||||||
|
logger.LogWarning(response.ToString());
|
||||||
|
logger.LogWarning(responseText);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
Assert.Equal("Manually Chunked and Close", responseText);
|
||||||
|
Assert.True(response.Headers.TransferEncodingChunked, "/manuallychunkedandclose, chunked?");
|
||||||
|
Assert.True(response.Headers.ConnectionClose, "/manuallychunkedandclose, closed?");
|
||||||
|
Assert.Null(GetContentLength(response));
|
||||||
|
}
|
||||||
|
catch (XunitException)
|
||||||
|
{
|
||||||
|
logger.LogWarning(response.ToString());
|
||||||
|
logger.LogWarning(responseText);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetContentLength(HttpResponseMessage response)
|
||||||
|
{
|
||||||
|
// Don't use response.Content.Headers.ContentLength, it will dynamically calculate the value if it can.
|
||||||
|
IEnumerable<string> values;
|
||||||
|
return response.Content.Headers.TryGetValues(HeaderNames.ContentLength, out values) ? values.FirstOrDefault() : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Use 2.1 to run the tests. The tests will select their own TFMs for the test application when publishing -->
|
<!-- Use 2.2 to run the tests. The tests will select their own TFMs for the test application when publishing -->
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkPackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.IntegrationTesting" Version="$(MicrosoftAspNetCoreServerIntegrationTestingPackageVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.IntegrationTesting.IIS" Version="$(MicrosoftAspNetCoreServerIntegrationTestingIISPackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="$(MicrosoftExtensionsLoggingPackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Testing" Version="$(MicrosoftExtensionsLoggingTestingPackageVersion)" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Testing" Version="$(MicrosoftExtensionsLoggingTestingPackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.Net.Http.Headers" Version="$(MicrosoftNetHttpHeadersPackageVersion)" />
|
<PackageReference Include="Microsoft.Net.Http.Headers" Version="$(MicrosoftNetHttpHeadersPackageVersion)" />
|
||||||
|
|
@ -53,8 +53,9 @@ namespace ServerComparison.TestSites
|
||||||
// Check that we are not using IIS inproc before we add Kestrel.
|
// Check that we are not using IIS inproc before we add Kestrel.
|
||||||
builder.UseKestrel();
|
builder.UseKestrel();
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.UseIISIntegration();
|
builder.UseIISIntegration();
|
||||||
|
builder.UseIIS();
|
||||||
|
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|
||||||
|
|
@ -5,17 +5,15 @@
|
||||||
<RuntimeIdentifiers>win7-x86;win7-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win7-x86;win7-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(OS)' == 'Windows_NT' AND ('$(ANCMVersion)' == 'V2' Or '$(ANCMVersion)' == '')">
|
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
|
||||||
<PackageReference Include="Microsoft.AspNetCore.AspNetCoreModule" Version="$(MicrosoftAspNetCoreAspNetCoreModulePackageVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.AspNetCoreModule" Version="$(MicrosoftAspNetCoreAspNetCoreModulePackageVersion)" />
|
||||||
</ItemGroup>
|
<PackageReference Include="Microsoft.AspNetCore.AspNetCoreModuleV2" Version="$(MicrosoftAspNetCoreAspNetCoreModuleV2PackageVersion)" />
|
||||||
|
|
||||||
<ItemGroup Condition="'$(OS)' == 'Windows_NT' AND ('$(ANCMVersion)' == 'V1')">
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.AspNetCoreModuleV1" Version="$(MicrosoftAspNetCoreAspNetCoreModuleV1PackageVersion)" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="$(MicrosoftAspNetCoreResponseCompressionPackageVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="$(MicrosoftAspNetCoreResponseCompressionPackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.HttpSys" Version="$(MicrosoftAspNetCoreServerHttpSysPackageVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.HttpSys" Version="$(MicrosoftAspNetCoreServerHttpSysPackageVersion)" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Server.IIS" Version="$(MicrosoftAspNetCoreServerIISPackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="$(MicrosoftAspNetCoreWebUtilitiesPackageVersion)" />
|
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="$(MicrosoftAspNetCoreWebUtilitiesPackageVersion)" />
|
||||||
|
|
@ -1,19 +1,20 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace ServerComparison.TestSites
|
namespace ServerComparison.TestSites
|
||||||
{
|
{
|
||||||
public class StartupHelloWorld
|
public class Startup
|
||||||
{
|
{
|
||||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
app.Run(ctx =>
|
app.Run(ctx =>
|
||||||
{
|
{
|
||||||
return ctx.Response.WriteAsync("Hello World");
|
return ctx.Response.WriteAsync("Hello World " + RuntimeInformation.ProcessArchitecture);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
<!--
|
||||||
|
|
||||||
|
IIS Asp.Net Core Extension Schema
|
||||||
|
|
||||||
|
** Please DO NOT edit this file yourself. **
|
||||||
|
|
||||||
|
If you want to add configuration sections to the schema, you may place
|
||||||
|
them in .xml files similar to this one, in this directory. They will be
|
||||||
|
picked up automatically on startup.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<configSchema>
|
||||||
|
<sectionSchema name="system.webServer/aspNetCore">
|
||||||
|
<attribute name="processPath" type="string" expanded="true"/>
|
||||||
|
<attribute name="arguments" type="string" expanded="true" defaultValue=""/>
|
||||||
|
<attribute name="startupTimeLimit" type="uint" defaultValue="120" validationType="integerRange" validationParameter="0,3600"/> <!-- in seconds -->
|
||||||
|
<attribute name="shutdownTimeLimit" type="uint" defaultValue="10" validationType="integerRange" validationParameter="0,600"/> <!-- in seconds -->
|
||||||
|
<attribute name="rapidFailsPerMinute" type="uint" defaultValue="10" validationType="integerRange" validationParameter="0,100"/>
|
||||||
|
<attribute name="requestTimeout" type="timeSpan" defaultValue="00:02:00" validationType="timeSpanRange" validationParameter="0,1296000,60"/>
|
||||||
|
<attribute name="stdoutLogEnabled" type="bool" defaultValue="false" />
|
||||||
|
<attribute name="stdoutLogFile" type="string" defaultValue=".\aspnetcore-stdout" expanded="true"/>
|
||||||
|
<attribute name="processesPerApplication" type="uint" defaultValue="1" validationType="integerRange" validationParameter="1,100"/>
|
||||||
|
<attribute name="forwardWindowsAuthToken" type="bool" defaultValue="true" />
|
||||||
|
<attribute name="disableStartUpErrorPage" type="bool" defaultValue="false" />
|
||||||
|
<attribute name="hostingModel" type="string" />
|
||||||
|
<element name="recycleOnFileChange">
|
||||||
|
<collection addElement="file" clearElement="clear">
|
||||||
|
<attribute name="path" type="string" required="true" validationType="nonEmptyString" expanded="true"/>
|
||||||
|
</collection>
|
||||||
|
</element>
|
||||||
|
<element name="environmentVariables">
|
||||||
|
<collection addElement="environmentVariable" clearElement="clear" >
|
||||||
|
<attribute name="name" type="string" required="true" validationType="nonEmptyString"/>
|
||||||
|
<attribute name="value" type="string" required="true"/>
|
||||||
|
</collection>
|
||||||
|
</element>
|
||||||
|
</sectionSchema>
|
||||||
|
</configSchema>
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<!--
|
||||||
|
|
||||||
|
IIS Asp.Net Core Extension Schema
|
||||||
|
|
||||||
|
** Please DO NOT edit this file yourself. **
|
||||||
|
|
||||||
|
If you want to add configuration sections to the schema, you may place
|
||||||
|
them in .xml files similar to this one, in this directory. They will be
|
||||||
|
picked up automatically on startup.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<configSchema>
|
||||||
|
<sectionSchema name="system.webServer/aspNetCore">
|
||||||
|
<attribute name="processPath" type="string" expanded="true"/>
|
||||||
|
<attribute name="arguments" type="string" expanded="true" defaultValue=""/>
|
||||||
|
<attribute name="startupTimeLimit" type="uint" defaultValue="120" validationType="integerRange" validationParameter="0,3600"/>
|
||||||
|
<!-- in seconds -->
|
||||||
|
<attribute name="shutdownTimeLimit" type="uint" defaultValue="10" validationType="integerRange" validationParameter="0,600"/>
|
||||||
|
<!-- in seconds -->
|
||||||
|
<attribute name="rapidFailsPerMinute" type="uint" defaultValue="10" validationType="integerRange" validationParameter="0,100"/>
|
||||||
|
<attribute name="requestTimeout" type="timeSpan" defaultValue="00:02:00" validationType="timeSpanRange" validationParameter="0,1296000,1"/>
|
||||||
|
<attribute name="stdoutLogEnabled" type="bool" defaultValue="false" />
|
||||||
|
<attribute name="stdoutLogFile" type="string" defaultValue=".\aspnetcore-stdout" expanded="true"/>
|
||||||
|
<attribute name="processesPerApplication" type="uint" defaultValue="1" validationType="integerRange" validationParameter="1,100"/>
|
||||||
|
<attribute name="forwardWindowsAuthToken" type="bool" defaultValue="true" />
|
||||||
|
<attribute name="disableStartUpErrorPage" type="bool" defaultValue="false" />
|
||||||
|
<attribute name="hostingModel" type="string" />
|
||||||
|
<element name="recycleOnFileChange">
|
||||||
|
<collection addElement="file" clearElement="clear">
|
||||||
|
<attribute name="path" type="string" required="true" validationType="nonEmptyString" expanded="true"/>
|
||||||
|
</collection>
|
||||||
|
</element>
|
||||||
|
<element name="environmentVariables">
|
||||||
|
<collection addElement="environmentVariable" clearElement="clear" >
|
||||||
|
<attribute name="name" type="string" required="true" validationType="nonEmptyString"/>
|
||||||
|
<attribute name="value" type="string" required="true"/>
|
||||||
|
</collection>
|
||||||
|
</element>
|
||||||
|
<element name="handlerSettings">
|
||||||
|
<collection addElement="handlerSetting" clearElement="clear" >
|
||||||
|
<attribute name="name" type="string" required="true" validationType="nonEmptyString"/>
|
||||||
|
<attribute name="value" type="string" required="true"/>
|
||||||
|
</collection>
|
||||||
|
</element>
|
||||||
|
</sectionSchema>
|
||||||
|
</configSchema>
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
<#
|
||||||
|
.DESCRIPTION
|
||||||
|
Updates aspnetcore_schema.xml to the latest version.
|
||||||
|
Updates aspnetcore_schema_v2.xml to the latest version.
|
||||||
|
Requires admin privileges.
|
||||||
|
#>
|
||||||
|
[cmdletbinding(SupportsShouldProcess = $true)]
|
||||||
|
param()
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
Set-StrictMode -Version 1
|
||||||
|
|
||||||
|
$ancmSchemaFiles = @(
|
||||||
|
"aspnetcore_schema.xml",
|
||||||
|
"aspnetcore_schema_v2.xml"
|
||||||
|
)
|
||||||
|
|
||||||
|
$ancmSchemaFileLocations = @(
|
||||||
|
@(Resolve-Path "$PSScriptRoot\aspnetcore_schema.xml"),
|
||||||
|
@(Resolve-Path "$PSScriptRoot\aspnetcore_schema_v2.xml")
|
||||||
|
)
|
||||||
|
|
||||||
|
[bool]$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||||||
|
|
||||||
|
if (-not $isAdmin -and -not $WhatIfPreference) {
|
||||||
|
if ($PSCmdlet.ShouldContinue("Continue as an admin?", "This script needs admin privileges to update IIS Express and IIS.")) {
|
||||||
|
$thisFile = Join-Path $PSScriptRoot $MyInvocation.MyCommand.Name
|
||||||
|
|
||||||
|
Start-Process `
|
||||||
|
-Verb runas `
|
||||||
|
-FilePath "powershell.exe" `
|
||||||
|
-ArgumentList $thisFile `
|
||||||
|
-Wait `
|
||||||
|
| Out-Null
|
||||||
|
|
||||||
|
if (-not $?) {
|
||||||
|
throw 'Update failed'
|
||||||
|
}
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw 'Requires admin privileges'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i=0; $i -lt $ancmSchemaFiles.Length; $i++)
|
||||||
|
{
|
||||||
|
$schemaFile = $ancmSchemaFiles[$i]
|
||||||
|
$schemaSource = $ancmSchemaFileLocations[$i]
|
||||||
|
|
||||||
|
$destinations = @(
|
||||||
|
"${env:ProgramFiles(x86)}\IIS Express\config\schema\",
|
||||||
|
"${env:ProgramFiles}\IIS Express\config\schema\",
|
||||||
|
"${env:windir}\system32\inetsrv\config\schema\"
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($destPath in $destinations) {
|
||||||
|
$dest = "$destPath\${schemaFile}";
|
||||||
|
|
||||||
|
if (!(Test-Path $destPath))
|
||||||
|
{
|
||||||
|
Write-Host "$destPath doesn't exist"
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($PSCmdlet.ShouldProcess($dest, "Replace file")) {
|
||||||
|
Write-Host "Updated $dest"
|
||||||
|
Move-Item $dest "${dest}.bak" -ErrorAction Ignore
|
||||||
|
Copy-Item $schemaSource $dest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>2.1.1</VersionPrefix>
|
<VersionPrefix>2.2.0</VersionPrefix>
|
||||||
<VersionSuffix>rtm</VersionSuffix>
|
<VersionSuffix>rtm</VersionSuffix>
|
||||||
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' == 'rtm' ">$(VersionPrefix)</PackageVersion>
|
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' == 'rtm' ">$(VersionPrefix)</PackageVersion>
|
||||||
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' != 'rtm' ">$(VersionPrefix)-$(VersionSuffix)-final</PackageVersion>
|
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' != 'rtm' ">$(VersionPrefix)-$(VersionSuffix)-final</PackageVersion>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue