diff --git a/tests/xharness/AppRunner.cs b/tests/xharness/AppRunner.cs index a99cd6bf97..407c1507d1 100644 --- a/tests/xharness/AppRunner.cs +++ b/tests/xharness/AppRunner.cs @@ -39,6 +39,7 @@ namespace xharness public string AppPath; public TestExecutingResult Result { get; private set; } + public string FailureMessage { get; private set; } string appName; string appPath; @@ -735,6 +736,59 @@ namespace xharness } else { Result = TestExecutingResult.Failed; } + + // Check crash reports to see if any of them explains why the test run crashed. + if (!success.Value) { + int pid = 0; + string crash_reason = null; + foreach (var crash in crash_reports.Logs) { + try { + if (pid == 0) { + // Find the pid + using (var log_reader = main_log.GetReader ()) { + string line; + while ((line = log_reader.ReadLine ()) != null) { + const string str = "was launched with pid '"; + var idx = line.IndexOf (str, StringComparison.Ordinal); + if (idx > 0) { + idx += str.Length; + var next_idx = line.IndexOf ('\'', idx); + if (next_idx > idx) + int.TryParse (line.Substring (idx, next_idx - idx), out pid); + } + if (pid != 0) + break; + } + } + } + + using (var crash_reader = crash.GetReader ()) { + var text = crash_reader.ReadToEnd (); + + var reader = System.Runtime.Serialization.Json.JsonReaderWriterFactory.CreateJsonReader (Encoding.UTF8.GetBytes (text), new XmlDictionaryReaderQuotas ()); + var doc = new XmlDocument (); + doc.Load (reader); + foreach (XmlNode node in doc.SelectNodes ($"/root/processes/item[pid = '" + pid + "']")) { + Console.WriteLine (node?.InnerXml); + Console.WriteLine (node?.SelectSingleNode ("reason")?.InnerText); + crash_reason = node?.SelectSingleNode ("reason")?.InnerText; + } + } + if (crash_reason != null) + break; + } catch (Exception e) { + Console.WriteLine ("Failed to process crash report {1}: {0}", e.Message, crash.Description); + } + } + if (!string.IsNullOrEmpty (crash_reason)) { + if (crash_reason == "per-process-limit") { + FailureMessage = "Killed due to using too much memory (per-process-limit)."; + } else { + FailureMessage = $"Killed by the OS ({crash_reason})"; + } + } + } + return success.Value ? 0 : 1; } diff --git a/tests/xharness/Jenkins.cs b/tests/xharness/Jenkins.cs index e6eb04ae96..ce941762d6 100644 --- a/tests/xharness/Jenkins.cs +++ b/tests/xharness/Jenkins.cs @@ -2503,6 +2503,9 @@ function oninitialload () runner.MainLog = Logs.CreateStream (LogDirectory, $"run-{Device.UDID}-{Timestamp}.log", "Run log"); await runner.RunAsync (); + if (!string.IsNullOrEmpty (runner.FailureMessage)) + FailureMessage = runner.FailureMessage; + if (runner.Result == TestExecutingResult.Succeeded && Platform == TestPlatform.iOS_TodayExtension64) { // For the today extension, the main app is just a single test. // This is because running the today extension will not wake up the device, @@ -2523,6 +2526,9 @@ function oninitialload () additional_runner = todayRunner; await todayRunner.RunAsync (); ExecutionResult = todayRunner.Result; + + if (!string.IsNullOrEmpty (todayRunner.FailureMessage)) + FailureMessage = todayRunner.FailureMessage; } else { ExecutionResult = runner.Result; }