diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildServerIntegrationTest.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildServerIntegrationTest.cs index efd1187c6e..4de9dfca4b 100644 --- a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildServerIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildServerIntegrationTest.cs @@ -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(), Mock.Of(), (path, properties) => Mock.Of(), 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) + { + } + } } } diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildProcessManager.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildProcessManager.cs index cda20de69b..d38ae9f5f5 100644 --- a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildProcessManager.cs +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildProcessManager.cs @@ -11,14 +11,12 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests { internal static class MSBuildProcessManager { - public static Task RunProcessAsync( + public static async Task 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 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((t) => + var timeoutTask = Task.Delay(timeout.Value).ContinueWith((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(waitTask, timeoutTask).Unwrap(); + return Task.WhenAny(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; } + } } } diff --git a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/ProjectDirectory.cs b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/ProjectDirectory.cs index fcfdd30311..7a80ce4c31 100644 --- a/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/ProjectDirectory.cs +++ b/test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/ProjectDirectory.cs @@ -139,7 +139,7 @@ $@" } } - private ProjectDirectory(string solutionPath, string directoryPath, string projectFilePath) + protected ProjectDirectory(string solutionPath, string directoryPath, string projectFilePath) { SolutionPath = solutionPath; DirectoryPath = directoryPath; @@ -164,7 +164,7 @@ $@" } } - private static void CleanupDirectory(string filePath) + internal static void CleanupDirectory(string filePath) { var tries = 5; var sleep = TimeSpan.FromSeconds(3);