|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Xml.Linq;
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
using Microsoft.AspNetCore.InternalTesting;
using Xunit;
#if !IIS_FUNCTIONALS
using Microsoft.AspNetCore.Server.IIS.FunctionalTests;
#if IISEXPRESS_FUNCTIONALS
namespace Microsoft.AspNetCore.Server.IIS.IISExpress.FunctionalTests;
#elif NEWHANDLER_FUNCTIONALS
namespace Microsoft.AspNetCore.Server.IIS.NewHandler.FunctionalTests;
#elif NEWSHIM_FUNCTIONALS
namespace Microsoft.AspNetCore.Server.IIS.NewShim.FunctionalTests;
#endif
#else
namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests;
#endif
[Collection(PublishedSitesCollection.Name)]
[SkipOnHelix("Unsupported queue", Queues = "Windows.Amd64.VS2022.Pre.Open;")]
public class GlobalVersionTests : IISFunctionalTestBase
{
public GlobalVersionTests(PublishedSitesFixture fixture) : base(fixture)
{
}
private const string _handlerVersion20 = "2.0.0";
private const string _helloWorldRequest = "HelloWorld";
private const string _helloWorldResponse = "Hello World";
[ConditionalFact]
public async Task GlobalVersion_DefaultWorks()
{
var deploymentParameters = GetGlobalVersionBaseDeploymentParameters();
deploymentParameters.HandlerSettings["handlerVersion"] = _handlerVersion20;
var deploymentResult = await DeployAsync(deploymentParameters);
var response = await deploymentResult.HttpClient.GetAsync(_helloWorldRequest);
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(_helloWorldResponse, responseText);
}
[ConditionalFact]
[RequiresIIS(IISCapability.PoolEnvironmentVariables)]
[RequiresNewShim]
public async Task GlobalVersion_EnvironmentVariableWorks()
{
var temporaryFile = Path.GetTempFileName();
try
{
var deploymentParameters = GetGlobalVersionBaseDeploymentParameters();
CopyShimToOutput(deploymentParameters);
deploymentParameters.PublishApplicationBeforeDeployment = true;
deploymentParameters.EnvironmentVariables["ASPNETCORE_MODULE_OUTOFPROCESS_HANDLER"] = temporaryFile;
var deploymentResult = await DeployAsync(deploymentParameters);
var requestHandlerPath = Path.Combine(GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20), "aspnetcorev2_outofprocess.dll");
File.Delete(temporaryFile);
File.Move(requestHandlerPath, temporaryFile);
var response = await deploymentResult.HttpClient.GetAsync(_helloWorldRequest);
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(_helloWorldResponse, responseText);
StopServer();
}
finally
{
File.Delete(temporaryFile);
}
}
[ConditionalTheory]
[InlineData("2.1.0")]
[InlineData("2.1.0-preview")]
[InlineData("7.0.0")]
[InlineData("7.0.0-preview")]
public async Task GlobalVersion_NewVersionNumber_Fails(string version)
{
var deploymentParameters = GetGlobalVersionBaseDeploymentParameters();
deploymentParameters.HandlerSettings["handlerVersion"] = version;
var deploymentResult = await DeployAsync(deploymentParameters);
var response = await deploymentResult.HttpClient.GetAsync(_helloWorldRequest);
Assert.False(response.IsSuccessStatusCode);
var responseString = await response.Content.ReadAsStringAsync();
Assert.Contains("500.0", responseString);
}
[ConditionalTheory]
[InlineData("2.1.0")]
[InlineData("2.1.0-preview")]
[InlineData("7.0.0")]
[InlineData("7.0.0-preview")]
public async Task GlobalVersion_NewVersionNumber(string version)
{
var deploymentParameters = GetGlobalVersionBaseDeploymentParameters();
CopyShimToOutput(deploymentParameters);
deploymentParameters.HandlerSettings["handlerVersion"] = version;
var deploymentResult = await DeployAsync(deploymentParameters);
var originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20);
var newANCMPath = GetANCMRequestHandlerPath(deploymentResult, version);
Directory.Move(originalANCMPath, newANCMPath);
var response = await deploymentResult.HttpClient.GetAsync(_helloWorldRequest);
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(_helloWorldResponse, responseText);
AssertLoadedVersion(version);
}
[ConditionalTheory]
[InlineData("2.1.0")]
[InlineData("2.1.0-preview")]
[InlineData("7.0.0")]
[InlineData("7.0.0-preview")]
public async Task GlobalVersion_MultipleRequestHandlers_PicksHighestOne(string version)
{
var deploymentParameters = GetGlobalVersionBaseDeploymentParameters();
CopyShimToOutput(deploymentParameters);
var deploymentResult = await DeployAsync(deploymentParameters);
var originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20);
var newANCMPath = GetANCMRequestHandlerPath(deploymentResult, version);
CopyDirectory(originalANCMPath, newANCMPath);
deploymentResult.HttpClient.DefaultRequestHeaders.Add("ANCMRHPath", newANCMPath);
var response = await deploymentResult.HttpClient.GetAsync("CheckRequestHandlerVersion");
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(_helloWorldResponse, responseText);
AssertLoadedVersion(version);
}
[ConditionalTheory]
[InlineData("2.1.0")]
[InlineData("2.1.0-preview")]
[InlineData("7.0.0")]
[InlineData("7.0.0-preview")]
public async Task GlobalVersion_MultipleRequestHandlers_UpgradeWorks(string version)
{
var deploymentParameters = GetGlobalVersionBaseDeploymentParameters();
CopyShimToOutput(deploymentParameters);
var deploymentResult = await DeployAsync(deploymentParameters);
var originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20);
deploymentResult.HttpClient.DefaultRequestHeaders.Add("ANCMRHPath", originalANCMPath);
var response = await deploymentResult.HttpClient.GetAsync("CheckRequestHandlerVersion");
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(_helloWorldResponse, responseText);
StopServer();
deploymentResult = await DeployAsync(deploymentParameters);
originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20);
var newANCMPath = GetANCMRequestHandlerPath(deploymentResult, version);
CopyDirectory(originalANCMPath, newANCMPath);
deploymentResult.HttpClient.DefaultRequestHeaders.Add("ANCMRHPath", newANCMPath);
response = await deploymentResult.HttpClient.GetAsync("CheckRequestHandlerVersion");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(_helloWorldResponse, responseText);
AssertLoadedVersion(version);
}
[ConditionalFact]
public async Task DoesNotCrashWhenNoVersionsAvailable()
{
var deploymentParameters = GetGlobalVersionBaseDeploymentParameters();
CopyShimToOutput(deploymentParameters);
var deploymentResult = await DeployAsync(deploymentParameters);
var originalANCMPath = GetANCMRequestHandlerPath(deploymentResult, _handlerVersion20);
Directory.Delete(originalANCMPath, true);
var response = await deploymentResult.HttpClient.GetAsync("HelloWorld");
Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
}
private IISDeploymentParameters GetGlobalVersionBaseDeploymentParameters()
{
return Fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess);
}
private void CopyDirectory(string from, string to)
{
var toInfo = new DirectoryInfo(to);
toInfo.Create();
foreach (var file in new DirectoryInfo(from).GetFiles())
{
file.CopyTo(Path.Combine(toInfo.FullName, file.Name));
}
}
private string GetANCMRequestHandlerPath(IISDeploymentResult deploymentResult, string version)
{
return Path.Combine(deploymentResult.ContentRoot,
deploymentResult.DeploymentParameters.RuntimeArchitecture.ToString(),
version);
}
private void AssertLoadedVersion(string version)
{
StopServer();
Assert.Contains(TestSink.Writes, context => context.Message.Contains(version + @"\aspnetcorev2_outofprocess.dll"));
}
private static void CopyShimToOutput(IISDeploymentParameters parameters)
{
parameters.AddServerConfigAction(
(config, contentRoot) =>
{
var moduleNodes = config.DescendantNodesAndSelf()
.OfType<XElement>()
.Where(element =>
element.Name == "add" &&
element.Attribute("name")?.Value.StartsWith("AspNetCoreModule", StringComparison.Ordinal) == true &&
element.Attribute("image") != null);
var sourceDirectory = new DirectoryInfo(Path.GetDirectoryName(moduleNodes.First().Attribute("image").Value));
var destinationDirectory = new DirectoryInfo(Path.Combine(contentRoot, sourceDirectory.Name));
destinationDirectory.Create();
foreach (var element in moduleNodes)
{
var imageAttribute = element.Attribute("image");
imageAttribute.Value = imageAttribute.Value.Replace(sourceDirectory.FullName, destinationDirectory.FullName);
}
CopyFiles(sourceDirectory, destinationDirectory);
});
}
private static void CopyFiles(DirectoryInfo source, DirectoryInfo target)
{
foreach (DirectoryInfo directoryInfo in source.GetDirectories())
{
CopyFiles(directoryInfo, target.CreateSubdirectory(directoryInfo.Name));
}
foreach (FileInfo fileInfo in source.GetFiles())
{
var destFileName = Path.Combine(target.FullName, fileInfo.Name);
fileInfo.CopyTo(destFileName, overwrite: true);
}
}
}
|