|
// 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.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)]
public class MultiApplicationTests : IISFunctionalTestBase
{
private PublishedApplication _publishedApplication;
private PublishedApplication _rootApplication;
public MultiApplicationTests(PublishedSitesFixture fixture) : base(fixture)
{
}
[ConditionalFact]
public async Task RunsTwoOutOfProcessApps()
{
var parameters = Fixture.GetBaseDeploymentParameters(HostingModel.OutOfProcess);
parameters.ServerConfigActionList.Add(DuplicateApplication);
var result = await DeployAsync(parameters);
var id1 = await result.HttpClient.GetStringAsync("/app1/ProcessId");
var id2 = await result.HttpClient.GetStringAsync("/app2/ProcessId");
Assert.NotEqual(id2, id1);
}
[ConditionalFact]
public async Task FailsAndLogsWhenRunningTwoInProcessApps()
{
var parameters = Fixture.GetBaseDeploymentParameters(HostingModel.InProcess);
parameters.ServerConfigActionList.Add(DuplicateApplication);
var result = await DeployAsync(parameters);
var result1 = await result.HttpClient.GetAsync("/app1/HelloWorld");
var result2 = await result.HttpClient.GetAsync("/app2/HelloWorld");
Assert.Equal(200, (int)result1.StatusCode);
Assert.Equal(500, (int)result2.StatusCode);
StopServer();
if (DeployerSelector.HasNewShim)
{
Assert.Contains("500.35", await result2.Content.ReadAsStringAsync());
}
await EventLogHelpers.VerifyEventLogEventAsync(result, EventLogHelpers.OnlyOneAppPerAppPool(), Logger);
}
[ConditionalTheory]
[InlineData(HostingModel.OutOfProcess)]
[InlineData(HostingModel.InProcess)]
public async Task FailsAndLogsEventLogForMixedHostingModel(HostingModel firstApp)
{
var parameters = Fixture.GetBaseDeploymentParameters(firstApp);
parameters.ServerConfigActionList.Add(DuplicateApplication);
var result = await DeployAsync(parameters);
// Modify hosting model of other app to be the opposite
var otherApp = firstApp == HostingModel.InProcess ? HostingModel.OutOfProcess : HostingModel.InProcess;
SetHostingModel(_publishedApplication.Path, otherApp);
var result1 = await result.HttpClient.GetAsync("/app1/HelloWorld");
var result2 = await result.HttpClient.GetAsync("/app2/HelloWorld");
Assert.Equal(200, (int)result1.StatusCode);
Assert.Equal(500, (int)result2.StatusCode);
StopServer();
if (DeployerSelector.HasNewShim)
{
Assert.Contains("500.34", await result2.Content.ReadAsStringAsync());
}
await EventLogHelpers.VerifyEventLogEventAsync(result, "Mixed hosting model is not supported.", Logger);
}
private void SetHostingModel(string directory, HostingModel model)
{
var webConfigLocation = GetWebConfigLocation(directory);
XDocument webConfig = XDocument.Load(webConfigLocation);
webConfig.Root
.Descendants("system.webServer")
.Single()
.GetOrAdd("aspNetCore")
.SetAttributeValue("hostingModel", model.ToString());
webConfig.Save(webConfigLocation);
}
private void DuplicateApplication(XElement config, string contentRoot)
{
var siteElement = config
.RequiredElement("system.applicationHost")
.RequiredElement("sites")
.Elements("site").Last();
var application = siteElement
.RequiredElement("application");
application.SetAttributeValue("path", "/app1");
var source = new DirectoryInfo(contentRoot);
var destination = new DirectoryInfo(contentRoot + "anotherApp");
destination.Create();
Helpers.CopyFiles(source, destination, Logger);
_publishedApplication = new PublishedApplication(destination.FullName, Logger);
var newApplication = new XElement(application);
newApplication.SetAttributeValue("path", "/app2");
newApplication.RequiredElement("virtualDirectory")
.SetAttributeValue("physicalPath", destination.FullName);
siteElement.Add(newApplication);
// IIS Express requires root application to exist
_rootApplication = new PublishedApplication(Helpers.CreateEmptyApplication(config, contentRoot), Logger);
}
private static string GetWebConfigLocation(string siteRoot)
{
return Path.Combine(siteRoot, "web.config");
}
public override void Dispose()
{
base.Dispose();
_rootApplication.Dispose();
_publishedApplication.Dispose();
}
}
|