Reduce flakiness in tests caused by the OS re-using the PID on test processes (#512)

We were using PID to assert that dotnet-watch had restarted processes. The OS does not guaranteed the uniqueness of PID, so I've changed tests to use PID + process start time to distinguish between processes.
This commit is contained in:
Nate McMaster 2018-11-06 09:57:17 -08:00 committed by GitHub
parent 9de04520e0
commit a24b4ee459
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 19 additions and 14 deletions

View File

@ -27,7 +27,7 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
public async Task RestartProcessOnFileChange() public async Task RestartProcessOnFileChange()
{ {
await _app.StartWatcherAsync(new[] { "--no-exit" }); await _app.StartWatcherAsync(new[] { "--no-exit" });
var pid = await _app.GetProcessId(); var processIdentifier = await _app.GetProcessIdentifier();
// Then wait for it to restart when we change a file // Then wait for it to restart when we change a file
var fileToChange = Path.Combine(_app.SourceDirectory, "Program.cs"); var fileToChange = Path.Combine(_app.SourceDirectory, "Program.cs");
@ -37,15 +37,15 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
await _app.HasRestarted(); await _app.HasRestarted();
Assert.DoesNotContain(_app.Process.Output, l => l.StartsWith("Exited with error code")); Assert.DoesNotContain(_app.Process.Output, l => l.StartsWith("Exited with error code"));
var pid2 = await _app.GetProcessId(); var processIdentifier2 = await _app.GetProcessIdentifier();
Assert.NotEqual(pid, pid2); Assert.NotEqual(processIdentifier, processIdentifier2);
} }
[Fact] [Fact]
public async Task RestartProcessThatTerminatesAfterFileChange() public async Task RestartProcessThatTerminatesAfterFileChange()
{ {
await _app.StartWatcherAsync(); await _app.StartWatcherAsync();
var pid = await _app.GetProcessId(); var processIdentifier = await _app.GetProcessIdentifier();
await _app.HasExited(); // process should exit after run await _app.HasExited(); // process should exit after run
await _app.IsWaitingForFileChange(); await _app.IsWaitingForFileChange();
@ -63,8 +63,8 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
await _app.HasRestarted(); await _app.HasRestarted();
} }
var pid2 = await _app.GetProcessId(); var processIdentifier2 = await _app.GetProcessIdentifier();
Assert.NotEqual(pid, pid2); Assert.NotEqual(processIdentifier, processIdentifier2);
await _app.HasExited(); // process should exit after run await _app.HasExited(); // process should exit after run
} }

View File

@ -57,11 +57,12 @@ namespace Microsoft.DotNet.Watcher.Tools.FunctionalTests
public bool UsePollingWatcher { get; set; } public bool UsePollingWatcher { get; set; }
public async Task<int> GetProcessId() public async Task<string> GetProcessIdentifier()
{ {
var line = await Process.GetOutputLineStartsWithAsync("PID =", DefaultMessageTimeOut); // Process ID is insufficient because PID's may be reused. Process identifier also includes other info to distinguish
var pid = line.Split('=').Last(); // between different process instances.
return int.Parse(pid); var line = await Process.GetOutputLineStartsWithAsync("Process identifier =", DefaultMessageTimeOut);
return line.Split('=').Last();
} }
public async Task PrepareAsync() public async Task PrepareAsync()

View File

@ -14,7 +14,8 @@ namespace ConsoleApplication
public static void Main(string[] args) public static void Main(string[] args)
{ {
Console.WriteLine("Started"); Console.WriteLine("Started");
Console.WriteLine($"PID = " + Process.GetCurrentProcess().Id); // Process ID is insufficient because PID's may be reused.
Console.WriteLine($"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}");
Thread.Sleep(Timeout.Infinite); Thread.Sleep(Timeout.Infinite);
} }
} }

View File

@ -14,7 +14,8 @@ namespace ConsoleApplication
public static void Main(string[] args) public static void Main(string[] args)
{ {
Console.WriteLine("Started"); Console.WriteLine("Started");
Console.WriteLine("PID = " + Process.GetCurrentProcess().Id); // Process ID is insufficient because PID's may be reused.
Console.WriteLine($"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}");
Console.WriteLine("Defined types = " + typeof(Program).GetTypeInfo().Assembly.DefinedTypes.Count()); Console.WriteLine("Defined types = " + typeof(Program).GetTypeInfo().Assembly.DefinedTypes.Count());
Thread.Sleep(Timeout.Infinite); Thread.Sleep(Timeout.Infinite);
} }

View File

@ -11,7 +11,8 @@ namespace KitchenSink
static void Main(string[] args) static void Main(string[] args)
{ {
Console.WriteLine("Started"); Console.WriteLine("Started");
Console.WriteLine("PID = " + Process.GetCurrentProcess().Id); // Process ID is insufficient because PID's may be reused.
Console.WriteLine($"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}");
Console.WriteLine("DOTNET_WATCH = " + Environment.GetEnvironmentVariable("DOTNET_WATCH")); Console.WriteLine("DOTNET_WATCH = " + Environment.GetEnvironmentVariable("DOTNET_WATCH"));
Console.WriteLine("DOTNET_WATCH_ITERATION = " + Environment.GetEnvironmentVariable("DOTNET_WATCH_ITERATION")); Console.WriteLine("DOTNET_WATCH_ITERATION = " + Environment.GetEnvironmentVariable("DOTNET_WATCH_ITERATION"));
} }

View File

@ -12,7 +12,8 @@ namespace ConsoleApplication
public static void Main(string[] args) public static void Main(string[] args)
{ {
Console.WriteLine("Started"); Console.WriteLine("Started");
Console.WriteLine($"PID = " + Process.GetCurrentProcess().Id); // Process ID is insufficient because PID's may be reused.
Console.WriteLine($"Process identifier = {Process.GetCurrentProcess().Id}, {Process.GetCurrentProcess().StartTime:hh:mm:ss.FF}");
if (args.Length > 0 && args[0] == "--no-exit") if (args.Length > 0 && args[0] == "--no-exit")
{ {
Thread.Sleep(Timeout.Infinite); Thread.Sleep(Timeout.Infinite);