aspnetcore/test/IISExpress.FunctionalTests/InProcess/AppOfflineTests.cs

160 lines
5.8 KiB
C#

// 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.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.IIS.FunctionalTests.Utilities;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests;
using Microsoft.AspNetCore.Server.IntegrationTesting;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging;
using Xunit;
using Microsoft.AspNetCore.Server.IntegrationTesting.IIS;
namespace Microsoft.AspNetCore.Server.IIS.FunctionalTests.Inprocess
{
public class AppOfflineTests : IISFunctionalTestBase
{
// TODO these will differ between IIS and IISExpress
[ConditionalTheory]
[InlineData(HostingModel.InProcess)]
[InlineData(HostingModel.OutOfProcess)]
public async Task AppOfflineDroppedWhileSiteIsDown_SiteReturns503(HostingModel hostingModel)
{
var deploymentResult = await DeployApp(hostingModel);
AddAppOffline(deploymentResult.ContentRoot);
await AssertAppOffline(deploymentResult);
}
[ConditionalTheory]
[InlineData(HostingModel.InProcess)]
[InlineData(HostingModel.OutOfProcess)]
public async Task AppOfflineDroppedWhileSiteIsDown_CustomResponse(HostingModel hostingModel)
{
var expectedResponse = "The app is offline.";
var deploymentResult = await DeployApp(hostingModel);
AddAppOffline(deploymentResult.ContentRoot, expectedResponse);
await AssertAppOffline(deploymentResult, expectedResponse);
}
[ConditionalFact]
public async Task AppOfflineDroppedWhileSiteRunning_SiteShutsDown_InProcess()
{
var deploymentResult = await AssertStarts(HostingModel.InProcess);
AddAppOffline(deploymentResult.ContentRoot);
await AssertStopsProcess(deploymentResult);
}
[ConditionalFact]
public async Task AppOfflineDroppedWhileSiteRunning_SiteShutsDown_OutOfProcess()
{
var deploymentResult = await AssertStarts(HostingModel.OutOfProcess);
// Repeat dropping file and restarting multiple times
for (int i = 0; i < 5; i++)
{
AddAppOffline(deploymentResult.ContentRoot);
await AssertAppOffline(deploymentResult);
RemoveAppOffline(deploymentResult.ContentRoot);
await AssertRunning(deploymentResult);
}
}
[ConditionalTheory]
[InlineData(HostingModel.InProcess)]
[InlineData(HostingModel.OutOfProcess)]
public async Task AppOfflineDropped_CanRemoveAppOfflineAfterAddingAndSiteWorks(HostingModel hostingModel)
{
var deploymentResult = await DeployApp(hostingModel);
AddAppOffline(deploymentResult.ContentRoot);
await AssertAppOffline(deploymentResult);
RemoveAppOffline(deploymentResult.ContentRoot);
await AssertRunning(deploymentResult);
}
private async Task<IISDeploymentResult> DeployApp(HostingModel hostingModel = HostingModel.InProcess)
{
var deploymentParameters = Helpers.GetBaseDeploymentParameters(hostingModel: hostingModel, publish: true);
return await DeployAsync(deploymentParameters);
}
private void AddAppOffline(string appPath, string content = "")
{
File.WriteAllText(Path.Combine(appPath, "app_offline.htm"), content);
}
private void RemoveAppOffline(string appPath)
{
RetryHelper.RetryOperation(
() => File.Delete(Path.Combine(appPath, "app_offline.htm")),
e => Logger.LogError($"Failed to remove app_offline : {e.Message}"),
retryCount: 3,
retryDelayMilliseconds: 100);
}
private async Task AssertAppOffline(IISDeploymentResult deploymentResult, string expectedResponse = "")
{
var response = await deploymentResult.HttpClient.GetAsync("HelloWorld");
for (var i = 0; response.IsSuccessStatusCode && i < 5; i++)
{
// Keep retrying until app_offline is present.
response = await deploymentResult.HttpClient.GetAsync("HelloWorld");
}
Assert.Equal(HttpStatusCode.ServiceUnavailable, response.StatusCode);
Assert.Equal(expectedResponse, await response.Content.ReadAsStringAsync());
}
private async Task AssertStopsProcess(IISDeploymentResult deploymentResult)
{
try
{
var response = await deploymentResult.RetryingHttpClient.GetAsync("HelloWorld");
}
catch (HttpRequestException)
{
// dropping app_offline will kill the process
}
var hostShutdownToken = deploymentResult.HostShutdownToken;
Assert.True(hostShutdownToken.WaitHandle.WaitOne(TimeoutExtensions.DefaultTimeout));
Assert.True(hostShutdownToken.IsCancellationRequested);
}
private async Task<IISDeploymentResult> AssertStarts(HostingModel hostingModel)
{
var deploymentResult = await DeployApp(hostingModel);
await AssertRunning(deploymentResult);
return deploymentResult;
}
private static async Task AssertRunning(IISDeploymentResult deploymentResult)
{
var response = await deploymentResult.RetryingHttpClient.GetAsync("HelloWorld");
var responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("Hello World", responseText);
}
}
}