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>
|
||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.0' ">$(MicrosoftNETCoreApp20PackageVersion)</RuntimeFrameworkVersion>
|
||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.1' ">$(MicrosoftNETCoreApp21PackageVersion)</RuntimeFrameworkVersion>
|
||||
<RuntimeFrameworkVersion Condition=" '$(TargetFramework)' == 'netcoreapp2.2' ">$(MicrosoftNETCoreApp22PackageVersion)</RuntimeFrameworkVersion>
|
||||
<NETStandardImplicitPackageVersion Condition=" '$(TargetFramework)' == 'netstandard2.0' ">$(NETStandardLibrary20PackageVersion)</NETStandardImplicitPackageVersion>
|
||||
<!-- aspnet/BuildTools#662 Don't police what version of NetCoreApp we use -->
|
||||
<NETCoreAppMaximumVersion>99.9</NETCoreAppMaximumVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ VisualStudioVersion = 15.0.27130.2036
|
|||
MinimumVisualStudioVersion = 15.0.26730.03
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{49AB8AAA-8160-48DF-A18B-78F51E54E02A}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.appveyor.yml = .appveyor.yml
|
||||
.travis.yml = .travis.yml
|
||||
Directory.Build.props = Directory.Build.props
|
||||
Directory.Build.targets = Directory.Build.targets
|
||||
NuGet.config = NuGet.config
|
||||
|
|
@ -20,6 +22,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{55694E45
|
|||
ProjectSection(SolutionItems) = preProject
|
||||
build\dependencies.props = build\dependencies.props
|
||||
build\repo.props = build\repo.props
|
||||
build\sources.props = build\sources.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
|
|
|
|||
|
|
@ -2,38 +2,33 @@
|
|||
<PropertyGroup>
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- These package versions may be overridden or updated by automation. -->
|
||||
<PropertyGroup Label="Package Versions: Auto">
|
||||
<InternalAspNetCoreSdkPackageVersion>2.1.3-rtm-15802</InternalAspNetCoreSdkPackageVersion>
|
||||
<MicrosoftAspNetCoreAspNetCoreModulePackageVersion>2.1.1</MicrosoftAspNetCoreAspNetCoreModulePackageVersion>
|
||||
<MicrosoftAspNetCoreAspNetCoreModuleV1PackageVersion>2.1.1</MicrosoftAspNetCoreAspNetCoreModuleV1PackageVersion>
|
||||
<MicrosoftAspNetCoreResponseCompressionPackageVersion>2.1.1</MicrosoftAspNetCoreResponseCompressionPackageVersion>
|
||||
<MicrosoftAspNetCoreServerHttpSysPackageVersion>2.1.1</MicrosoftAspNetCoreServerHttpSysPackageVersion>
|
||||
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.1.1</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
|
||||
<MicrosoftAspNetCoreServerIISPackageVersion>2.1.1</MicrosoftAspNetCoreServerIISPackageVersion>
|
||||
<MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>0.5.1</MicrosoftAspNetCoreServerIntegrationTestingPackageVersion>
|
||||
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.1.2</MicrosoftAspNetCoreServerKestrelPackageVersion>
|
||||
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.1.1</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.1.1</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.1.1</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>2.1.1</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>2.1.1</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTestingPackageVersion>2.1.1</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||
<MicrosoftNETCoreApp20PackageVersion>2.0.0</MicrosoftNETCoreApp20PackageVersion>
|
||||
<MicrosoftNETCoreApp21PackageVersion>2.1.2</MicrosoftNETCoreApp21PackageVersion>
|
||||
<MicrosoftNetHttpHeadersPackageVersion>2.1.1</MicrosoftNetHttpHeadersPackageVersion>
|
||||
<PropertyGroup Label="Package Versions">
|
||||
<InternalAspNetCoreSdkPackageVersion>2.2.0-preview2-20181004.6</InternalAspNetCoreSdkPackageVersion>
|
||||
<MicrosoftAspNetCoreAspNetCoreModulePackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAspNetCoreModulePackageVersion>
|
||||
<MicrosoftAspNetCoreAspNetCoreModuleV2PackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreAspNetCoreModuleV2PackageVersion>
|
||||
<MicrosoftAspNetCoreResponseCompressionPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreResponseCompressionPackageVersion>
|
||||
<MicrosoftAspNetCoreServerHttpSysPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerHttpSysPackageVersion>
|
||||
<MicrosoftAspNetCoreServerIISIntegrationPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerIISIntegrationPackageVersion>
|
||||
<MicrosoftAspNetCoreServerIISPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerIISPackageVersion>
|
||||
<MicrosoftAspNetCoreServerIntegrationTestingIISPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerIntegrationTestingIISPackageVersion>
|
||||
<MicrosoftAspNetCoreServerKestrelPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreServerKestrelPackageVersion>
|
||||
<MicrosoftAspNetCoreWebUtilitiesPackageVersion>2.2.0-preview3-35425</MicrosoftAspNetCoreWebUtilitiesPackageVersion>
|
||||
<MicrosoftExtensionsConfigurationCommandLinePackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationCommandLinePackageVersion>
|
||||
<MicrosoftExtensionsConfigurationJsonPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsConfigurationJsonPackageVersion>
|
||||
<MicrosoftExtensionsLoggingConsolePackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingConsolePackageVersion>
|
||||
<MicrosoftExtensionsLoggingPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingPackageVersion>
|
||||
<MicrosoftExtensionsLoggingTestingPackageVersion>2.2.0-preview3-35425</MicrosoftExtensionsLoggingTestingPackageVersion>
|
||||
<MicrosoftNETCoreApp20PackageVersion>2.0.9</MicrosoftNETCoreApp20PackageVersion>
|
||||
<MicrosoftNETCoreApp21PackageVersion>2.1.3</MicrosoftNETCoreApp21PackageVersion>
|
||||
<MicrosoftNETCoreApp22PackageVersion>2.2.0-preview3-27001-02</MicrosoftNETCoreApp22PackageVersion>
|
||||
<MicrosoftNetHttpHeadersPackageVersion>2.2.0-preview3-35425</MicrosoftNetHttpHeadersPackageVersion>
|
||||
<MicrosoftNETTestSdkPackageVersion>15.6.1</MicrosoftNETTestSdkPackageVersion>
|
||||
<NETStandardLibrary20PackageVersion>2.0.3</NETStandardLibrary20PackageVersion>
|
||||
<SerilogExtensionsLoggingPackageVersion>1.4.0</SerilogExtensionsLoggingPackageVersion>
|
||||
<SerilogSinksFilePackageVersion>3.2.0</SerilogSinksFilePackageVersion>
|
||||
<SerilogSinksFilePackageVersion>4.0.0</SerilogSinksFilePackageVersion>
|
||||
<XunitPackageVersion>2.3.1</XunitPackageVersion>
|
||||
<XunitRunnerVisualStudioPackageVersion>2.4.0-beta.1.build3945</XunitRunnerVisualStudioPackageVersion>
|
||||
<XunitRunnerVisualStudioPackageVersion>2.4.0</XunitRunnerVisualStudioPackageVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- This may import a generated file which may override the variables above. -->
|
||||
<Import Project="$(DotNetPackageVersionPropsPath)" Condition=" '$(DotNetPackageVersionPropsPath)' != '' " />
|
||||
|
||||
<!-- These are package versions that should not be overridden or updated by automation. -->
|
||||
<PropertyGroup Label="Package Versions: Pinned" />
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -7,12 +7,12 @@
|
|||
<PropertyGroup>
|
||||
<!-- These properties are use by the automation that updates dependencies.props -->
|
||||
<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>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp20PackageVersion)" />
|
||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp21PackageVersion)" />
|
||||
<DotNetCoreRuntime Include="$(MicrosoftNETCoreApp22PackageVersion)" />
|
||||
<DotNetCoreRuntime Condition="'$(OS)' == 'Windows_NT'" Include="$(MicrosoftNETCoreApp22PackageVersion)" Arch="x86" />
|
||||
</ItemGroup>
|
||||
</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" />
|
||||
|
||||
<PropertyGroup>
|
||||
<DeveloperBuildTestTfms>netcoreapp2.1;netcoreapp2.0</DeveloperBuildTestTfms>
|
||||
<DeveloperBuildTestTfms>netcoreapp2.2</DeveloperBuildTestTfms>
|
||||
<StandardTestTfms>$(DeveloperBuildTestTfms)</StandardTestTfms>
|
||||
<StandardTestTfms Condition=" '$(DeveloperBuild)' != 'true' AND '$(OS)' == 'Windows_NT' ">$(StandardTestTfms);net461</StandardTestTfms>
|
||||
</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 static string GetApplicationPath(ApplicationType applicationType)
|
||||
public static string GetApplicationPath()
|
||||
{
|
||||
var applicationBasePath = AppContext.BaseDirectory;
|
||||
|
||||
|
|
@ -29,41 +29,11 @@ namespace ServerComparison.FunctionalTests
|
|||
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;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
var content = File.ReadAllText(Path.Combine(applicationBasePath, nginxConfig));
|
||||
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]
|
||||
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
|
||||
[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")]
|
||||
[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 = "")
|
||||
[MemberData(nameof(TestVariants))]
|
||||
public async Task NtlmAuthentication(TestVariant variant)
|
||||
{
|
||||
var testName = $"NtlmAuthentication_{serverType}_{runtimeFlavor}_{architecture}_{applicationType}";
|
||||
var testName = $"NtlmAuthentication_{variant.Server}_{variant.Tfm}_{variant.Architecture}_{variant.ApplicationType}";
|
||||
using (StartLog(out var loggerFactory, testName))
|
||||
{
|
||||
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'
|
||||
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 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>
|
||||
<!-- Use 2.1 to run the tests. The tests will select their own TFMs for the test application when publishing -->
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<!-- Use 2.2 to run the tests. The tests will select their own TFMs for the test application when publishing -->
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<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.Testing" Version="$(MicrosoftExtensionsLoggingTestingPackageVersion)" />
|
||||
<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.
|
||||
builder.UseKestrel();
|
||||
}
|
||||
|
||||
|
||||
builder.UseIISIntegration();
|
||||
builder.UseIIS();
|
||||
|
||||
var host = builder.Build();
|
||||
|
||||
|
|
@ -5,17 +5,15 @@
|
|||
<RuntimeIdentifiers>win7-x86;win7-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition="'$(OS)' == 'Windows_NT' AND ('$(ANCMVersion)' == 'V2' Or '$(ANCMVersion)' == '')">
|
||||
<ItemGroup Condition="'$(OS)' == 'Windows_NT'">
|
||||
<PackageReference Include="Microsoft.AspNetCore.AspNetCoreModule" Version="$(MicrosoftAspNetCoreAspNetCoreModulePackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(OS)' == 'Windows_NT' AND ('$(ANCMVersion)' == 'V1')">
|
||||
<PackageReference Include="Microsoft.AspNetCore.AspNetCoreModuleV1" Version="$(MicrosoftAspNetCoreAspNetCoreModuleV1PackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.AspNetCoreModuleV2" Version="$(MicrosoftAspNetCoreAspNetCoreModuleV2PackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="$(MicrosoftAspNetCoreResponseCompressionPackageVersion)" />
|
||||
<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.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.WebUtilities" Version="$(MicrosoftAspNetCoreWebUtilitiesPackageVersion)" />
|
||||
|
|
@ -1,19 +1,20 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace ServerComparison.TestSites
|
||||
{
|
||||
public class StartupHelloWorld
|
||||
public class Startup
|
||||
{
|
||||
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
|
||||
{
|
||||
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>
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>2.1.1</VersionPrefix>
|
||||
<VersionPrefix>2.2.0</VersionPrefix>
|
||||
<VersionSuffix>rtm</VersionSuffix>
|
||||
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' == 'rtm' ">$(VersionPrefix)</PackageVersion>
|
||||
<PackageVersion Condition="'$(IsFinalBuild)' == 'true' AND '$(VersionSuffix)' != 'rtm' ">$(VersionPrefix)-$(VersionSuffix)-final</PackageVersion>
|
||||
|
|
|
|||
Loading…
Reference in New Issue