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 System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.Tools; using Microsoft.AspNetCore.Razor.Tools;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit; using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Moq; using Moq;
@ -143,28 +144,62 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
// it reaches server creation part. // 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] [ConditionalFact]
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
[InitializeTestProject("SimpleMvc")] [InitializeTestProject("SimpleMvc")]
public async Task ManualServerShutdown_NoPipeName_ShutsDownServer() public async Task ManualServerShutdown_NoPipeName_ShutsDownServer()
{ {
var toolAssembly = typeof(Application).Assembly.Location; // We are trying to test whether the correct pipe name is generated (from the location of rzc tool)
var result = await DotnetMSBuild( // when we don't explicitly specify a pipe name.
"Build",
$"/p:_RazorForceBuildServer=true /p:_RazorToolAssembly={toolAssembly}",
suppressBuildServer: true); // We don't want to 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 try
var output = new StringWriter(); {
var error = new StringWriter(); // Make sure publish succeeded.
var application = new Application(CancellationToken.None, Mock.Of<ExtensionAssemblyLoader>(), Mock.Of<ExtensionDependencyChecker>(), (path, properties) => Mock.Of<PortableExecutableReference>(), output, error); Assert.BuildPassed(publishResult);
var exitCode = application.Execute("shutdown", "-w");
Assert.Equal(0, exitCode); // Run the build using the published tool
Assert.Contains("shut down completed", output.ToString()); 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] [Fact]
@ -195,5 +230,13 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
fixture.Dispose(); 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 internal static class MSBuildProcessManager
{ {
public static Task<MSBuildResult> RunProcessAsync( public static async Task<MSBuildResult> RunProcessAsync(
ProjectDirectory project, ProjectDirectory project,
string arguments, string arguments,
TimeSpan? timeout = null, TimeSpan? timeout = null,
MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet) MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet)
{ {
timeout = timeout ?? TimeSpan.FromSeconds(120);
var processStartInfo = new ProcessStartInfo() var processStartInfo = new ProcessStartInfo()
{ {
WorkingDirectory = project.DirectoryPath, WorkingDirectory = project.DirectoryPath,
@ -44,6 +42,17 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
processStartInfo.Arguments = $"msbuild {arguments}"; 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() var process = new Process()
{ {
StartInfo = processStartInfo, StartInfo = processStartInfo,
@ -57,10 +66,10 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
process.OutputDataReceived += Process_OutputDataReceived; process.OutputDataReceived += Process_OutputDataReceived;
process.Start(); process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine(); 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 // Don't timeout during debug sessions
while (Debugger.IsAttached) while (Debugger.IsAttached)
@ -98,11 +107,11 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
outputString = output.ToString(); 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 result;
}); });
return Task.WhenAny<MSBuildResult>(waitTask, timeoutTask).Unwrap(); return Task.WhenAny<ProcessResult>(waitTask, timeoutTask).Unwrap();
void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e) 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; SolutionPath = solutionPath;
DirectoryPath = directoryPath; DirectoryPath = directoryPath;
@ -164,7 +164,7 @@ $@"<Project>
} }
} }
private static void CleanupDirectory(string filePath) internal static void CleanupDirectory(string filePath)
{ {
var tries = 5; var tries = 5;
var sleep = TimeSpan.FromSeconds(3); var sleep = TimeSpan.FromSeconds(3);