[Harness] Use readers over paths. (#8534)

As issue https://github.com/xamarin/xamarin-macios/issues/8533 states,
not all loggers support the BullPath property, all of them do support
the GetReader one. We move the creation of the failures to use the
readers and reduce the chances of getting an exception.

fixes: https://github.com/xamarin/xamarin-macios/issues/8533
This commit is contained in:
Manuel de la Pena 2020-05-06 18:58:10 -04:00 коммит произвёл GitHub
Родитель b462447053
Коммит 531ba21a49
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 27 добавлений и 14 удалений

Просмотреть файл

@ -11,6 +11,8 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared {
// generates a xml result that will consider to be an error by the CI. Allows to catch errors in cases in which we are not talking about a test // generates a xml result that will consider to be an error by the CI. Allows to catch errors in cases in which we are not talking about a test
// failure perse but the situation in which the app could not be built, timeout or crashed. // failure perse but the situation in which the app could not be built, timeout or crashed.
void GenerateFailure (ILogs logs, string source, string appName, string variation, string title, string message, string stderrPath, XmlResultJargon jargon); void GenerateFailure (ILogs logs, string source, string appName, string variation, string title, string message, string stderrPath, XmlResultJargon jargon);
void GenerateFailure (ILogs logs, string source, string appName, string variation, string title, string message, StreamReader stderrReader, XmlResultJargon jargon);
// updates a given xml result to contain a list of attachments. This is useful for CI to be able to add logs as part of the attachments of a failing test. // updates a given xml result to contain a list of attachments. This is useful for CI to be able to add logs as part of the attachments of a failing test.
void UpdateMissingData (string source, string destination, string applicationName, IEnumerable<string> attachments); void UpdateMissingData (string source, string destination, string applicationName, IEnumerable<string> attachments);

Просмотреть файл

@ -391,6 +391,7 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared {
// generate all the xml failures that will help the integration with the CI and return the failure reason // generate all the xml failures that will help the integration with the CI and return the failure reason
async Task GenerateXmlFailures (string failureMessage, bool crashed, string crashReason) async Task GenerateXmlFailures (string failureMessage, bool crashed, string crashReason)
{ {
using var mainLogReader = mainLog.GetReader ();
if (!ResultsUseXml) // nothing to do if (!ResultsUseXml) // nothing to do
return; return;
if (!string.IsNullOrEmpty (crashReason)) { if (!string.IsNullOrEmpty (crashReason)) {
@ -401,7 +402,7 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared {
appInfo.Variation, appInfo.Variation,
$"App Crash {appInfo.AppName} {appInfo.Variation}", $"App Crash {appInfo.AppName} {appInfo.Variation}",
$"App crashed: {failureMessage}", $"App crashed: {failureMessage}",
mainLog.FullPath, mainLogReader,
xmlJargon); xmlJargon);
} else if (launchFailure) { } else if (launchFailure) {
resultParser.GenerateFailure ( resultParser.GenerateFailure (
@ -411,7 +412,7 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared {
appInfo.Variation, appInfo.Variation,
$"App Launch {appInfo.AppName} {appInfo.Variation} on {deviceName}", $"App Launch {appInfo.AppName} {appInfo.Variation} on {deviceName}",
$"{failureMessage} on {deviceName}", $"{failureMessage} on {deviceName}",
mainLog.FullPath, mainLogReader,
xmlJargon); xmlJargon);
} else if (!isSimulatorTest && crashed && string.IsNullOrEmpty (crashReason)) { } else if (!isSimulatorTest && crashed && string.IsNullOrEmpty (crashReason)) {
// this happens more that what we would like on devices, the main reason most of the time is that we have had netwoking problems and the // this happens more that what we would like on devices, the main reason most of the time is that we have had netwoking problems and the
@ -425,7 +426,7 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared {
appInfo.Variation, appInfo.Variation,
$"TcpConnection on {deviceName}", $"TcpConnection on {deviceName}",
$"Device {deviceName} could not reach the host over tcp.", $"Device {deviceName} could not reach the host over tcp.",
mainLog.FullPath, mainLogReader,
xmlJargon); xmlJargon);
} }
} else if (timedout) { } else if (timedout) {
@ -436,7 +437,7 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared {
appInfo.Variation, appInfo.Variation,
$"App Timeout {appInfo.AppName} {appInfo.Variation} on bot {deviceName}", $"App Timeout {appInfo.AppName} {appInfo.Variation} on bot {deviceName}",
$"{appInfo.AppName} {appInfo.Variation} Test run timed out after {timeout.TotalMinutes} minute(s) on bot {deviceName}.", $"{appInfo.AppName} {appInfo.Variation} Test run timed out after {timeout.TotalMinutes} minute(s) on bot {deviceName}.",
mainLog.FullPath, mainLogReader,
xmlJargon); xmlJargon);
} }
} }

Просмотреть файл

@ -1,3 +1,4 @@
#nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -611,7 +612,7 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared {
("skipped", "0"), ("skipped", "0"),
("asserts", "0")); ("asserts", "0"));
static void WriteFailure (XmlWriter writer, string message, StreamReader stderr = null) static void WriteFailure (XmlWriter writer, string message, StreamReader? stderr = null)
{ {
writer.WriteStartElement ("failure"); writer.WriteStartElement ("failure");
writer.WriteStartElement ("message"); writer.WriteStartElement ("message");
@ -714,11 +715,10 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared {
writer.WriteEndElement (); // assemblies writer.WriteEndElement (); // assemblies
} }
static void GenerateFailureXml (string destination, string title, string message, string stderrPath, XmlResultJargon jargon) static void GenerateFailureXml (string destination, string title, string message, StreamReader stderrReader, XmlResultJargon jargon)
{ {
XmlWriterSettings settings = new XmlWriterSettings { Indent = true }; XmlWriterSettings settings = new XmlWriterSettings { Indent = true };
using (var stream = File.CreateText (destination)) using (var stream = File.CreateText (destination))
using (var stderrReader = new StreamReader (stderrPath))
using (var xmlWriter = XmlWriter.Create (stream, settings)) { using (var xmlWriter = XmlWriter.Create (stream, settings)) {
xmlWriter.WriteStartDocument (); xmlWriter.WriteStartDocument ();
switch (jargon) { switch (jargon) {
@ -736,21 +736,27 @@ namespace Microsoft.DotNet.XHarness.iOS.Shared {
} }
} }
public void GenerateFailure (ILogs logs, string source, string appName, string variation, string title, string message, string stderrPath, XmlResultJargon jargon) public void GenerateFailure (ILogs logs, string source, string appName, string variation, string title,
string message, StreamReader stderr, XmlResultJargon jargon)
{ {
// VSTS does not provide a nice way to report build errors, create a fake // VSTS does not provide a nice way to report build errors, create a fake
// test result with a failure in the case the build did not work // test result with a failure in the case the build did not work
var failureLogXml = logs.Create ($"vsts-nunit-{source}-{Helpers.Timestamp}.xml", LogType.XmlLog.ToString ()); var failureLogXml = logs.Create ($"vsts-nunit-{source}-{Helpers.Timestamp}.xml", LogType.XmlLog.ToString ());
if (jargon == XmlResultJargon.NUnitV3) { if (jargon == XmlResultJargon.NUnitV3) {
var failureXmlTmp = logs.Create ($"nunit-{source}-{Helpers.Timestamp}.tmp", "Failure Log tmp"); var failureXmlTmp = logs.Create ($"nunit-{source}-{Helpers.Timestamp}.tmp", "Failure Log tmp");
GenerateFailureXml (failureXmlTmp.FullPath, title, message, stderrPath, jargon); GenerateFailureXml (failureXmlTmp.FullPath, title, message, stderr, jargon);
// add the required attachments and the info of the application that failed to install // add the required attachments and the info of the application that failed to install
var failure_logs = Directory.GetFiles (logs.Directory).Where (p => !p.Contains ("nunit")); // all logs but ourself var failure_logs = Directory.GetFiles (logs.Directory).Where (p => !p.Contains ("nunit")); // all logs but ourself
UpdateMissingData (failureXmlTmp.FullPath, failureLogXml.FullPath, $"{appName} {variation}", failure_logs); UpdateMissingData (failureXmlTmp.FullPath, failureLogXml.FullPath, $"{appName} {variation}", failure_logs);
} else { } else {
GenerateFailureXml (failureLogXml.FullPath, title, message, stderrPath, jargon); GenerateFailureXml (failureLogXml.FullPath, title, message, stderr, jargon);
} }
} }
public void GenerateFailure (ILogs logs, string source, string appName, string variation, string title, string message, string stderrPath, XmlResultJargon jargon)
{
using var stderrReader = new StreamReader (stderrPath);
GenerateFailure (logs, source, appName, variation, title, message, stderrReader, jargon);
}
public static string GetVSTSFilename (string filename) public static string GetVSTSFilename (string filename)
=> Path.Combine (Path.GetDirectoryName (filename), $"vsts-{Path.GetFileName (filename)}"); => Path.Combine (Path.GetDirectoryName (filename), $"vsts-{Path.GetFileName (filename)}");

Просмотреть файл

@ -130,6 +130,7 @@ namespace Xharness.TestTasks {
// Install the app // Install the app
InstallLog = new AppInstallMonitorLog (testTask.Logs.Create ($"install-{Helpers.Timestamp}.log", "Install log")); InstallLog = new AppInstallMonitorLog (testTask.Logs.Create ($"install-{Helpers.Timestamp}.log", "Install log"));
try { try {
using var logReader = InstallLog.GetReader ();
testTask.Runner.MainLog = this.InstallLog; testTask.Runner.MainLog = this.InstallLog;
var install_result = await testTask.Runner.InstallAsync (InstallLog.CancellationToken); var install_result = await testTask.Runner.InstallAsync (InstallLog.CancellationToken);
if (!install_result.Succeeded) { if (!install_result.Succeeded) {
@ -143,7 +144,8 @@ namespace Xharness.TestTasks {
testTask.Variation, testTask.Variation,
$"AppInstallation on {testTask.Device.Name}", $"AppInstallation on {testTask.Device.Name}",
$"Install failed on {testTask.Device.Name}, exit code: {install_result.ExitCode}", $"Install failed on {testTask.Device.Name}, exit code: {install_result.ExitCode}",
InstallLog.FullPath, xmlResultJargon); logReader,
xmlResultJargon);
} }
} finally { } finally {
InstallLog.Dispose (); InstallLog.Dispose ();

Просмотреть файл

@ -67,16 +67,18 @@ namespace Xharness.TestTasks {
testTask.FailureMessage = BuildTask.FailureMessage; testTask.FailureMessage = BuildTask.FailureMessage;
if (!string.IsNullOrEmpty (BuildTask.KnownFailure)) if (!string.IsNullOrEmpty (BuildTask.KnownFailure))
testTask.KnownFailure = BuildTask.KnownFailure; testTask.KnownFailure = BuildTask.KnownFailure;
if (generateXmlFailures) if (generateXmlFailures) {
var logReader = BuildTask.BuildLog.GetReader ();
ResultParser.GenerateFailure ( ResultParser.GenerateFailure (
logs: testTask.Logs, logs: testTask.Logs,
source: "build", source: "build",
appName: testTask.TestName, appName: testTask.TestName,
variation: testTask.Variation, variation: testTask.Variation,
title: $"App Build {testTask.TestName} {testTask.Variation}", title: $"App Build {testTask.TestName} {testTask.Variation}",
message: $"App could not be built {testTask.FailureMessage}.", message: $"App could not be built {testTask.FailureMessage}.",
stderrPath: BuildTask.BuildLog.FullPath, stderrReader: logReader,
jargon: xmlResultJargon); jargon: xmlResultJargon);
}
} else { } else {
testTask.ExecutionResult = TestExecutingResult.Built; testTask.ExecutionResult = TestExecutingResult.Built;
} }