Skip to content

Commit 0905cdc

Browse files
Remove outdated test logging + fix the sidecar test (#12607)
1 parent 7353174 commit 0905cdc

File tree

1 file changed

+46
-224
lines changed

1 file changed

+46
-224
lines changed

src/Build.UnitTests/BackEnd/TaskHostFactory_Tests.cs

Lines changed: 46 additions & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5-
using System.Collections.Generic;
65
using System.Diagnostics;
76
using System.Globalization;
87
using Microsoft.Build.Execution;
@@ -46,7 +45,6 @@ public void TaskNodesDieAfterBuild(bool taskHostFactorySpecified, bool envVariab
4645
{
4746
using (TestEnvironment env = TestEnvironment.Create())
4847
{
49-
using ProcessTracker processTracker = new();
5048
string taskFactory = taskHostFactorySpecified ? "TaskHostFactory" : "AssemblyTaskFactory";
5149
string pidTaskProject = $@"
5250
<Project>
@@ -64,9 +62,16 @@ public void TaskNodesDieAfterBuild(bool taskHostFactorySpecified, bool envVariab
6462
env.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", "1");
6563
}
6664

65+
// To execute the task in sidecar mode, both node reuse and the environment variable must be set.
66+
BuildParameters buildParameters = new() { EnableNodeReuse = envVariableSpecified && true /* node reuse enabled */ };
67+
6768
ProjectInstance projectInstance = new(project.Path);
6869

69-
projectInstance.Build().ShouldBeTrue();
70+
BuildManager buildManager = BuildManager.DefaultBuildManager;
71+
BuildResult buildResult = buildManager.Build(buildParameters, new BuildRequestData(projectInstance, targetsToBuild: ["AccessPID"]));
72+
73+
buildResult.OverallResult.ShouldBe(BuildResultCode.Success);
74+
7075
string processId = projectInstance.GetPropertyValue("PID");
7176
string.IsNullOrEmpty(processId).ShouldBeFalse();
7277
Int32.TryParse(processId, out int pid).ShouldBeTrue();
@@ -88,23 +93,18 @@ public void TaskNodesDieAfterBuild(bool taskHostFactorySpecified, bool envVariab
8893
}
8994
else
9095
{
96+
// This is the sidecar TaskHost case - it should persist after build is done. So we need to clean up and kill it ourselves.
97+
Process taskHostNode = Process.GetProcessById(pid);
98+
bool processExited = taskHostNode.WaitForExit(3000);
99+
100+
processExited.ShouldBeFalse();
91101
try
92102
{
93-
// This is the sidecar TaskHost case - it should persist after build is done. So we need to clean up and kill it ourselves.
94-
Process taskHostNode = Process.GetProcessById(pid);
95-
using var taskHostNodeTracker = processTracker.AttachToProcess(pid, "Sidecar", _output);
96-
bool processExited = taskHostNode.WaitForExit(3000);
97-
if (processExited)
98-
{
99-
processTracker.PrintSummary(_output);
100-
}
101-
102-
processExited.ShouldBeFalse();
103103
taskHostNode.Kill();
104104
}
105105
catch
106106
{
107-
processTracker.PrintSummary(_output);
107+
// Ignore exceptions from Kill - the process may have exited between the WaitForExit and Kill calls.
108108
}
109109
}
110110
}
@@ -119,9 +119,7 @@ public void TransientAndSidecarNodeCanCoexist()
119119
{
120120
using (TestEnvironment env = TestEnvironment.Create(_output))
121121
{
122-
using ProcessTracker processTracker = new();
123-
{
124-
string pidTaskProject = $@"
122+
string pidTaskProject = $@"
125123
<Project>
126124
<UsingTask TaskName=""ProcessIdTask"" AssemblyName=""Microsoft.Build.Engine.UnitTests"" TaskFactory=""TaskHostFactory"" />
127125
<UsingTask TaskName=""ProcessIdTaskSidecar"" AssemblyName=""Microsoft.Build.Engine.UnitTests"" TaskFactory=""AssemblyTaskFactory"" />
@@ -136,48 +134,44 @@ public void TransientAndSidecarNodeCanCoexist()
136134
</Target>
137135
</Project>";
138136

139-
TransientTestFile project = env.CreateFile("testProject.csproj", pidTaskProject);
140-
141-
env.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", "1");
142-
ProjectInstance projectInstance = new(project.Path);
137+
TransientTestFile project = env.CreateFile("testProject.csproj", pidTaskProject);
143138

144-
projectInstance.Build().ShouldBeTrue();
139+
env.SetEnvironmentVariable("MSBUILDFORCEALLTASKSOUTOFPROC", "1");
140+
ProjectInstance projectInstance = new(project.Path);
145141

146-
string transientPid = projectInstance.GetPropertyValue("PID");
147-
string sidecarPid = projectInstance.GetPropertyValue("PID2");
148-
sidecarPid.ShouldNotBe(transientPid, "Each task should have it's own TaskHost node.");
142+
projectInstance.Build().ShouldBeTrue();
149143

150-
using var sidecarTracker = processTracker.AttachToProcess(int.Parse(sidecarPid), "Sidecar", _output);
144+
string transientPid = projectInstance.GetPropertyValue("PID");
145+
string sidecarPid = projectInstance.GetPropertyValue("PID2");
146+
sidecarPid.ShouldNotBe(transientPid, "Each task should have it's own TaskHost node.");
151147

152-
string.IsNullOrEmpty(transientPid).ShouldBeFalse();
153-
Int32.TryParse(transientPid, out int pid).ShouldBeTrue();
154-
Int32.TryParse(sidecarPid, out int pidSidecar).ShouldBeTrue();
148+
string.IsNullOrEmpty(transientPid).ShouldBeFalse();
149+
Int32.TryParse(transientPid, out int pid).ShouldBeTrue();
150+
Int32.TryParse(sidecarPid, out int pidSidecar).ShouldBeTrue();
155151

156-
Process.GetCurrentProcess().Id.ShouldNotBe(pid);
152+
Process.GetCurrentProcess().Id.ShouldNotBe(pid);
157153

158-
try
159-
{
160-
Process transientTaskHostNode = Process.GetProcessById(pid);
161-
transientTaskHostNode.WaitForExit(3000).ShouldBeTrue("The node should be dead since this is the transient case.");
162-
}
163-
catch (ArgumentException e)
164-
{
165-
// We expect the TaskHostNode to exit quickly. If it exits before Process.GetProcessById, it will throw an ArgumentException.
166-
e.Message.ShouldBe($"Process with an Id of {pid} is not running.");
167-
}
154+
try
155+
{
156+
Process transientTaskHostNode = Process.GetProcessById(pid);
157+
transientTaskHostNode.WaitForExit(3000).ShouldBeTrue("The node should be dead since this is the transient case.");
158+
}
159+
catch (ArgumentException e)
160+
{
161+
// We expect the TaskHostNode to exit quickly. If it exits before Process.GetProcessById, it will throw an ArgumentException.
162+
e.Message.ShouldBe($"Process with an Id of {pid} is not running.");
163+
}
168164

169-
try
170-
{
171-
// This is the sidecar TaskHost case - it should persist after build is done. So we need to clean up and kill it ourselves.
172-
Process sidecarTaskHostNode = Process.GetProcessById(pidSidecar);
173-
sidecarTaskHostNode.WaitForExit(3000).ShouldBeFalse($"The node should be alive since it is the sidecar node.");
174-
sidecarTaskHostNode.Kill();
175-
}
176-
catch (Exception e)
177-
{
178-
processTracker.PrintSummary(_output);
179-
e.Message.ShouldNotBe($"Process with an Id of {pidSidecar} is not running");
180-
}
165+
try
166+
{
167+
// This is the sidecar TaskHost case - it should persist after build is done. So we need to clean up and kill it ourselves.
168+
Process sidecarTaskHostNode = Process.GetProcessById(pidSidecar);
169+
sidecarTaskHostNode.WaitForExit(3000).ShouldBeFalse($"The node should be alive since it is the sidecar node.");
170+
sidecarTaskHostNode.Kill();
171+
}
172+
catch (Exception e)
173+
{
174+
e.Message.ShouldNotBe($"Process with an Id of {pidSidecar} is not running");
181175
}
182176
}
183177
}
@@ -332,177 +326,5 @@ public void VariousParameterTypesCanBeTransmittedToAndReceivedFromTaskHost()
332326
projectInstance.GetPropertyValue("CustomStructOutput").ShouldBe(TaskBuilderTestTask.s_customStruct.ToString(CultureInfo.InvariantCulture));
333327
projectInstance.GetPropertyValue("EnumOutput").ShouldBe(TargetBuiltReason.BeforeTargets.ToString());
334328
}
335-
336-
/// <summary>
337-
/// Helper class for tracking external processes during tests.
338-
/// Monitors process lifecycle and provides diagnostic information for debugging.
339-
/// </summary>
340-
internal sealed class ProcessTracker : IDisposable
341-
{
342-
private readonly List<TrackedProcess> _trackedProcesses = new();
343-
344-
/// <summary>
345-
/// Attaches to an existing process for monitoring.
346-
/// </summary>
347-
/// <param name="pid">Process ID to attach to</param>
348-
/// <param name="name">Friendly name for the process</param>
349-
/// <param name="output">Test output helper for logging</param>
350-
/// <returns>TrackedProcess instance for the attached process</returns>
351-
public TrackedProcess AttachToProcess(int pid, string name, ITestOutputHelper output)
352-
{
353-
try
354-
{
355-
var process = Process.GetProcessById(pid);
356-
var tracked = new TrackedProcess(process, name);
357-
358-
// Enable event notifications
359-
process.EnableRaisingEvents = true;
360-
361-
// Subscribe to exit event
362-
process.Exited += (sender, e) =>
363-
{
364-
var proc = sender as Process;
365-
tracked.ExitTime = DateTime.Now;
366-
tracked.ExitCode = proc?.ExitCode ?? -999;
367-
tracked.HasExited = true;
368-
369-
output.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] {tracked.Name} (PID {tracked.ProcessId}) EXITED with code {tracked.ExitCode}");
370-
};
371-
372-
_trackedProcesses.Add(tracked);
373-
output.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] Attached to {name} (PID {pid})");
374-
375-
return tracked;
376-
}
377-
catch (ArgumentException)
378-
{
379-
output.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] Could not attach to {name} (PID {pid}) - process not found");
380-
return new TrackedProcess(null, name) { ProcessId = pid, NotFound = true };
381-
}
382-
}
383-
384-
/// <summary>
385-
/// Prints a summary of all tracked processes for diagnostic purposes.
386-
/// </summary>
387-
/// <param name="output">Test output helper for logging</param>
388-
public void PrintSummary(ITestOutputHelper output)
389-
{
390-
output.WriteLine("\n=== PROCESS TRACKING SUMMARY ===");
391-
foreach (var tracked in _trackedProcesses)
392-
{
393-
tracked.PrintStatus(output);
394-
}
395-
}
396-
397-
public void Dispose()
398-
{
399-
foreach (var tracked in _trackedProcesses)
400-
{
401-
tracked.Dispose();
402-
}
403-
}
404-
}
405-
406-
/// <summary>
407-
/// Represents a tracked process with lifecycle monitoring capabilities.
408-
/// </summary>
409-
internal sealed class TrackedProcess : IDisposable
410-
{
411-
/// <summary>
412-
/// The underlying Process object being tracked.
413-
/// </summary>
414-
public Process Process { get; }
415-
416-
/// <summary>
417-
/// Friendly name for the tracked process.
418-
/// </summary>
419-
public string Name { get; }
420-
421-
/// <summary>
422-
/// Process ID of the tracked process.
423-
/// </summary>
424-
public int ProcessId { get; set; }
425-
426-
/// <summary>
427-
/// Time when tracking began for this process.
428-
/// </summary>
429-
public DateTime AttachTime { get; }
430-
431-
/// <summary>
432-
/// Time when the process exited, if applicable.
433-
/// </summary>
434-
public DateTime? ExitTime { get; set; }
435-
436-
/// <summary>
437-
/// Exit code of the process, if it has exited.
438-
/// </summary>
439-
public int? ExitCode { get; set; }
440-
441-
/// <summary>
442-
/// Whether the process has exited.
443-
/// </summary>
444-
public bool HasExited { get; set; }
445-
446-
/// <summary>
447-
/// Whether the process was not found when attempting to attach.
448-
/// </summary>
449-
public bool NotFound { get; set; }
450-
451-
public TrackedProcess(Process process, string name)
452-
{
453-
Process = process;
454-
Name = name;
455-
ProcessId = process?.Id ?? -1;
456-
AttachTime = DateTime.Now;
457-
}
458-
459-
/// <summary>
460-
/// Prints detailed status information about the tracked process.
461-
/// </summary>
462-
/// <param name="output">Test output helper for logging</param>
463-
public void PrintStatus(ITestOutputHelper output)
464-
{
465-
output.WriteLine($"\n{Name} (PID {ProcessId}):");
466-
output.WriteLine($" Attached at: {AttachTime:HH:mm:ss.fff}");
467-
468-
if (NotFound)
469-
{
470-
output.WriteLine(" Status: Not found when trying to attach");
471-
}
472-
else if (HasExited)
473-
{
474-
var duration = (ExitTime.Value - AttachTime).TotalMilliseconds;
475-
output.WriteLine($" Status: Exited with code {ExitCode}");
476-
output.WriteLine($" Exit time: {ExitTime:HH:mm:ss.fff}");
477-
output.WriteLine($" Duration: {duration:F0}ms");
478-
}
479-
else
480-
{
481-
try
482-
{
483-
if (Process != null && !Process.HasExited)
484-
{
485-
output.WriteLine(" Status: Still running");
486-
output.WriteLine($" Start time: {Process.StartTime:HH:mm:ss.fff}");
487-
output.WriteLine($" CPU time: {Process.TotalProcessorTime.TotalMilliseconds:F0}ms");
488-
}
489-
else
490-
{
491-
output.WriteLine(" Status: Exited (detected during status check)");
492-
if (Process != null)
493-
{
494-
output.WriteLine($" Exit code: {Process.ExitCode}");
495-
}
496-
}
497-
}
498-
catch (Exception ex)
499-
{
500-
output.WriteLine($" Status: Error checking process - {ex.Message}");
501-
}
502-
}
503-
}
504-
505-
public void Dispose() => Process?.Dispose();
506-
}
507329
}
508330
}

0 commit comments

Comments
 (0)