private void AssertFileExists(string path) { TestRetryException.Assert( File.Exists(path), "File {0} did not exist. Directory contents: {1}{2}", path, Environment.NewLine, string.Join(Environment.NewLine, Directory.EnumerateFiles(Path.GetDirectoryName(path)))); }
public void DumpProcessTreeTest() { // This test has proven to occasionally be flakey, primarily by failing to create some of the dump files. // We add retries to prevent it from failing our automation. int MaxTries = 4; for (int i = 1; i <= MaxTries; i++) { try { string dumpPath = Path.Combine(TemporaryDirectory, "dumps" + i); Directory.CreateDirectory(dumpPath); var cmd = CmdHelper.CmdX64; Process p = null; bool success; Exception failure; try { p = Process.Start(new ProcessStartInfo(cmd, string.Format(@" /K {0} /K {0} /K ping localhost -t", cmd)) { CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, RedirectStandardOutput = true, UseShellExecute = false, }); // Make sure ping is actually running before dumping. Otherwise the process tree might not be fully created. bool found = false; Stopwatch sw = Stopwatch.StartNew(); StringBuilder output = new StringBuilder(); while (sw.Elapsed.TotalSeconds < 30) { string line = p.StandardOutput.ReadLine(); output.AppendLine(line); if (line.Contains("Pinging")) { found = true; break; } } if (!found) { TestRetryException.Assert(false, "Didn't find result of ping in standard out. Full output:" + Environment.NewLine + output.ToString() + Environment.NewLine + p.StandardError.ReadToEnd()); } var processIds = ProcessDumper.GetProcessTreeIds(p.Id, 0); XAssert.IsTrue(processIds.Count == 1, processIds.Count.ToString()); success = ProcessDumper.TryDumpProcessAndChildren(p.Id, dumpPath, out failure); } finally { Stopwatch killTimer = Stopwatch.StartNew(); if (p != null) { while (killTimer.Elapsed.TotalSeconds < 10) { // Make sure we kill all of the child processes before exiting the test var kill = Process.Start(new ProcessStartInfo("taskkill", "/pid " + p.Id + " /T /F") { CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, }); kill.WaitForExit(); if (p.HasExited) { break; } else { Thread.Sleep(200); } } } } // Make sure all of the dumps exist TestRetryException.Assert(success, "Dumping processes failed: " + (failure == null ? "Failure was null" : failure.ToString())); AssertFileExists(Path.Combine(dumpPath, "1_cmd.exe.dmp")); #if !FEATURE_CORECLR // ConHost is not launched with the CoreCLR through the xUnit runner AssertFileExists(Path.Combine(dumpPath, "1_2_cmd.exe.dmp")); AssertFileExists(Path.Combine(dumpPath, "1_2_1_cmd.exe.dmp")); AssertFileExists(Path.Combine(dumpPath, "1_2_1_1_PING.EXE.dmp")); #endif } catch (TestRetryException ex) { if (i >= MaxTries) { TestRetryException.Assert(false, "Test failed after exhausting retries. Retry number {0}. Failure: {1}", i, ex); } m_testOutputHelper.WriteLine("Test iteration failed. Pausing and retrying"); // Take a break before retrying the test Thread.Sleep(3000); continue; } // Success break; } }