Change testing strategy for build server shutdown test

This commit is contained in:
Ajay Bhargav Baaskaran 2018-10-29 19:00:04 -07:00
parent 8674dd9236
commit 8e62dbcae9
3 changed files with 94 additions and 23 deletions

View File

@ -8,6 +8,7 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Tools;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.CodeAnalysis;
using Moq;
@ -143,28 +144,62 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
// it reaches server creation part.
}
// Skipping on linux/mac because of https://github.com/aspnet/Razor/issues/2507.
// Skipping on MacOS because of https://github.com/dotnet/corefx/issues/33141.
// Skipping on Linux because of https://github.com/aspnet/Razor/issues/2525.
[ConditionalFact]
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
[InitializeTestProject("SimpleMvc")]
public async Task ManualServerShutdown_NoPipeName_ShutsDownServer()
{
var toolAssembly = typeof(Application).Assembly.Location;
var result = await DotnetMSBuild(
"Build",
$"/p:_RazorForceBuildServer=true /p:_RazorToolAssembly={toolAssembly}",
suppressBuildServer: true); // We don't want to specify a pipe name
// We are trying to test whether the correct pipe name is generated (from the location of rzc tool)
// when we don't explicitly specify a pipe name.
Assert.BuildPassed(result);
// Publish rzc tool to a temporary path. This is the location based on which the pipe name is generated.
var solutionRoot = TestPathUtilities.GetSolutionRootDirectory("Razor");
var toolAssemblyDirectory = Path.Combine(solutionRoot, "src", "Microsoft.AspNetCore.Razor.Tools");
var toolAssemblyPath = Path.Combine(toolAssemblyDirectory, "Microsoft.AspNetCore.Razor.Tools.csproj");
var projectDirectory = new TestProjectDirectory(solutionRoot, toolAssemblyDirectory, toolAssemblyPath);
var publishDir = Path.Combine(Path.GetTempPath(), "Razor", Path.GetRandomFileName(), "RzcPublish");
var publishResult = await MSBuildProcessManager.RunProcessAsync(projectDirectory, $"/t:Publish /p:PublishDir=\"{publishDir}\"");
// Shutdown the server
var output = new StringWriter();
var error = new StringWriter();
var application = new Application(CancellationToken.None, Mock.Of<ExtensionAssemblyLoader>(), Mock.Of<ExtensionDependencyChecker>(), (path, properties) => Mock.Of<PortableExecutableReference>(), output, error);
var exitCode = application.Execute("shutdown", "-w");
try
{
// Make sure publish succeeded.
Assert.BuildPassed(publishResult);
Assert.Equal(0, exitCode);
Assert.Contains("shut down completed", output.ToString());
// Run the build using the published tool
var toolAssembly = Path.Combine(publishDir, "rzc.dll");
var result = await DotnetMSBuild(
"Build",
$"/p:_RazorForceBuildServer=true /p:_RazorToolAssembly={toolAssembly}",
suppressBuildServer: true); // We don't want to specify a pipe name
Assert.BuildPassed(result);
// Manually shutdown the server
var processStartInfo = new ProcessStartInfo()
{
WorkingDirectory = publishDir,
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true,
FileName = "dotnet",
Arguments = $"{toolAssembly} shutdown -w"
};
var logFilePath = Path.Combine(publishDir, "out.log");
processStartInfo.Environment.Add("RAZORBUILDSERVER_LOG", logFilePath);
var shutdownResult = await MSBuildProcessManager.RunProcessCoreAsync(processStartInfo);
Assert.Equal(0, shutdownResult.ExitCode);
var output = await File.ReadAllTextAsync(logFilePath);
Assert.Contains("shut down completed", output);
}
finally
{
// Finally delete the temporary publish directory
ProjectDirectory.CleanupDirectory(publishDir);
}
}
[Fact]
@ -195,5 +230,13 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
fixture.Dispose();
}
}
private class TestProjectDirectory : ProjectDirectory
{
public TestProjectDirectory(string solutionPath, string directoryPath, string projectFilePath)
: base(solutionPath, directoryPath, projectFilePath)
{
}
}
}
}

View File

@ -11,14 +11,12 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
{
internal static class MSBuildProcessManager
{
public static Task<MSBuildResult> RunProcessAsync(
public static async Task<MSBuildResult> RunProcessAsync(
ProjectDirectory project,
string arguments,
TimeSpan? timeout = null,
MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet)
{
timeout = timeout ?? TimeSpan.FromSeconds(120);
var processStartInfo = new ProcessStartInfo()
{
WorkingDirectory = project.DirectoryPath,
@ -44,6 +42,17 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
processStartInfo.Arguments = $"msbuild {arguments}";
}
var processResult = await RunProcessCoreAsync(processStartInfo, timeout);
return new MSBuildResult(project, processResult.FileName, processResult.Arguments, processResult.ExitCode, processResult.Output);
}
internal static Task<ProcessResult> RunProcessCoreAsync(
ProcessStartInfo processStartInfo,
TimeSpan? timeout = null)
{
timeout = timeout ?? TimeSpan.FromSeconds(120);
var process = new Process()
{
StartInfo = processStartInfo,
@ -57,10 +66,10 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
process.OutputDataReceived += Process_OutputDataReceived;
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
var timeoutTask = Task.Delay(timeout.Value).ContinueWith<MSBuildResult>((t) =>
var timeoutTask = Task.Delay(timeout.Value).ContinueWith<ProcessResult>((t) =>
{
// Don't timeout during debug sessions
while (Debugger.IsAttached)
@ -98,11 +107,11 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
outputString = output.ToString();
}
var result = new MSBuildResult(project, process.StartInfo.FileName, process.StartInfo.Arguments, process.ExitCode, outputString);
var result = new ProcessResult(process.StartInfo.FileName, process.StartInfo.Arguments, process.ExitCode, outputString);
return result;
});
return Task.WhenAny<MSBuildResult>(waitTask, timeoutTask).Unwrap();
return Task.WhenAny<ProcessResult>(waitTask, timeoutTask).Unwrap();
void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
@ -120,5 +129,24 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
}
}
}
internal class ProcessResult
{
public ProcessResult(string fileName, string arguments, int exitCode, string output)
{
FileName = fileName;
Arguments = arguments;
ExitCode = exitCode;
Output = output;
}
public string Arguments { get; }
public string FileName { get; }
public int ExitCode { get; }
public string Output { get; }
}
}
}

View File

@ -139,7 +139,7 @@ $@"<Project>
}
}
private ProjectDirectory(string solutionPath, string directoryPath, string projectFilePath)
protected ProjectDirectory(string solutionPath, string directoryPath, string projectFilePath)
{
SolutionPath = solutionPath;
DirectoryPath = directoryPath;
@ -164,7 +164,7 @@ $@"<Project>
}
}
private static void CleanupDirectory(string filePath)
internal static void CleanupDirectory(string filePath)
{
var tries = 5;
var sleep = TimeSpan.FromSeconds(3);