public static async Task <MSBuildResult> RunProcessAsync( ProjectDirectory project, string arguments, TimeSpan?timeout = null, MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet) { var processStartInfo = new ProcessStartInfo() { WorkingDirectory = project.DirectoryPath, UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true, }; if (msBuildProcessKind == MSBuildProcessKind.Desktop) { if (string.IsNullOrEmpty(BuildVariables.MSBuildPath)) { throw new ArgumentException("Unable to locate MSBuild.exe to run desktop tests. " + "MSBuild.exe is located using state created as part of running build[cmd|sh] at the root of the repository. Run build /t:Prepare to set this up if this hasn't been done."); } processStartInfo.FileName = BuildVariables.MSBuildPath; processStartInfo.Arguments = arguments; } else { processStartInfo.FileName = "dotnet"; processStartInfo.Arguments = $"msbuild {arguments}"; } var processResult = await RunProcessCoreAsync(processStartInfo, timeout); return(new MSBuildResult(project, processResult.FileName, processResult.Arguments, processResult.ExitCode, processResult.Output)); }
internal Task <MSBuildResult> DotnetMSBuild( string target, string args = null, bool suppressRestore = false, bool suppressTimeout = false, bool suppressBuildServer = false, MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet) { var timeout = suppressTimeout ? (TimeSpan?)Timeout.InfiniteTimeSpan : null; var buildArgumentList = new List <string>(); if (!suppressRestore) { buildArgumentList.Add("/restore"); } if (!suppressBuildServer) { buildArgumentList.Add($"/p:_RazorBuildServerPipeName={BuildServer.PipeName}"); } buildArgumentList.Add($"/t:{target} /p:Configuration={Configuration} {args}"); var buildArguments = string.Join(" ", buildArgumentList); return(MSBuildProcessManager.RunProcessAsync( Project, buildArguments, timeout, msBuildProcessKind)); }
private async Task Build_SimpleMvc_CanBuildSuccessfully(MSBuildProcessKind msBuildProcessKind) { var result = await DotnetMSBuild( "Build", $"/p:RazorCompileOnBuild=true /p:UseRazorBuildServer=true /p:_RazorBuildServerPipeName={_pipeName} /p:_RazorForceBuildServer=true", msBuildProcessKind : msBuildProcessKind); Assert.BuildPassed(result); Assert.FileExists(result, OutputPath, "SimpleMvc.dll"); Assert.FileExists(result, OutputPath, "SimpleMvc.pdb"); Assert.FileExists(result, OutputPath, "SimpleMvc.PrecompiledViews.dll"); Assert.FileExists(result, OutputPath, "SimpleMvc.PrecompiledViews.pdb"); }
private async Task Build_ComponentsWorks(MSBuildProcessKind msBuildProcessKind) { var result = await DotnetMSBuild("Build", msBuildProcessKind : msBuildProcessKind); Assert.BuildPassed(result); Assert.FileExists(result, OutputPath, "MvcWithComponents.dll"); Assert.FileExists(result, OutputPath, "MvcWithComponents.pdb"); Assert.FileExists(result, OutputPath, "MvcWithComponents.Views.dll"); Assert.FileExists(result, OutputPath, "MvcWithComponents.Views.pdb"); Assert.AssemblyContainsType(result, Path.Combine(OutputPath, "MvcWithComponents.dll"), "MvcWithComponents.TestComponent"); Assert.AssemblyContainsType(result, Path.Combine(OutputPath, "MvcWithComponents.dll"), "MvcWithComponents.Views.Shared.NavMenu"); }
internal Task <MSBuildResult> DotnetMSBuild( string target, string args = null, bool suppressTimeout = false, bool suppressBuildServer = false, string buildServerPipeName = null, MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet) { var timeout = suppressTimeout ? (TimeSpan?)Timeout.InfiniteTimeSpan : null; var buildArgumentList = new List <string> { // Disable node-reuse. We don't want msbuild processes to stick around // once the test is completed. "/nr:false", // Always generate a bin log for debugging purposes "/bl", // Let the test app know it is running as part of a test. "/p:RunningAsTest=true", $"/p:MicrosoftNETCoreAppRuntimeVersion={BuildVariables.MicrosoftNETCoreAppRuntimeVersion}", $"/p:MicrosoftNetCompilersToolsetPackageVersion={BuildVariables.MicrosoftNetCompilersToolsetPackageVersion}", $"/p:RazorSdkDirectoryRoot={BuildVariables.RazorSdkDirectoryRoot}", $"/p:RepoRoot={BuildVariables.RepoRoot}", }; if (!suppressBuildServer) { buildArgumentList.Add($@"/p:_RazorBuildServerPipeName=""{buildServerPipeName ?? BuildServer.PipeName}"""); } if (!string.IsNullOrEmpty(target)) { buildArgumentList.Add($"/t:{target}"); } else { buildArgumentList.Add($"/t:Build"); } buildArgumentList.Add($"/p:Configuration={Configuration} {args}"); var buildArguments = string.Join(" ", buildArgumentList); return(MSBuildProcessManager.RunProcessAsync( Project, buildArguments, timeout, msBuildProcessKind)); }
internal Task <MSBuildResult> DotnetMSBuild( string target, string args = null, bool suppressRestore = false, bool suppressTimeout = false, MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet) { var timeout = suppressTimeout ? (TimeSpan?)Timeout.InfiniteTimeSpan : null; var restoreArgument = suppressRestore ? "" : "/restore"; return(MSBuildProcessManager.RunProcessAsync( Project, $"{restoreArgument} /t:{target} /p:Configuration={Configuration} {args}", timeout, msBuildProcessKind)); }
private async Task Build_SimpleMvc_CanBuildSuccessfully(MSBuildProcessKind msBuildProcessKind) { var result = await DotnetMSBuild("Build", "/p:RazorCompileOnBuild=true", msBuildProcessKind : msBuildProcessKind); Assert.BuildPassed(result); Assert.FileExists(result, OutputPath, "SimpleMvc.dll"); Assert.FileExists(result, OutputPath, "SimpleMvc.pdb"); Assert.FileExists(result, OutputPath, "SimpleMvc.PrecompiledViews.dll"); Assert.FileExists(result, OutputPath, "SimpleMvc.PrecompiledViews.pdb"); if (RuntimeEnvironment.OperatingSystemPlatform != Platform.Darwin) { // GetFullPath on OSX doesn't work well in travis. We end up computing a different path than will // end up in the MSBuild logs. Assert.BuildOutputContainsLine(result, $"SimpleMvc -> {Path.Combine(Path.GetFullPath(Project.DirectoryPath), OutputPath, "SimpleMvc.PrecompiledViews.dll")}"); } }
public static async Task <MSBuildResult> RunProcessAsync( ProjectDirectory project, string arguments, TimeSpan?timeout = null, MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet, string localPackageCache = null) { var processStartInfo = new ProcessStartInfo() { WorkingDirectory = project.DirectoryPath, UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true, }; if (localPackageCache != null) { processStartInfo.Environment.Add("NUGET_PACKAGES", localPackageCache); } if (msBuildProcessKind == MSBuildProcessKind.Desktop) { if (string.IsNullOrEmpty(BuildVariables.MSBuildPath)) { throw new ArgumentException("Unable to locate MSBuild.exe to run desktop tests. " + "MSBuild.exe is located using state created as part of running build[cmd|sh] at the root of the repository. Run build /t:Prepare to set this up if this hasn't been done."); } processStartInfo.FileName = BuildVariables.MSBuildPath; processStartInfo.Arguments = arguments; } else { processStartInfo.FileName = DotNetMuxer.MuxerPathOrDefault(); processStartInfo.Arguments = $"msbuild {arguments}"; // Suppresses the 'Welcome to .NET Core!' output that times out tests and causes locked file issues. // When using dotnet we're not guarunteed to run in an environment where the dotnet.exe has had its first run experience already invoked. processStartInfo.EnvironmentVariables["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "true"; } var processResult = await RunProcessCoreAsync(processStartInfo, timeout); return(new MSBuildResult(project, processResult.FileName, processResult.Arguments, processResult.ExitCode, processResult.Output)); }
// This test is identical to the ones in BuildServerIntegrationTest except this one explicitly disables the Razor build server. private async Task Build_SimpleMvc_WithoutBuildServer_CanBuildSuccessfully(MSBuildProcessKind msBuildProcessKind) { var result = await DotnetMSBuild("Build", "/p:UseRazorBuildServer=false", suppressBuildServer : true, msBuildProcessKind : msBuildProcessKind); Assert.BuildPassed(result); Assert.FileExists(result, OutputPath, "SimpleMvc.dll"); Assert.FileExists(result, OutputPath, "SimpleMvc.pdb"); Assert.FileExists(result, OutputPath, "SimpleMvc.Views.dll"); Assert.FileExists(result, OutputPath, "SimpleMvc.Views.pdb"); if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { // GetFullPath on OSX doesn't work well in travis. We end up computing a different path than will // end up in the MSBuild logs. Assert.BuildOutputContainsLine(result, $"SimpleMvc -> {Path.Combine(Path.GetFullPath(Project.DirectoryPath), OutputPath, "SimpleMvc.Views.dll")}"); } }
private async Task Build_SimpleMvc_CanBuildSuccessfully(MSBuildProcessKind msBuildProcessKind) { var result = await DotnetMSBuild("Build", "/p:RazorCompileOnBuild=true", msBuildProcessKind : msBuildProcessKind); Assert.BuildPassed(result); Assert.FileExists(result, OutputPath, "SimpleMvc.dll"); Assert.FileExists(result, OutputPath, "SimpleMvc.pdb"); Assert.FileExists(result, OutputPath, "SimpleMvc.PrecompiledViews.dll"); Assert.FileExists(result, OutputPath, "SimpleMvc.PrecompiledViews.pdb"); if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { // GetFullPath on OSX doesn't work well in travis. We end up computing a different path than will // end up in the MSBuild logs. Assert.BuildOutputContainsLine(result, $"SimpleMvc -> {Path.Combine(Path.GetFullPath(Project.DirectoryPath), OutputPath, "SimpleMvc.PrecompiledViews.dll")}"); } result = await DotnetMSBuild("_IntrospectPreserveCompilationContext"); Assert.BuildPassed(result); Assert.BuildOutputContainsLine(result, "PreserveCompilationContext: true"); }
private async Task Build_ComponentsWorks(MSBuildProcessKind msBuildProcessKind) { var result = await DotnetMSBuild("Build", msBuildProcessKind : msBuildProcessKind); Assert.BuildPassed(result); Assert.FileExists(result, OutputPath, "MvcWithComponents.dll"); Assert.FileExists(result, OutputPath, "MvcWithComponents.pdb"); Assert.FileExists(result, OutputPath, "MvcWithComponents.Views.dll"); Assert.FileExists(result, OutputPath, "MvcWithComponents.Views.pdb"); Assert.AssemblyContainsType(result, Path.Combine(OutputPath, "MvcWithComponents.dll"), "MvcWithComponents.TestComponent"); Assert.AssemblyContainsType(result, Path.Combine(OutputPath, "MvcWithComponents.dll"), "MvcWithComponents.Views.Shared.NavMenu"); // This is a component file with a .cshtml extension. It should appear in the main assembly, but not in the views dll. Assert.AssemblyContainsType(result, Path.Combine(OutputPath, "MvcWithComponents.dll"), "MvcWithComponents.Components.Counter"); Assert.AssemblyDoesNotContainType(result, Path.Combine(OutputPath, "MvcWithComponents.Views.dll"), "MvcWithComponents.Components.Counter"); Assert.AssemblyDoesNotContainType(result, Path.Combine(OutputPath, "MvcWithComponents.Views.dll"), "AspNetCore.Components_Counter"); // Verify a regular View appears in the views dll, but not in the main assembly. Assert.AssemblyDoesNotContainType(result, Path.Combine(OutputPath, "MvcWithComponents.dll"), "AspNetCore.Views.Home.Index"); Assert.AssemblyDoesNotContainType(result, Path.Combine(OutputPath, "MvcWithComponents.dll"), "AspNetCore.Views_Home_Index"); Assert.AssemblyContainsType(result, Path.Combine(OutputPath, "MvcWithComponents.Views.dll"), "AspNetCore.Views_Home_Index"); }
private async Task Build_SimpleMvc_CanBuildSuccessfully(MSBuildProcessKind msBuildProcessKind) { var result = await DotnetMSBuild( "Build", "/p:_RazorForceBuildServer=true", msBuildProcessKind : msBuildProcessKind); Assert.BuildPassed(result); Assert.FileExists(result, OutputPath, "SimpleMvc.dll"); Assert.FileExists(result, OutputPath, "SimpleMvc.pdb"); Assert.FileExists(result, OutputPath, "SimpleMvc.Views.dll"); Assert.FileExists(result, OutputPath, "SimpleMvc.Views.pdb"); // Verify RazorTagHelper works Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.TagHelpers.input.cache"); Assert.FileExists(result, IntermediateOutputPath, "SimpleMvc.TagHelpers.output.cache"); Assert.FileContains( result, Path.Combine(IntermediateOutputPath, "SimpleMvc.TagHelpers.output.cache"), @"""Name"":""SimpleMvc.SimpleTagHelper"""); // Verify RazorGenerate works Assert.FileCountEquals(result, 8, RazorIntermediateOutputPath, "*.cs"); }
public static Task <MSBuildResult> RunProcessAsync( ProjectDirectory project, string arguments, TimeSpan?timeout = null, MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet) { timeout = timeout ?? TimeSpan.FromSeconds(60); var processStartInfo = new ProcessStartInfo() { WorkingDirectory = project.DirectoryPath, UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true, }; if (msBuildProcessKind == MSBuildProcessKind.Desktop) { if (string.IsNullOrEmpty(BuildVariables.MSBuildPath)) { throw new ArgumentException("Unable to locate MSBuild.exe to run desktop tests."); } processStartInfo.FileName = BuildVariables.MSBuildPath; processStartInfo.Arguments = arguments; } else { processStartInfo.FileName = "dotnet"; processStartInfo.Arguments = $"msbuild {arguments}"; } var process = new Process() { StartInfo = processStartInfo, EnableRaisingEvents = true, }; var completionSource = new TaskCompletionSource <MSBuildResult>(); var output = new StringBuilder(); process.Exited += Process_Exited; process.ErrorDataReceived += Process_ErrorDataReceived; process.OutputDataReceived += Process_OutputDataReceived; process.Start(); process.BeginErrorReadLine(); process.BeginOutputReadLine(); var timeoutTask = Task.Delay(timeout.Value).ContinueWith((t) => { // Don't timeout during debug sessions while (Debugger.IsAttached) { Thread.Sleep(TimeSpan.FromSeconds(1)); } if (process.HasExited) { // This will happen on success, the 'real' task has already completed so this value will // never be visible. return((MSBuildResult)null); } // This is a timeout. process.Kill(); throw new TimeoutException($"command '${process.StartInfo.FileName} {process.StartInfo.Arguments}' timed out after {timeout}."); }); return(Task.WhenAny <MSBuildResult>(completionSource.Task, timeoutTask).Unwrap()); void Process_Exited(object sender, EventArgs e) { var result = new MSBuildResult(project, process.StartInfo.FileName, process.StartInfo.Arguments, process.ExitCode, output.ToString()); completionSource.SetResult(result); } void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e) { output.AppendLine(e.Data); } void Process_OutputDataReceived(object sender, DataReceivedEventArgs e) { output.AppendLine(e.Data); } }
public static async Task <MSBuildResult> RunProcessAsync( ProjectDirectory project, string arguments, TimeSpan?timeout = null, MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet) { var processStartInfo = new ProcessStartInfo() { WorkingDirectory = project.DirectoryPath, UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true, }; if (msBuildProcessKind == MSBuildProcessKind.Desktop) { if (string.IsNullOrEmpty(BuildVariables.MSBuildPath)) { throw new ArgumentException("Unable to locate MSBuild.exe to run desktop tests. " + "MSBuild.exe is located using state created as part of running build[cmd|sh] at the root of the repository. Run build /t:Prepare to set this up if this hasn't been done."); } processStartInfo.FileName = BuildVariables.MSBuildPath; processStartInfo.Arguments = arguments; } else { processStartInfo.FileName = DotNetMuxer.MuxerPathOrDefault(); processStartInfo.Arguments = $"msbuild {arguments}"; // Suppresses the 'Welcome to .NET Core!' output that times out tests and causes locked file issues. // When using dotnet we're not guarunteed to run in an environment where the dotnet.exe has had its first run experience already invoked. processStartInfo.EnvironmentVariables["DOTNET_SKIP_FIRST_TIME_EXPERIENCE"] = "true"; } ProcessResult processResult; try { processResult = await RunProcessCoreAsync(processStartInfo, timeout); } catch (TimeoutException ex) { // Copy the binlog to the artifacts directory if executing MSBuild throws. // This would help diagnosing failures on the CI. var binaryLogFile = Path.Combine(project.ProjectFilePath, "msbuild.binlog"); var artifactsLogDir = Assembly.GetExecutingAssembly() .GetCustomAttributes <AssemblyMetadataAttribute>() .FirstOrDefault(ama => ama.Key == "ArtifactsLogDir")?.Value; if (!string.IsNullOrEmpty(artifactsLogDir) && File.Exists(binaryLogFile)) { var targetPath = Path.Combine(artifactsLogDir, Path.GetFileNameWithoutExtension(project.ProjectFilePath) + "." + Path.GetRandomFileName() + ".binlog"); File.Copy(binaryLogFile, targetPath); throw new TimeoutException(ex.Message + $"{Environment.NewLine}Captured binlog at {targetPath}"); } throw; } return(new MSBuildResult(project, processResult.FileName, processResult.Arguments, processResult.ExitCode, processResult.Output)); }
public static Task <MSBuildResult> RunProcessAsync( ProjectDirectory project, string arguments, TimeSpan?timeout = null, MSBuildProcessKind msBuildProcessKind = MSBuildProcessKind.Dotnet) { timeout = timeout ?? TimeSpan.FromSeconds(60); var processStartInfo = new ProcessStartInfo() { WorkingDirectory = project.DirectoryPath, UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true, }; if (msBuildProcessKind == MSBuildProcessKind.Desktop) { if (string.IsNullOrEmpty(BuildVariables.MSBuildPath)) { throw new ArgumentException("Unable to locate MSBuild.exe to run desktop tests. " + "MSBuild.exe is located using state created as part of running build[cmd|sh] at the root of the repository. Run build /t:Prepare to set this up if this hasn't been done."); } processStartInfo.FileName = BuildVariables.MSBuildPath; processStartInfo.Arguments = arguments; } else { processStartInfo.FileName = "dotnet"; processStartInfo.Arguments = $"msbuild {arguments}"; } var process = new Process() { StartInfo = processStartInfo, EnableRaisingEvents = true, }; var output = new StringBuilder(); var outputLock = new object(); process.ErrorDataReceived += Process_ErrorDataReceived; process.OutputDataReceived += Process_OutputDataReceived; process.Start(); process.BeginErrorReadLine(); process.BeginOutputReadLine(); var timeoutTask = Task.Delay(timeout.Value).ContinueWith((t) => { // Don't timeout during debug sessions while (Debugger.IsAttached) { Thread.Sleep(TimeSpan.FromSeconds(1)); } if (process.HasExited) { // This will happen on success, the 'real' task has already completed so this value will // never be visible. return((MSBuildResult)null); } // This is a timeout. process.Kill(); throw new TimeoutException($"command '${process.StartInfo.FileName} {process.StartInfo.Arguments}' timed out after {timeout}."); }); var waitTask = Task.Run(() => { // We need to use two WaitForExit calls to ensure that all of the output/events are processed. Previously // this code used Process.Exited, which could result in us missing some output due to the ordering of // events. // // See the remarks here: https://msdn.microsoft.com/en-us/library/ty0d8k56(v=vs.110).aspx if (!process.WaitForExit(Int32.MaxValue)) { // unreachable - the timeoutTask will kill the process before this happens. throw new TimeoutException(); } process.WaitForExit(); string outputString; lock (outputLock) { outputString = output.ToString(); } var result = new MSBuildResult(project, process.StartInfo.FileName, process.StartInfo.Arguments, process.ExitCode, outputString); return(result); }); return(Task.WhenAny <MSBuildResult>(waitTask, timeoutTask).Unwrap()); void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e) { lock (outputLock) { output.AppendLine(e.Data); } } void Process_OutputDataReceived(object sender, DataReceivedEventArgs e) { lock (outputLock) { output.AppendLine(e.Data); } } }
private async Task Build_ProjectWithDependencyThatReferencesMvc_AddsAttribute(MSBuildProcessKind msBuildProcessKind) { var result = await DotnetMSBuild("Build", msBuildProcessKind : msBuildProcessKind); Assert.BuildPassed(result); Assert.FileExists(result, IntermediateOutputPath, "AppWithP2PReference.MvcApplicationPartsAssemblyInfo.cs"); Assert.FileContains(result, Path.Combine(IntermediateOutputPath, "AppWithP2PReference.MvcApplicationPartsAssemblyInfo.cs"), "[assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute(\"ClassLibrary\")]"); Assert.AssemblyHasAttribute(result, Path.Combine(OutputPath, "AppWithP2PReference.dll"), "Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute"); }