[Harness] Remove Harness as a dependency (#8203)
This commit is contained in:
Родитель
dddcba9dc4
Коммит
6209719f51
|
@ -188,10 +188,6 @@ namespace Xharness {
|
||||||
|
|
||||||
var args = new MlaunchArguments ();
|
var args = new MlaunchArguments ();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty (harness.XcodeRoot)) {
|
|
||||||
args.Add (new SdkRootArgument (harness.XcodeRoot));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = -1; i < harness.Verbosity; i++)
|
for (int i = -1; i < harness.Verbosity; i++)
|
||||||
args.Add (new VerbosityArgument ());
|
args.Add (new VerbosityArgument ());
|
||||||
|
|
||||||
|
@ -205,7 +201,7 @@ namespace Xharness {
|
||||||
var totalSize = Directory.GetFiles (AppInformation.AppPath, "*", SearchOption.AllDirectories).Select ((v) => new FileInfo (v).Length).Sum ();
|
var totalSize = Directory.GetFiles (AppInformation.AppPath, "*", SearchOption.AllDirectories).Select ((v) => new FileInfo (v).Length).Sum ();
|
||||||
MainLog.WriteLine ($"Installing '{AppInformation.AppPath}' to '{companionDeviceName ?? deviceName}'. Size: {totalSize} bytes = {totalSize / 1024.0 / 1024.0:N2} MB");
|
MainLog.WriteLine ($"Installing '{AppInformation.AppPath}' to '{companionDeviceName ?? deviceName}'. Size: {totalSize} bytes = {totalSize / 1024.0 / 1024.0:N2} MB");
|
||||||
|
|
||||||
return await ProcessManager.ExecuteCommandAsync (harness.MlaunchPath, args, MainLog, TimeSpan.FromHours (1), cancellation_token: cancellation_token);
|
return await ProcessManager.ExecuteCommandAsync (args, MainLog, TimeSpan.FromHours (1), cancellation_token: cancellation_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ProcessExecutionResult> UninstallAsync ()
|
public async Task<ProcessExecutionResult> UninstallAsync ()
|
||||||
|
@ -217,17 +213,13 @@ namespace Xharness {
|
||||||
|
|
||||||
var args = new MlaunchArguments ();
|
var args = new MlaunchArguments ();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty (harness.XcodeRoot)) {
|
|
||||||
args.Add (new SdkRootArgument (harness.XcodeRoot));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = -1; i < harness.Verbosity; i++)
|
for (int i = -1; i < harness.Verbosity; i++)
|
||||||
args.Add (new VerbosityArgument ());
|
args.Add (new VerbosityArgument ());
|
||||||
|
|
||||||
args.Add (new UninstallAppFromDeviceArgument (AppInformation.BundleIdentifier));
|
args.Add (new UninstallAppFromDeviceArgument (AppInformation.BundleIdentifier));
|
||||||
args.Add (new DeviceNameArgument (companionDeviceName ?? deviceName));
|
args.Add (new DeviceNameArgument (companionDeviceName ?? deviceName));
|
||||||
|
|
||||||
return await ProcessManager.ExecuteCommandAsync (harness.MlaunchPath, args, MainLog, TimeSpan.FromMinutes (1));
|
return await ProcessManager.ExecuteCommandAsync (args, MainLog, TimeSpan.FromMinutes (1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSpan GetNewTimeout () => TimeSpan.FromMinutes (harness.Timeout * timeoutMultiplier);
|
public TimeSpan GetNewTimeout () => TimeSpan.FromMinutes (harness.Timeout * timeoutMultiplier);
|
||||||
|
@ -241,10 +233,6 @@ namespace Xharness {
|
||||||
|
|
||||||
var args = new MlaunchArguments ();
|
var args = new MlaunchArguments ();
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty (harness.XcodeRoot)) {
|
|
||||||
args.Add (new SdkRootArgument (harness.XcodeRoot));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = -1; i < harness.Verbosity; i++)
|
for (int i = -1; i < harness.Verbosity; i++)
|
||||||
args.Add (new VerbosityArgument ());
|
args.Add (new VerbosityArgument ());
|
||||||
|
|
||||||
|
@ -387,7 +375,7 @@ namespace Xharness {
|
||||||
MainLog.WriteLine ("Starting test run");
|
MainLog.WriteLine ("Starting test run");
|
||||||
|
|
||||||
await testReporter.CollectSimulatorResult (
|
await testReporter.CollectSimulatorResult (
|
||||||
ProcessManager.ExecuteCommandAsync (harness.MlaunchPath, args, run_log, testReporter.Timeout, cancellation_token: testReporter.CancellationToken));
|
ProcessManager.ExecuteCommandAsync (args, run_log, testReporter.Timeout, cancellation_token: testReporter.CancellationToken));
|
||||||
|
|
||||||
// cleanup after us
|
// cleanup after us
|
||||||
if (EnsureCleanSimulatorState)
|
if (EnsureCleanSimulatorState)
|
||||||
|
@ -419,7 +407,7 @@ namespace Xharness {
|
||||||
// We need to check for MT1111 (which means that mlaunch won't wait for the app to exit).
|
// We need to check for MT1111 (which means that mlaunch won't wait for the app to exit).
|
||||||
var runLog = Log.CreateAggregatedLog (testReporter.CallbackLog, MainLog);
|
var runLog = Log.CreateAggregatedLog (testReporter.CallbackLog, MainLog);
|
||||||
testReporter.TimeoutWatch.Start ();
|
testReporter.TimeoutWatch.Start ();
|
||||||
await testReporter.CollectDeviceResult (ProcessManager.ExecuteCommandAsync (harness.MlaunchPath, args, runLog, testReporter.Timeout, cancellation_token: testReporter.CancellationToken));
|
await testReporter.CollectDeviceResult (ProcessManager.ExecuteCommandAsync (args, runLog, testReporter.Timeout, cancellation_token: testReporter.CancellationToken));
|
||||||
} finally {
|
} finally {
|
||||||
deviceLogCapturer.StopCapture ();
|
deviceLogCapturer.StopCapture ();
|
||||||
deviceSystemLog.Dispose ();
|
deviceSystemLog.Dispose ();
|
||||||
|
|
|
@ -5,6 +5,5 @@ using Xharness.Logging;
|
||||||
namespace Xharness.Collections{
|
namespace Xharness.Collections{
|
||||||
public interface ILoadAsync {
|
public interface ILoadAsync {
|
||||||
Task LoadAsync (ILog log, bool include_locked, bool force);
|
Task LoadAsync (ILog log, bool include_locked, bool force);
|
||||||
IHarness Harness { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,18 +17,14 @@ namespace Xharness
|
||||||
|
|
||||||
public class CrashSnapshotReporterFactory : ICrashSnapshotReporterFactory {
|
public class CrashSnapshotReporterFactory : ICrashSnapshotReporterFactory {
|
||||||
readonly IProcessManager processManager;
|
readonly IProcessManager processManager;
|
||||||
readonly string xcodeRoot;
|
|
||||||
readonly string mlaunchPath;
|
|
||||||
|
|
||||||
public CrashSnapshotReporterFactory (IProcessManager processManager, string xcodeRoot, string mlaunchPath)
|
public CrashSnapshotReporterFactory (IProcessManager processManager)
|
||||||
{
|
{
|
||||||
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
||||||
this.xcodeRoot = xcodeRoot ?? throw new ArgumentNullException (nameof (xcodeRoot));
|
|
||||||
this.mlaunchPath = mlaunchPath ?? throw new ArgumentNullException (nameof (mlaunchPath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICrashSnapshotReporter Create (ILog log, ILogs logs, bool isDevice, string deviceName) =>
|
public ICrashSnapshotReporter Create (ILog log, ILogs logs, bool isDevice, string deviceName) =>
|
||||||
new CrashSnapshotReporter (processManager, log, logs, xcodeRoot, mlaunchPath, isDevice, deviceName);
|
new CrashSnapshotReporter (processManager, log, logs, isDevice, deviceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ICrashSnapshotReporter {
|
public interface ICrashSnapshotReporter {
|
||||||
|
@ -40,8 +36,6 @@ namespace Xharness
|
||||||
readonly IProcessManager processManager;
|
readonly IProcessManager processManager;
|
||||||
readonly ILog log;
|
readonly ILog log;
|
||||||
readonly ILogs logs;
|
readonly ILogs logs;
|
||||||
readonly string xcodeRoot;
|
|
||||||
readonly string mlaunchPath;
|
|
||||||
readonly bool isDevice;
|
readonly bool isDevice;
|
||||||
readonly string deviceName;
|
readonly string deviceName;
|
||||||
readonly Func<string> tempFileProvider;
|
readonly Func<string> tempFileProvider;
|
||||||
|
@ -52,8 +46,6 @@ namespace Xharness
|
||||||
public CrashSnapshotReporter (IProcessManager processManager,
|
public CrashSnapshotReporter (IProcessManager processManager,
|
||||||
ILog log,
|
ILog log,
|
||||||
ILogs logs,
|
ILogs logs,
|
||||||
string xcodeRoot,
|
|
||||||
string mlaunchPath,
|
|
||||||
bool isDevice,
|
bool isDevice,
|
||||||
string deviceName,
|
string deviceName,
|
||||||
Func<string> tempFileProvider = null)
|
Func<string> tempFileProvider = null)
|
||||||
|
@ -61,15 +53,13 @@ namespace Xharness
|
||||||
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
||||||
this.log = log ?? throw new ArgumentNullException (nameof (log));
|
this.log = log ?? throw new ArgumentNullException (nameof (log));
|
||||||
this.logs = logs ?? throw new ArgumentNullException (nameof (logs));
|
this.logs = logs ?? throw new ArgumentNullException (nameof (logs));
|
||||||
this.xcodeRoot = xcodeRoot ?? throw new ArgumentNullException (nameof (xcodeRoot));
|
|
||||||
this.mlaunchPath = mlaunchPath ?? throw new ArgumentNullException (nameof (mlaunchPath));
|
|
||||||
this.isDevice = isDevice;
|
this.isDevice = isDevice;
|
||||||
this.deviceName = deviceName;
|
this.deviceName = deviceName;
|
||||||
this.tempFileProvider = tempFileProvider ?? Path.GetTempFileName;
|
this.tempFileProvider = tempFileProvider ?? Path.GetTempFileName;
|
||||||
|
|
||||||
symbolicateCrashPath = Path.Combine (xcodeRoot, "Contents", "SharedFrameworks", "DTDeviceKitBase.framework", "Versions", "A", "Resources", "symbolicatecrash");
|
symbolicateCrashPath = Path.Combine (processManager.XcodeRoot, "Contents", "SharedFrameworks", "DTDeviceKitBase.framework", "Versions", "A", "Resources", "symbolicatecrash");
|
||||||
if (!File.Exists (symbolicateCrashPath))
|
if (!File.Exists (symbolicateCrashPath))
|
||||||
symbolicateCrashPath = Path.Combine (xcodeRoot, "Contents", "SharedFrameworks", "DVTFoundation.framework", "Versions", "A", "Resources", "symbolicatecrash");
|
symbolicateCrashPath = Path.Combine (processManager.XcodeRoot, "Contents", "SharedFrameworks", "DVTFoundation.framework", "Versions", "A", "Resources", "symbolicatecrash");
|
||||||
if (!File.Exists (symbolicateCrashPath))
|
if (!File.Exists (symbolicateCrashPath))
|
||||||
symbolicateCrashPath = null;
|
symbolicateCrashPath = null;
|
||||||
}
|
}
|
||||||
|
@ -135,14 +125,13 @@ namespace Xharness
|
||||||
var crashReportFile = logs.Create (name, $"Crash report: {name}", timestamp: false);
|
var crashReportFile = logs.Create (name, $"Crash report: {name}", timestamp: false);
|
||||||
var args = new MlaunchArguments (
|
var args = new MlaunchArguments (
|
||||||
new DownloadCrashReportArgument (crashFile),
|
new DownloadCrashReportArgument (crashFile),
|
||||||
new DownloadCrashReportToArgument (crashReportFile.FullPath),
|
new DownloadCrashReportToArgument (crashReportFile.FullPath));
|
||||||
new SdkRootArgument (xcodeRoot));
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty (deviceName)) {
|
if (!string.IsNullOrEmpty (deviceName)) {
|
||||||
args.Add (new DeviceNameArgument(deviceName));
|
args.Add (new DeviceNameArgument(deviceName));
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await processManager.ExecuteCommandAsync (mlaunchPath, args, log, TimeSpan.FromMinutes (1));
|
var result = await processManager.ExecuteCommandAsync (args, log, TimeSpan.FromMinutes (1));
|
||||||
|
|
||||||
if (result.Succeeded) {
|
if (result.Succeeded) {
|
||||||
log.WriteLine ("Downloaded crash report {0} to {1}", crashFile, crashReportFile.FullPath);
|
log.WriteLine ("Downloaded crash report {0} to {1}", crashFile, crashReportFile.FullPath);
|
||||||
|
@ -162,7 +151,7 @@ namespace Xharness
|
||||||
|
|
||||||
var name = Path.GetFileName (report.FullPath);
|
var name = Path.GetFileName (report.FullPath);
|
||||||
var symbolicated = logs.Create (Path.ChangeExtension (name, ".symbolicated.log"), $"Symbolicated crash report: {name}", timestamp: false);
|
var symbolicated = logs.Create (Path.ChangeExtension (name, ".symbolicated.log"), $"Symbolicated crash report: {name}", timestamp: false);
|
||||||
var environment = new Dictionary<string, string> { { "DEVELOPER_DIR", Path.Combine (xcodeRoot, "Contents", "Developer") } };
|
var environment = new Dictionary<string, string> { { "DEVELOPER_DIR", Path.Combine (processManager.XcodeRoot, "Contents", "Developer") } };
|
||||||
var result = await processManager.ExecuteCommandAsync (symbolicateCrashPath, new [] { report.FullPath }, symbolicated, TimeSpan.FromMinutes (1), environment);
|
var result = await processManager.ExecuteCommandAsync (symbolicateCrashPath, new [] { report.FullPath }, symbolicated, TimeSpan.FromMinutes (1), environment);
|
||||||
if (result.Succeeded) {
|
if (result.Succeeded) {
|
||||||
log.WriteLine ("Symbolicated {0} successfully.", report.FullPath);
|
log.WriteLine ("Symbolicated {0} successfully.", report.FullPath);
|
||||||
|
@ -184,15 +173,13 @@ namespace Xharness
|
||||||
} else {
|
} else {
|
||||||
var tempFile = tempFileProvider ();
|
var tempFile = tempFileProvider ();
|
||||||
try {
|
try {
|
||||||
var args = new MlaunchArguments (
|
var args = new MlaunchArguments (new ListCrashReportsArgument (tempFile));
|
||||||
new ListCrashReportsArgument (tempFile),
|
|
||||||
new SdkRootArgument (xcodeRoot));
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty (deviceName)) {
|
if (!string.IsNullOrEmpty (deviceName)) {
|
||||||
args.Add (new DeviceNameArgument(deviceName));
|
args.Add (new DeviceNameArgument(deviceName));
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = await processManager.ExecuteCommandAsync (mlaunchPath, args, log, TimeSpan.FromMinutes (1));
|
var result = await processManager.ExecuteCommandAsync (args, log, TimeSpan.FromMinutes (1));
|
||||||
if (result.Succeeded)
|
if (result.Succeeded)
|
||||||
crashes.UnionWith (File.ReadAllLines (tempFile));
|
crashes.UnionWith (File.ReadAllLines (tempFile));
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -14,19 +14,15 @@ namespace Xharness
|
||||||
|
|
||||||
public class DeviceLogCapturerFactory : IDeviceLogCapturerFactory {
|
public class DeviceLogCapturerFactory : IDeviceLogCapturerFactory {
|
||||||
readonly IProcessManager processManager;
|
readonly IProcessManager processManager;
|
||||||
readonly string xcodeRoot;
|
|
||||||
readonly string mlaunchPath;
|
|
||||||
|
|
||||||
public DeviceLogCapturerFactory (IProcessManager processManager, string xcodeRoot, string mlaunchPath)
|
public DeviceLogCapturerFactory (IProcessManager processManager)
|
||||||
{
|
{
|
||||||
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
||||||
this.xcodeRoot = xcodeRoot ?? throw new ArgumentNullException (nameof (xcodeRoot));
|
|
||||||
this.mlaunchPath = mlaunchPath ?? throw new ArgumentNullException (nameof (mlaunchPath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDeviceLogCapturer Create (ILog mainLog, ILog deviceLog, string deviceName)
|
public IDeviceLogCapturer Create (ILog mainLog, ILog deviceLog, string deviceName)
|
||||||
{
|
{
|
||||||
return new DeviceLogCapturer (processManager, mainLog, deviceLog, deviceName, xcodeRoot, mlaunchPath);
|
return new DeviceLogCapturer (processManager, mainLog, deviceLog, deviceName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,17 +36,13 @@ namespace Xharness
|
||||||
readonly ILog mainLog;
|
readonly ILog mainLog;
|
||||||
readonly ILog deviceLog;
|
readonly ILog deviceLog;
|
||||||
readonly string deviceName;
|
readonly string deviceName;
|
||||||
readonly string xcodeRoot;
|
|
||||||
readonly string mlaunchPath;
|
|
||||||
|
|
||||||
public DeviceLogCapturer (IProcessManager processManager, ILog mainLog, ILog deviceLog, string deviceName, string xcodeRoot, string mlaunchPath)
|
public DeviceLogCapturer (IProcessManager processManager, ILog mainLog, ILog deviceLog, string deviceName)
|
||||||
{
|
{
|
||||||
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
||||||
this.mainLog = mainLog ?? throw new ArgumentNullException (nameof (mainLog));
|
this.mainLog = mainLog ?? throw new ArgumentNullException (nameof (mainLog));
|
||||||
this.deviceLog = deviceLog ?? throw new ArgumentNullException (nameof (deviceLog));
|
this.deviceLog = deviceLog ?? throw new ArgumentNullException (nameof (deviceLog));
|
||||||
this.deviceName = deviceName ?? throw new ArgumentNullException (nameof (deviceName));
|
this.deviceName = deviceName ?? throw new ArgumentNullException (nameof (deviceName));
|
||||||
this.xcodeRoot = xcodeRoot ?? throw new ArgumentNullException (nameof (xcodeRoot));
|
|
||||||
this.mlaunchPath = mlaunchPath ?? throw new ArgumentNullException (nameof (mlaunchPath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Process process;
|
Process process;
|
||||||
|
@ -60,17 +52,17 @@ namespace Xharness
|
||||||
{
|
{
|
||||||
streamEnds = new CountdownEvent (2);
|
streamEnds = new CountdownEvent (2);
|
||||||
|
|
||||||
var sb = new List<string> {
|
var args = new List<string> {
|
||||||
"--logdev",
|
"--logdev",
|
||||||
"--sdkroot",
|
"--sdkroot",
|
||||||
xcodeRoot,
|
processManager.XcodeRoot,
|
||||||
"--devname",
|
"--devname",
|
||||||
deviceName
|
deviceName
|
||||||
};
|
};
|
||||||
|
|
||||||
process = new Process ();
|
process = new Process ();
|
||||||
process.StartInfo.FileName = mlaunchPath;
|
process.StartInfo.FileName = processManager.MlaunchPath;
|
||||||
process.StartInfo.Arguments = StringUtils.FormatArguments (sb);
|
process.StartInfo.Arguments = StringUtils.FormatArguments (args);
|
||||||
process.StartInfo.UseShellExecute = false;
|
process.StartInfo.UseShellExecute = false;
|
||||||
process.StartInfo.RedirectStandardOutput = true;
|
process.StartInfo.RedirectStandardOutput = true;
|
||||||
process.StartInfo.RedirectStandardError = true;
|
process.StartInfo.RedirectStandardError = true;
|
||||||
|
|
|
@ -17,15 +17,17 @@ namespace Xharness.Execution {
|
||||||
|
|
||||||
// interface that helps to manage the different processes in the app.
|
// interface that helps to manage the different processes in the app.
|
||||||
public interface IProcessManager {
|
public interface IProcessManager {
|
||||||
|
string XcodeRoot { get; }
|
||||||
|
string MlaunchPath { get; }
|
||||||
|
Version XcodeVersion { get; }
|
||||||
|
|
||||||
Task<ProcessExecutionResult> ExecuteCommandAsync (string filename, IList<string> args, ILog log, TimeSpan timeout, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null);
|
Task<ProcessExecutionResult> ExecuteCommandAsync (string filename, IList<string> args, ILog log, TimeSpan timeout, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null);
|
||||||
Task<ProcessExecutionResult> ExecuteCommandAsync (string filename, MlaunchArguments args, ILog log, TimeSpan timeout, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null);
|
Task<ProcessExecutionResult> ExecuteCommandAsync (MlaunchArguments args, ILog log, TimeSpan timeout, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null);
|
||||||
Task<ProcessExecutionResult> RunAsync (Process process, ILog log, CancellationToken? cancellationToken = null, bool? diagnostics = null);
|
Task<ProcessExecutionResult> ExecuteXcodeCommandAsync (string executable, IList<string> args, ILog log, TimeSpan timeout);
|
||||||
Task<ProcessExecutionResult> RunAsync (Process process, ILog log, TimeSpan? timeout = null, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null, bool? diagnostics = null);
|
Task<ProcessExecutionResult> RunAsync (Process process, ILog log, TimeSpan? timeout = null, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null, bool? diagnostics = null);
|
||||||
Task<ProcessExecutionResult> RunAsync (Process process, MlaunchArguments args, ILog log, TimeSpan? timeout = null, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null, bool? diagnostics = null);
|
Task<ProcessExecutionResult> RunAsync (Process process, MlaunchArguments args, ILog log, TimeSpan? timeout = null, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null, bool? diagnostics = null);
|
||||||
Task<ProcessExecutionResult> RunAsync (Process process, ILog log, ILog stdoutLog, ILog stderrLog, TimeSpan? timeout = null, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null, bool? diagnostics = null);
|
Task<ProcessExecutionResult> RunAsync (Process process, ILog log, ILog stdoutLog, ILog stderrLog, TimeSpan? timeout = null, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null, bool? diagnostics = null);
|
||||||
Task<bool> WaitForExitAsync (Process process, TimeSpan? timeout = null);
|
|
||||||
Task KillTreeAsync (Process process, ILog log, bool? diagnostics = true);
|
Task KillTreeAsync (Process process, ILog log, bool? diagnostics = true);
|
||||||
Task KillTreeAsync (int pid, ILog log, bool? diagnostics = true);
|
Task KillTreeAsync (int pid, ILog log, bool? diagnostics = true);
|
||||||
void GetChildrenPS (ILog log, List<int> list, int pid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,84 +7,101 @@ using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
using Xharness.Execution.Mlaunch;
|
using Xharness.Execution.Mlaunch;
|
||||||
using Xharness.Logging;
|
using Xharness.Logging;
|
||||||
using Xharness.Utilities;
|
using Xharness.Utilities;
|
||||||
|
|
||||||
namespace Xharness.Execution {
|
namespace Xharness.Execution {
|
||||||
public class ProcessManager : IProcessManager {
|
public class ProcessManager : IProcessManager {
|
||||||
public ProcessManager ()
|
public string XcodeRoot { get; }
|
||||||
|
public string MlaunchPath { get; }
|
||||||
|
|
||||||
|
Version xcode_version;
|
||||||
|
public Version XcodeVersion {
|
||||||
|
get {
|
||||||
|
if (xcode_version == null) {
|
||||||
|
var doc = new XmlDocument ();
|
||||||
|
doc.Load (Path.Combine (XcodeRoot, "Contents", "version.plist"));
|
||||||
|
xcode_version = Version.Parse (doc.SelectSingleNode ("//key[text() = 'CFBundleShortVersionString']/following-sibling::string").InnerText);
|
||||||
|
}
|
||||||
|
return xcode_version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProcessManager (string xcodeRoot, string mlaunchPath)
|
||||||
{
|
{
|
||||||
|
XcodeRoot = xcodeRoot ?? throw new ArgumentNullException (nameof (xcodeRoot));
|
||||||
|
MlaunchPath = mlaunchPath ?? throw new ArgumentNullException (nameof (mlaunchPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ProcessExecutionResult> ExecuteCommandAsync (string filename,
|
public async Task<ProcessExecutionResult> ExecuteCommandAsync (string filename,
|
||||||
IList<string> args,
|
IList<string> args,
|
||||||
ILog log,
|
ILog log,
|
||||||
TimeSpan timeout,
|
TimeSpan timeout,
|
||||||
Dictionary<string, string> environment_variables = null,
|
Dictionary<string, string> environmentVariables = null,
|
||||||
CancellationToken? cancellation_token = null)
|
CancellationToken? cancellationToken = null)
|
||||||
{
|
{
|
||||||
using (var p = new Process ()) {
|
using var p = new Process ();
|
||||||
p.StartInfo.FileName = filename;
|
p.StartInfo.FileName = filename ?? throw new ArgumentNullException (nameof (filename));
|
||||||
p.StartInfo.Arguments = StringUtils.FormatArguments (args);
|
p.StartInfo.Arguments = StringUtils.FormatArguments (args);
|
||||||
return await RunAsync (p, log, timeout, environment_variables, cancellation_token);
|
return await RunAsync (p, log, timeout, environmentVariables, cancellationToken);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ProcessExecutionResult> ExecuteCommandAsync (string filename,
|
public async Task<ProcessExecutionResult> ExecuteCommandAsync (MlaunchArguments args,
|
||||||
MlaunchArguments args,
|
|
||||||
ILog log,
|
ILog log,
|
||||||
TimeSpan timeout,
|
TimeSpan timeout,
|
||||||
Dictionary<string, string> environment_variables = null,
|
Dictionary<string, string> environmentVariables = null,
|
||||||
CancellationToken? cancellation_token = null)
|
CancellationToken? cancellationToken = null)
|
||||||
{
|
{
|
||||||
using (var p = new Process ()) {
|
using var p = new Process ();
|
||||||
p.StartInfo.FileName = filename;
|
return await RunAsync (p, args, log, timeout, environmentVariables, cancellationToken);
|
||||||
p.StartInfo.Arguments = args.AsCommandLine ();
|
|
||||||
return await RunAsync (p, log, timeout, environment_variables, cancellation_token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<ProcessExecutionResult> ExecuteXcodeCommandAsync (string executable, IList<string> args, ILog log, TimeSpan timeout)
|
||||||
|
{
|
||||||
|
string filename = Path.Combine (XcodeRoot, "Contents", "Developer", "usr", "bin", executable);
|
||||||
|
return ExecuteCommandAsync (filename, args, log, timeout: timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport ("/usr/lib/libc.dylib")]
|
[DllImport ("/usr/lib/libc.dylib")]
|
||||||
internal static extern int kill (int pid, int sig);
|
internal static extern int kill (int pid, int sig);
|
||||||
|
|
||||||
public static Task<bool> PollForExitAsync (int pid, TimeSpan timeout)
|
public Task<ProcessExecutionResult> RunAsync (Process process,
|
||||||
|
ILog log,
|
||||||
|
TimeSpan? timeout = null,
|
||||||
|
Dictionary<string, string> environment_variables = null,
|
||||||
|
CancellationToken? cancellationToken = null,
|
||||||
|
bool? diagnostics = null)
|
||||||
{
|
{
|
||||||
var rv = new TaskCompletionSource<bool> ();
|
return RunAsync (process, log, log, log, timeout, environment_variables, cancellationToken, diagnostics);
|
||||||
var watch = new Stopwatch ();
|
|
||||||
watch.Start ();
|
|
||||||
Task.Run (async () => {
|
|
||||||
while (watch.ElapsedMilliseconds < timeout.TotalMilliseconds) {
|
|
||||||
if (kill (pid, 0) != 0) {
|
|
||||||
// pid is not valid anymore, program exited
|
|
||||||
rv.SetResult (true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await Task.Delay (TimeSpan.FromMilliseconds (100));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rv.SetResult (false);
|
public Task<ProcessExecutionResult> RunAsync (Process process,
|
||||||
});
|
MlaunchArguments args,
|
||||||
return rv.Task;
|
ILog log,
|
||||||
}
|
TimeSpan? timeout = null,
|
||||||
|
Dictionary<string, string> environmentVariables = null,
|
||||||
public async Task<ProcessExecutionResult> RunAsync (Process process, ILog log, CancellationToken? cancellation_token = null, bool? diagnostics = null)
|
CancellationToken? cancellationToken = null,
|
||||||
|
bool? diagnostics = null)
|
||||||
{
|
{
|
||||||
return await RunAsync (process, log, log, log, cancellation_token: cancellation_token, diagnostics: diagnostics);
|
if (!args.Any (a => a is SdkRootArgument))
|
||||||
}
|
args.Prepend (new SdkRootArgument (XcodeRoot));
|
||||||
|
|
||||||
public Task<ProcessExecutionResult> RunAsync (Process process, ILog log, TimeSpan? timeout = null, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null, bool? diagnostics = null)
|
process.StartInfo.FileName = MlaunchPath;
|
||||||
{
|
|
||||||
return RunAsync (process, log, log, log, timeout, environment_variables, cancellation_token, diagnostics);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<ProcessExecutionResult> RunAsync (Process process, MlaunchArguments args, ILog log, TimeSpan? timeout = null, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null, bool? diagnostics = null)
|
|
||||||
{
|
|
||||||
process.StartInfo.Arguments = args.AsCommandLine ();
|
process.StartInfo.Arguments = args.AsCommandLine ();
|
||||||
return RunAsync (process, log, timeout, environment_variables, cancellation_token, diagnostics);
|
|
||||||
|
return RunAsync (process, log, timeout, environmentVariables, cancellationToken, diagnostics);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ProcessExecutionResult> RunAsync (Process process, ILog log, ILog StdoutStream, ILog StderrStream, TimeSpan? timeout = null, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = null, bool? diagnostics = null)
|
public async Task<ProcessExecutionResult> RunAsync (Process process,
|
||||||
|
ILog log,
|
||||||
|
ILog stdout,
|
||||||
|
ILog stderr,
|
||||||
|
TimeSpan? timeout = null,
|
||||||
|
Dictionary<string, string> environment_variables = null,
|
||||||
|
CancellationToken? cancellationToken = null,
|
||||||
|
bool? diagnostics = null)
|
||||||
{
|
{
|
||||||
var stdout_completion = new TaskCompletionSource<bool> ();
|
var stdout_completion = new TaskCompletionSource<bool> ();
|
||||||
var stderr_completion = new TaskCompletionSource<bool> ();
|
var stderr_completion = new TaskCompletionSource<bool> ();
|
||||||
|
@ -105,9 +122,9 @@ namespace Xharness.Execution {
|
||||||
process.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
|
process.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
|
||||||
{
|
{
|
||||||
if (e.Data != null) {
|
if (e.Data != null) {
|
||||||
lock (StdoutStream) {
|
lock (stdout) {
|
||||||
StdoutStream.WriteLine (e.Data);
|
stdout.WriteLine (e.Data);
|
||||||
StdoutStream.Flush ();
|
stdout.Flush ();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stdout_completion.TrySetResult (true);
|
stdout_completion.TrySetResult (true);
|
||||||
|
@ -117,9 +134,9 @@ namespace Xharness.Execution {
|
||||||
process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
|
process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
|
||||||
{
|
{
|
||||||
if (e.Data != null) {
|
if (e.Data != null) {
|
||||||
lock (StderrStream) {
|
lock (stderr) {
|
||||||
StderrStream.WriteLine (e.Data);
|
stderr.WriteLine (e.Data);
|
||||||
StderrStream.Flush ();
|
stderr.Flush ();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stderr_completion.TrySetResult (true);
|
stderr_completion.TrySetResult (true);
|
||||||
|
@ -148,7 +165,7 @@ namespace Xharness.Execution {
|
||||||
process.BeginErrorReadLine ();
|
process.BeginErrorReadLine ();
|
||||||
process.BeginOutputReadLine ();
|
process.BeginOutputReadLine ();
|
||||||
|
|
||||||
cancellation_token?.Register (() => {
|
cancellationToken?.Register (() => {
|
||||||
var hasExited = false;
|
var hasExited = false;
|
||||||
try {
|
try {
|
||||||
hasExited = process.HasExited;
|
hasExited = process.HasExited;
|
||||||
|
@ -159,7 +176,7 @@ namespace Xharness.Execution {
|
||||||
// processes behind).
|
// processes behind).
|
||||||
}
|
}
|
||||||
if (!hasExited) {
|
if (!hasExited) {
|
||||||
StderrStream.WriteLine ($"Execution of {pid} was cancelled.");
|
stderr.WriteLine ($"Execution of {pid} was cancelled.");
|
||||||
kill (pid, 9);
|
kill (pid, 9);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -168,7 +185,7 @@ namespace Xharness.Execution {
|
||||||
if (!await WaitForExitAsync (process, timeout.Value)) {
|
if (!await WaitForExitAsync (process, timeout.Value)) {
|
||||||
await KillTreeAsync (process, log, diagnostics ?? true);
|
await KillTreeAsync (process, log, diagnostics ?? true);
|
||||||
rv.TimedOut = true;
|
rv.TimedOut = true;
|
||||||
lock (StderrStream)
|
lock (stderr)
|
||||||
log.WriteLine ($"{pid} Execution timed out after {timeout.Value.TotalSeconds} seconds and the process was killed.");
|
log.WriteLine ($"{pid} Execution timed out after {timeout.Value.TotalSeconds} seconds and the process was killed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,38 +201,6 @@ namespace Xharness.Execution {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> WaitForExitAsync (Process process, TimeSpan? timeout = null)
|
|
||||||
{
|
|
||||||
if (process.HasExited)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
var tcs = new TaskCompletionSource<bool> ();
|
|
||||||
|
|
||||||
void ProcessExited (object sender, EventArgs ea)
|
|
||||||
{
|
|
||||||
process.Exited -= ProcessExited;
|
|
||||||
tcs.TrySetResult (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
process.Exited += ProcessExited;
|
|
||||||
process.EnableRaisingEvents = true;
|
|
||||||
|
|
||||||
// Check if process exited again, in case it exited after we checked
|
|
||||||
// the last time, but before we attached the event handler.
|
|
||||||
if (process.HasExited) {
|
|
||||||
process.Exited -= ProcessExited;
|
|
||||||
tcs.TrySetResult (true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeout.HasValue) {
|
|
||||||
return await tcs.Task.TimeoutAfter (timeout.Value);
|
|
||||||
} else {
|
|
||||||
await tcs.Task;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task KillTreeAsync (Process process, ILog log, bool? diagnostics = true)
|
public Task KillTreeAsync (Process process, ILog log, bool? diagnostics = true)
|
||||||
{
|
{
|
||||||
return KillTreeAsync (process.Id, log, diagnostics);
|
return KillTreeAsync (process.Id, log, diagnostics);
|
||||||
|
@ -223,8 +208,8 @@ namespace Xharness.Execution {
|
||||||
|
|
||||||
public async Task KillTreeAsync (int pid, ILog log, bool? diagnostics = true)
|
public async Task KillTreeAsync (int pid, ILog log, bool? diagnostics = true)
|
||||||
{
|
{
|
||||||
var pids = new List<int> ();
|
var pids = GetChildrenPS (log, pid);
|
||||||
GetChildrenPS (log, pids, pid);
|
|
||||||
if (diagnostics == true) {
|
if (diagnostics == true) {
|
||||||
log.WriteLine ($"Pids to kill: {string.Join (", ", pids.Select ((v) => v.ToString ()).ToArray ())}");
|
log.WriteLine ($"Pids to kill: {string.Join (", ", pids.Select ((v) => v.ToString ()).ToArray ())}");
|
||||||
using (var ps = new Process ()) {
|
using (var ps = new Process ()) {
|
||||||
|
@ -271,9 +256,41 @@ namespace Xharness.Execution {
|
||||||
kill (pids [i], 9);
|
kill (pids [i], 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetChildrenPS (ILog log, List<int> list, int pid)
|
static async Task<bool> WaitForExitAsync (Process process, TimeSpan? timeout = null)
|
||||||
{
|
{
|
||||||
string stdout;
|
if (process.HasExited)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var tcs = new TaskCompletionSource<bool> ();
|
||||||
|
|
||||||
|
void ProcessExited (object sender, EventArgs ea)
|
||||||
|
{
|
||||||
|
process.Exited -= ProcessExited;
|
||||||
|
tcs.TrySetResult (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.Exited += ProcessExited;
|
||||||
|
process.EnableRaisingEvents = true;
|
||||||
|
|
||||||
|
// Check if process exited again, in case it exited after we checked
|
||||||
|
// the last time, but before we attached the event handler.
|
||||||
|
if (process.HasExited) {
|
||||||
|
process.Exited -= ProcessExited;
|
||||||
|
tcs.TrySetResult (true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout.HasValue) {
|
||||||
|
return await tcs.Task.TimeoutAfter (timeout.Value);
|
||||||
|
} else {
|
||||||
|
await tcs.Task;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<int> GetChildrenPS (ILog log, int pid)
|
||||||
|
{
|
||||||
|
var list = new List<int> ();
|
||||||
|
|
||||||
using (Process ps = new Process ()) {
|
using (Process ps = new Process ()) {
|
||||||
ps.StartInfo.FileName = "ps";
|
ps.StartInfo.FileName = "ps";
|
||||||
|
@ -281,20 +298,21 @@ namespace Xharness.Execution {
|
||||||
ps.StartInfo.UseShellExecute = false;
|
ps.StartInfo.UseShellExecute = false;
|
||||||
ps.StartInfo.RedirectStandardOutput = true;
|
ps.StartInfo.RedirectStandardOutput = true;
|
||||||
ps.Start ();
|
ps.Start ();
|
||||||
stdout = ps.StandardOutput.ReadToEnd ();
|
|
||||||
|
string stdout = ps.StandardOutput.ReadToEnd ();
|
||||||
|
|
||||||
if (!ps.WaitForExit (1000)) {
|
if (!ps.WaitForExit (1000)) {
|
||||||
log.WriteLine ("ps didn't finish in a reasonable amount of time (1 second).");
|
log.WriteLine ("ps didn't finish in a reasonable amount of time (1 second).");
|
||||||
return;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps.ExitCode != 0)
|
if (ps.ExitCode != 0)
|
||||||
return;
|
return list;
|
||||||
|
|
||||||
stdout = stdout.Trim ();
|
stdout = stdout.Trim ();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty (stdout))
|
if (string.IsNullOrEmpty (stdout))
|
||||||
return;
|
return list;
|
||||||
|
|
||||||
var dict = new Dictionary<int, List<int>> ();
|
var dict = new Dictionary<int, List<int>> ();
|
||||||
foreach (string line in stdout.Split (new char [] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries)) {
|
foreach (string line in stdout.Split (new char [] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries)) {
|
||||||
|
@ -305,12 +323,11 @@ namespace Xharness.Execution {
|
||||||
|
|
||||||
var parent = l.Substring (0, space);
|
var parent = l.Substring (0, space);
|
||||||
var process = l.Substring (space + 1);
|
var process = l.Substring (space + 1);
|
||||||
int parent_id, process_id;
|
|
||||||
|
|
||||||
if (int.TryParse (parent, out parent_id) && int.TryParse (process, out process_id)) {
|
if (int.TryParse (parent, out var parent_id) && int.TryParse (process, out var process_id)) {
|
||||||
List<int> children;
|
if (!dict.TryGetValue (parent_id, out var children))
|
||||||
if (!dict.TryGetValue (parent_id, out children))
|
|
||||||
dict [parent_id] = children = new List<int> ();
|
dict [parent_id] = children = new List<int> ();
|
||||||
|
|
||||||
children.Add (process_id);
|
children.Add (process_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,15 +336,16 @@ namespace Xharness.Execution {
|
||||||
queue.Enqueue (pid);
|
queue.Enqueue (pid);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
List<int> children;
|
|
||||||
var parent_id = queue.Dequeue ();
|
var parent_id = queue.Dequeue ();
|
||||||
list.Add (parent_id);
|
list.Add (parent_id);
|
||||||
if (dict.TryGetValue (parent_id, out children)) {
|
if (dict.TryGetValue (parent_id, out var children)) {
|
||||||
foreach (var child in children)
|
foreach (var child in children)
|
||||||
queue.Enqueue (child);
|
queue.Enqueue (child);
|
||||||
}
|
}
|
||||||
} while (queue.Count > 0);
|
} while (queue.Count > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,6 @@ using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Runtime.Serialization.Json;
|
using System.Runtime.Serialization.Json;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using System.Text;
|
|
||||||
using Xamarin;
|
|
||||||
using Xharness.Execution;
|
using Xharness.Execution;
|
||||||
using Xharness.Logging;
|
using Xharness.Logging;
|
||||||
|
|
||||||
|
@ -15,7 +13,6 @@ namespace Xharness
|
||||||
{
|
{
|
||||||
public static class GitHub
|
public static class GitHub
|
||||||
{
|
{
|
||||||
static IProcessManager ProcessManager { get; set; } = new ProcessManager ();
|
|
||||||
static WebClient CreateClient ()
|
static WebClient CreateClient ()
|
||||||
{
|
{
|
||||||
var client = new WebClient ();
|
var client = new WebClient ();
|
||||||
|
@ -56,11 +53,11 @@ namespace Xharness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<string> GetModifiedFiles (Harness harness, int pull_request)
|
public static IEnumerable<string> GetModifiedFiles (IProcessManager processManager, Harness harness, int pull_request)
|
||||||
{
|
{
|
||||||
var path = Path.Combine (harness.LogDirectory, "pr" + pull_request + "-files.log");
|
var path = Path.Combine (harness.LogDirectory, "pr" + pull_request + "-files.log");
|
||||||
if (!File.Exists (path)) {
|
if (!File.Exists (path)) {
|
||||||
var rv = GetModifiedFilesLocally (harness, pull_request);
|
var rv = GetModifiedFilesLocally (processManager, harness, pull_request);
|
||||||
if (rv == null || rv.Count () == 0) {
|
if (rv == null || rv.Count () == 0) {
|
||||||
rv = GetModifiedFilesRemotely (harness, pull_request);
|
rv = GetModifiedFilesRemotely (harness, pull_request);
|
||||||
if (rv == null)
|
if (rv == null)
|
||||||
|
@ -141,7 +138,7 @@ namespace Xharness
|
||||||
return File.ReadAllLines (path);
|
return File.ReadAllLines (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static IEnumerable<string> GetModifiedFilesLocally (Harness harness, int pull_request)
|
static IEnumerable<string> GetModifiedFilesLocally (IProcessManager processManager, Harness harness, int pull_request)
|
||||||
{
|
{
|
||||||
var base_commit = $"origin/pr/{pull_request}/merge^";
|
var base_commit = $"origin/pr/{pull_request}/merge^";
|
||||||
var head_commit = $"origin/pr/{pull_request}/merge";
|
var head_commit = $"origin/pr/{pull_request}/merge";
|
||||||
|
@ -155,7 +152,7 @@ namespace Xharness
|
||||||
git.StartInfo.FileName = "git";
|
git.StartInfo.FileName = "git";
|
||||||
git.StartInfo.Arguments = $"diff-tree --no-commit-id --name-only -r {base_commit}..{head_commit}";
|
git.StartInfo.Arguments = $"diff-tree --no-commit-id --name-only -r {base_commit}..{head_commit}";
|
||||||
var output = new MemoryLog ();
|
var output = new MemoryLog ();
|
||||||
var rv = ProcessManager.RunAsync (git, harness.HarnessLog, output, output).Result;
|
var rv = processManager.RunAsync (git, harness.HarnessLog, stdoutLog: output, stderrLog: output).Result;
|
||||||
if (rv.Succeeded)
|
if (rv.Succeeded)
|
||||||
return output.ToString ().Split (new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
return output.ToString ().Split (new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Web.UI.WebControls;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using Xharness.Collections;
|
using Xharness.Collections;
|
||||||
using Xharness.Execution;
|
using Xharness.Execution;
|
||||||
|
@ -18,24 +19,20 @@ namespace Xharness.Hardware {
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DeviceLoaderFactory : IDeviceLoaderFactory {
|
public class DeviceLoaderFactory : IDeviceLoaderFactory {
|
||||||
readonly IHarness harness;
|
|
||||||
readonly IProcessManager processManager;
|
readonly IProcessManager processManager;
|
||||||
|
|
||||||
public DeviceLoaderFactory (IHarness harness, IProcessManager processManager)
|
public DeviceLoaderFactory (IProcessManager processManager)
|
||||||
{
|
{
|
||||||
this.harness = harness ?? throw new ArgumentNullException (nameof (harness));
|
|
||||||
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDeviceLoader CreateLoader () => new Devices (harness, processManager);
|
public IDeviceLoader CreateLoader () => new Devices (processManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Devices : IDeviceLoader {
|
public class Devices : IDeviceLoader {
|
||||||
readonly IProcessManager processManager;
|
readonly IProcessManager processManager;
|
||||||
bool loaded;
|
bool loaded;
|
||||||
|
|
||||||
public IHarness Harness { get; set; }
|
|
||||||
|
|
||||||
BlockingEnumerableCollection<IHardwareDevice> connected_devices = new BlockingEnumerableCollection<IHardwareDevice> ();
|
BlockingEnumerableCollection<IHardwareDevice> connected_devices = new BlockingEnumerableCollection<IHardwareDevice> ();
|
||||||
|
|
||||||
public IEnumerable<IHardwareDevice> ConnectedDevices => connected_devices;
|
public IEnumerable<IHardwareDevice> ConnectedDevices => connected_devices;
|
||||||
|
@ -51,9 +48,8 @@ namespace Xharness.Hardware {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Devices (IHarness harness, IProcessManager processManager)
|
public Devices (IProcessManager processManager)
|
||||||
{
|
{
|
||||||
Harness = harness ?? throw new ArgumentNullException (nameof (harness));
|
|
||||||
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,18 +72,19 @@ namespace Xharness.Hardware {
|
||||||
var tmpfile = Path.GetTempFileName ();
|
var tmpfile = Path.GetTempFileName ();
|
||||||
try {
|
try {
|
||||||
using (var process = new Process ()) {
|
using (var process = new Process ()) {
|
||||||
process.StartInfo.FileName = Harness.MlaunchPath;
|
|
||||||
var arguments = new MlaunchArguments (
|
var arguments = new MlaunchArguments (
|
||||||
new SdkRootArgument (Harness.XcodeRoot),
|
|
||||||
new ListDevicesArgument (tmpfile),
|
new ListDevicesArgument (tmpfile),
|
||||||
new XmlOutputFormatArgument ());
|
new XmlOutputFormatArgument ());
|
||||||
|
|
||||||
if (extra_data)
|
if (extra_data)
|
||||||
arguments.Add (new ListExtraDataArgument ());
|
arguments.Add (new ListExtraDataArgument ());
|
||||||
|
|
||||||
|
var task = processManager.ExecuteCommandAsync (arguments, log, timeout: TimeSpan.FromSeconds (120));
|
||||||
log.WriteLine ("Launching {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
log.WriteLine ("Launching {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
||||||
var rv = await processManager.RunAsync (process, arguments, log, timeout: TimeSpan.FromSeconds (120));
|
|
||||||
if (!rv.Succeeded)
|
var result = await task;
|
||||||
|
|
||||||
|
if (!result.Succeeded)
|
||||||
throw new Exception ("Failed to list devices.");
|
throw new Exception ("Failed to list devices.");
|
||||||
log.WriteLine ("Result:");
|
log.WriteLine ("Result:");
|
||||||
log.WriteLine (File.ReadAllText (tmpfile));
|
log.WriteLine (File.ReadAllText (tmpfile));
|
||||||
|
|
|
@ -33,7 +33,6 @@ namespace Xharness.Hardware {
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ISimulatorDevice : IDevice {
|
public interface ISimulatorDevice : IDevice {
|
||||||
ITCCDatabase TCCDatabase { get; set; }
|
|
||||||
string SimRuntime { get; set; }
|
string SimRuntime { get; set; }
|
||||||
string SimDeviceType { get; set; }
|
string SimDeviceType { get; set; }
|
||||||
string DataPath { get; set; }
|
string DataPath { get; set; }
|
||||||
|
|
|
@ -9,10 +9,8 @@ using Xharness.Logging;
|
||||||
namespace Xharness.Hardware {
|
namespace Xharness.Hardware {
|
||||||
|
|
||||||
public class SimulatorDevice : ISimulatorDevice {
|
public class SimulatorDevice : ISimulatorDevice {
|
||||||
readonly IHarness harness;
|
|
||||||
readonly IProcessManager processManager;
|
readonly IProcessManager processManager;
|
||||||
|
readonly ITCCDatabase tCCDatabase;
|
||||||
public ITCCDatabase TCCDatabase { get; set; } = new TCCDatabase ();
|
|
||||||
|
|
||||||
public string UDID { get; set; }
|
public string UDID { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
@ -23,10 +21,10 @@ namespace Xharness.Hardware {
|
||||||
public string SystemLog => Path.Combine (LogPath, "system.log");
|
public string SystemLog => Path.Combine (LogPath, "system.log");
|
||||||
|
|
||||||
|
|
||||||
public SimulatorDevice (IHarness harness, IProcessManager processManager)
|
public SimulatorDevice (IProcessManager processManager, ITCCDatabase tccDatabase)
|
||||||
{
|
{
|
||||||
this.harness = harness ?? throw new ArgumentNullException (nameof (harness));
|
|
||||||
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
||||||
|
this.tCCDatabase = tccDatabase ?? throw new ArgumentNullException (nameof (tccDatabase));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsWatchSimulator => SimRuntime.StartsWith ("com.apple.CoreSimulator.SimRuntime.watchOS", StringComparison.Ordinal);
|
public bool IsWatchSimulator => SimRuntime.StartsWith ("com.apple.CoreSimulator.SimRuntime.watchOS", StringComparison.Ordinal);
|
||||||
|
@ -43,17 +41,17 @@ namespace Xharness.Hardware {
|
||||||
{
|
{
|
||||||
// here we don't care if execution fails.
|
// here we don't care if execution fails.
|
||||||
// erase the simulator (make sure the device isn't running first)
|
// erase the simulator (make sure the device isn't running first)
|
||||||
await harness.ExecuteXcodeCommandAsync ("simctl", new [] { "shutdown", UDID }, log, TimeSpan.FromMinutes (1));
|
await processManager.ExecuteXcodeCommandAsync ("simctl", new [] { "shutdown", UDID }, log, TimeSpan.FromMinutes (1));
|
||||||
await harness.ExecuteXcodeCommandAsync ("simctl", new [] { "erase", UDID }, log, TimeSpan.FromMinutes (1));
|
await processManager.ExecuteXcodeCommandAsync ("simctl", new [] { "erase", UDID }, log, TimeSpan.FromMinutes (1));
|
||||||
|
|
||||||
// boot & shutdown to make sure it actually works
|
// boot & shutdown to make sure it actually works
|
||||||
await harness.ExecuteXcodeCommandAsync ("simctl", new [] { "boot", UDID }, log, TimeSpan.FromMinutes (1));
|
await processManager.ExecuteXcodeCommandAsync ("simctl", new [] { "boot", UDID }, log, TimeSpan.FromMinutes (1));
|
||||||
await harness.ExecuteXcodeCommandAsync ("simctl", new [] { "shutdown", UDID }, log, TimeSpan.FromMinutes (1));
|
await processManager.ExecuteXcodeCommandAsync ("simctl", new [] { "shutdown", UDID }, log, TimeSpan.FromMinutes (1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ShutdownAsync (ILog log)
|
public async Task ShutdownAsync (ILog log)
|
||||||
{
|
{
|
||||||
await harness.ExecuteXcodeCommandAsync ("simctl", new [] { "shutdown", UDID }, log, TimeSpan.FromMinutes (1));
|
await processManager.ExecuteXcodeCommandAsync ("simctl", new [] { "shutdown", UDID }, log, TimeSpan.FromMinutes (1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task KillEverythingAsync (ILog log)
|
public async Task KillEverythingAsync (ILog log)
|
||||||
|
@ -86,12 +84,12 @@ namespace Xharness.Hardware {
|
||||||
{
|
{
|
||||||
string simulator_app;
|
string simulator_app;
|
||||||
|
|
||||||
if (IsWatchSimulator && harness.XcodeVersion.Major < 9) {
|
if (IsWatchSimulator && processManager.XcodeVersion.Major < 9) {
|
||||||
simulator_app = Path.Combine (harness.XcodeRoot, "Contents", "Developer", "Applications", "Simulator (Watch).app");
|
simulator_app = Path.Combine (processManager.XcodeRoot, "Contents", "Developer", "Applications", "Simulator (Watch).app");
|
||||||
} else {
|
} else {
|
||||||
simulator_app = Path.Combine (harness.XcodeRoot, "Contents", "Developer", "Applications", "Simulator.app");
|
simulator_app = Path.Combine (processManager.XcodeRoot, "Contents", "Developer", "Applications", "Simulator.app");
|
||||||
if (!Directory.Exists (simulator_app))
|
if (!Directory.Exists (simulator_app))
|
||||||
simulator_app = Path.Combine (harness.XcodeRoot, "Contents", "Developer", "Applications", "iOS Simulator.app");
|
simulator_app = Path.Combine (processManager.XcodeRoot, "Contents", "Developer", "Applications", "iOS Simulator.app");
|
||||||
}
|
}
|
||||||
|
|
||||||
await processManager.ExecuteCommandAsync ("open", new [] { "-a", simulator_app, "--args", "-CurrentDeviceUDID", UDID }, log, TimeSpan.FromSeconds (15));
|
await processManager.ExecuteCommandAsync ("open", new [] { "-a", simulator_app, "--args", "-CurrentDeviceUDID", UDID }, log, TimeSpan.FromSeconds (15));
|
||||||
|
@ -121,7 +119,7 @@ namespace Xharness.Hardware {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (File.Exists (TCC_db)) {
|
if (File.Exists (TCC_db)) {
|
||||||
await TCCDatabase.AgreeToPromptsAsync (SimRuntime, TCC_db, log, bundle_identifiers);
|
await tCCDatabase.AgreeToPromptsAsync (SimRuntime, TCC_db, log, bundle_identifiers);
|
||||||
} else {
|
} else {
|
||||||
log.WriteLine ("No TCC.db found for the simulator {0} (SimRuntime={1} and SimDeviceType={1})", UDID, SimRuntime, SimDeviceType);
|
log.WriteLine ("No TCC.db found for the simulator {0} (SimRuntime={1} and SimDeviceType={1})", UDID, SimRuntime, SimDeviceType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,16 +22,14 @@ namespace Xharness.Hardware {
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SimulatorsLoaderFactory : ISimulatorsLoaderFactory {
|
public class SimulatorsLoaderFactory : ISimulatorsLoaderFactory {
|
||||||
readonly IHarness harness;
|
|
||||||
readonly IProcessManager processManager;
|
readonly IProcessManager processManager;
|
||||||
|
|
||||||
public SimulatorsLoaderFactory (IHarness harness, IProcessManager processManager)
|
public SimulatorsLoaderFactory (IProcessManager processManager)
|
||||||
{
|
{
|
||||||
this.harness = harness ?? throw new ArgumentNullException (nameof (harness));
|
|
||||||
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISimulatorsLoader CreateLoader () => new Simulators (harness, processManager);
|
public ISimulatorsLoader CreateLoader () => new Simulators (processManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Simulators : ISimulatorsLoader {
|
public class Simulators : ISimulatorsLoader {
|
||||||
|
@ -44,16 +42,13 @@ namespace Xharness.Hardware {
|
||||||
|
|
||||||
bool loaded;
|
bool loaded;
|
||||||
|
|
||||||
public IHarness Harness { get; set; }
|
|
||||||
|
|
||||||
public IEnumerable<SimRuntime> SupportedRuntimes => supported_runtimes;
|
public IEnumerable<SimRuntime> SupportedRuntimes => supported_runtimes;
|
||||||
public IEnumerable<SimDeviceType> SupportedDeviceTypes => supported_device_types;
|
public IEnumerable<SimDeviceType> SupportedDeviceTypes => supported_device_types;
|
||||||
public IEnumerable<SimulatorDevice> AvailableDevices => available_devices;
|
public IEnumerable<SimulatorDevice> AvailableDevices => available_devices;
|
||||||
public IEnumerable<SimDevicePair> AvailableDevicePairs => available_device_pairs;
|
public IEnumerable<SimDevicePair> AvailableDevicePairs => available_device_pairs;
|
||||||
|
|
||||||
public Simulators (IHarness harness, IProcessManager processManager)
|
public Simulators (IProcessManager processManager)
|
||||||
{
|
{
|
||||||
Harness = harness ?? throw new ArgumentNullException (nameof (harness));
|
|
||||||
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,18 +71,18 @@ namespace Xharness.Hardware {
|
||||||
var tmpfile = Path.GetTempFileName ();
|
var tmpfile = Path.GetTempFileName ();
|
||||||
try {
|
try {
|
||||||
using (var process = new Process ()) {
|
using (var process = new Process ()) {
|
||||||
process.StartInfo.FileName = Harness.MlaunchPath;
|
|
||||||
var arguments = new MlaunchArguments (
|
var arguments = new MlaunchArguments (
|
||||||
new SdkRootArgument(Harness.XcodeRoot),
|
|
||||||
new ListSimulatorsArgument(tmpfile),
|
new ListSimulatorsArgument(tmpfile),
|
||||||
new XmlOutputFormatArgument());
|
new XmlOutputFormatArgument());
|
||||||
|
|
||||||
process.StartInfo.Arguments = arguments.AsCommandLine ();
|
var task = processManager.ExecuteCommandAsync (arguments, log, timeout: TimeSpan.FromSeconds (30));
|
||||||
log.WriteLine ("Launching {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
log.WriteLine ("Launching {0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments);
|
||||||
var rv = await processManager.RunAsync (process, arguments, log, timeout: TimeSpan.FromSeconds (30));
|
|
||||||
|
|
||||||
if (!rv.Succeeded)
|
var result = await task;
|
||||||
|
|
||||||
|
if (!result.Succeeded)
|
||||||
throw new Exception ("Failed to list simulators.");
|
throw new Exception ("Failed to list simulators.");
|
||||||
|
|
||||||
log.WriteLine ("Result:");
|
log.WriteLine ("Result:");
|
||||||
log.WriteLine (File.ReadAllText (tmpfile));
|
log.WriteLine (File.ReadAllText (tmpfile));
|
||||||
var simulator_data = new XmlDocument ();
|
var simulator_data = new XmlDocument ();
|
||||||
|
@ -112,7 +107,7 @@ namespace Xharness.Hardware {
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (XmlNode sim in simulator_data.SelectNodes ("/MTouch/Simulator/AvailableDevices/SimDevice")) {
|
foreach (XmlNode sim in simulator_data.SelectNodes ("/MTouch/Simulator/AvailableDevices/SimDevice")) {
|
||||||
available_devices.Add (new SimulatorDevice (Harness, processManager) {
|
available_devices.Add (new SimulatorDevice (processManager, new TCCDatabase (processManager)) {
|
||||||
Name = sim.Attributes ["Name"].Value,
|
Name = sim.Attributes ["Name"].Value,
|
||||||
UDID = sim.Attributes ["UDID"].Value,
|
UDID = sim.Attributes ["UDID"].Value,
|
||||||
SimRuntime = sim.SelectSingleNode ("SimRuntime").InnerText,
|
SimRuntime = sim.SelectSingleNode ("SimRuntime").InnerText,
|
||||||
|
@ -168,7 +163,7 @@ namespace Xharness.Hardware {
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rv = await Harness.ExecuteXcodeCommandAsync ("simctl", new [] { "create", CreateName (devicetype, runtime), devicetype, runtime }, log, TimeSpan.FromMinutes (1));
|
var rv = await processManager.ExecuteXcodeCommandAsync ("simctl", new [] { "create", CreateName (devicetype, runtime), devicetype, runtime }, log, TimeSpan.FromMinutes (1));
|
||||||
if (!rv.Succeeded) {
|
if (!rv.Succeeded) {
|
||||||
log.WriteLine ($"Could not create device for runtime={runtime} and device type={devicetype}.");
|
log.WriteLine ($"Could not create device for runtime={runtime} and device type={devicetype}.");
|
||||||
return null;
|
return null;
|
||||||
|
@ -207,8 +202,7 @@ namespace Xharness.Hardware {
|
||||||
log.Write (value);
|
log.Write (value);
|
||||||
capturedLog.Append (value);
|
capturedLog.Append (value);
|
||||||
});
|
});
|
||||||
|
var rv = await processManager.ExecuteXcodeCommandAsync ("simctl", new [] { "pair", device.UDID, companion_device.UDID }, pairLog, TimeSpan.FromMinutes (1));
|
||||||
var rv = await Harness.ExecuteXcodeCommandAsync ("simctl", new [] { "pair", device.UDID, companion_device.UDID }, pairLog, TimeSpan.FromMinutes (1));
|
|
||||||
if (!rv.Succeeded) {
|
if (!rv.Succeeded) {
|
||||||
if (!create_device) {
|
if (!create_device) {
|
||||||
var try_creating_device = false;
|
var try_creating_device = false;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Xharness.Execution;
|
using Xharness.Execution;
|
||||||
using Xharness.Logging;
|
using Xharness.Logging;
|
||||||
|
@ -9,7 +8,6 @@ using Xharness.Logging;
|
||||||
namespace Xharness.Hardware {
|
namespace Xharness.Hardware {
|
||||||
|
|
||||||
public interface ITCCDatabase {
|
public interface ITCCDatabase {
|
||||||
IProcessManager ProcessManager { get; set; }
|
|
||||||
Task AgreeToPromptsAsync (string simRuntime, string dataPath, ILog log, params string [] bundle_identifiers);
|
Task AgreeToPromptsAsync (string simRuntime, string dataPath, ILog log, params string [] bundle_identifiers);
|
||||||
int GetTCCFormat (string simRuntime);
|
int GetTCCFormat (string simRuntime);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +17,12 @@ namespace Xharness.Hardware {
|
||||||
static readonly string tvOSSimRuntimePrefix = "com.apple.CoreSimulator.SimRuntime.tvOS-";
|
static readonly string tvOSSimRuntimePrefix = "com.apple.CoreSimulator.SimRuntime.tvOS-";
|
||||||
static readonly string watchOSRuntimePrefix = "com.apple.CoreSimulator.SimRuntime.watchOS-";
|
static readonly string watchOSRuntimePrefix = "com.apple.CoreSimulator.SimRuntime.watchOS-";
|
||||||
|
|
||||||
public IProcessManager ProcessManager { get; set; } = new ProcessManager ();
|
readonly IProcessManager processManager;
|
||||||
|
|
||||||
|
public TCCDatabase (IProcessManager processManager)
|
||||||
|
{
|
||||||
|
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
||||||
|
}
|
||||||
|
|
||||||
public int GetTCCFormat (string simRuntime) {
|
public int GetTCCFormat (string simRuntime) {
|
||||||
|
|
||||||
|
@ -109,7 +112,7 @@ namespace Xharness.Hardware {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args.Add (sql.ToString ());
|
args.Add (sql.ToString ());
|
||||||
var rv = await ProcessManager.ExecuteCommandAsync ("sqlite3", args, log, TimeSpan.FromSeconds (5));
|
var rv = await processManager.ExecuteCommandAsync ("sqlite3", args, log, TimeSpan.FromSeconds (5));
|
||||||
if (!rv.Succeeded) {
|
if (!rv.Succeeded) {
|
||||||
failure = true;
|
failure = true;
|
||||||
break;
|
break;
|
||||||
|
@ -124,7 +127,7 @@ namespace Xharness.Hardware {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.WriteLine ("Current TCC database contents:");
|
log.WriteLine ("Current TCC database contents:");
|
||||||
await ProcessManager.ExecuteCommandAsync ("sqlite3", new [] { TCCDb, ".dump" }, log, TimeSpan.FromSeconds (5));
|
await processManager.ExecuteCommandAsync ("sqlite3", new [] { TCCDb, ".dump" }, log, TimeSpan.FromSeconds (5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using Xharness.BCLTestImporter;
|
using Xharness.BCLTestImporter;
|
||||||
using Xharness.Logging;
|
using Xharness.Logging;
|
||||||
|
@ -51,66 +50,30 @@ namespace Xharness
|
||||||
|
|
||||||
public interface IHarness {
|
public interface IHarness {
|
||||||
HarnessAction Action { get; }
|
HarnessAction Action { get; }
|
||||||
bool DisableWatchOSOnWrench { get; }
|
|
||||||
string DOTNET { get; }
|
|
||||||
bool DryRun { get; }
|
|
||||||
bool ENABLE_XAMARIN { get; }
|
|
||||||
Dictionary<string, string> EnvironmentVariables { get; }
|
Dictionary<string, string> EnvironmentVariables { get; }
|
||||||
ILog HarnessLog { get; set; }
|
ILog HarnessLog { get; set; }
|
||||||
string GetStandardErrorTty ();
|
|
||||||
bool InCI { get; }
|
bool InCI { get; }
|
||||||
bool INCLUDE_IOS { get; }
|
|
||||||
bool INCLUDE_MAC { get; }
|
|
||||||
bool INCLUDE_TVOS { get; }
|
|
||||||
bool INCLUDE_WATCH { get; }
|
|
||||||
bool? IncludeSystemPermissionTests { get; set; }
|
|
||||||
string IOS_DESTDIR { get; }
|
|
||||||
List<iOSTestProject> IOSTestProjects { get; }
|
|
||||||
string JENKINS_RESULTS_DIRECTORY { get; }
|
|
||||||
string JenkinsConfiguration { get; }
|
|
||||||
HashSet<string> Labels { get; }
|
|
||||||
double LaunchTimeout { get; }
|
double LaunchTimeout { get; }
|
||||||
string LogDirectory { get; }
|
|
||||||
string MAC_DESTDIR { get; }
|
|
||||||
List<MacTestProject> MacTestProjects { get; }
|
|
||||||
string MarkdownSummaryPath { get; }
|
|
||||||
string MlaunchPath { get; }
|
|
||||||
string MONO_IOS_SDK_DESTDIR { get; }
|
|
||||||
string MONO_MAC_SDK_DESTDIR { get; }
|
|
||||||
string MONO_PATH { get; }
|
|
||||||
string PeriodicCommand { get; }
|
|
||||||
string PeriodicCommandArguments { get; }
|
|
||||||
TimeSpan PeriodicCommandInterval { get; }
|
|
||||||
IProcessManager ProcessManager { get; }
|
|
||||||
double Timeout { get; }
|
double Timeout { get; }
|
||||||
string TodayContainerTemplate { get; }
|
|
||||||
string TodayExtensionTemplate { get; }
|
|
||||||
bool UseGroupedApps { get; }
|
|
||||||
int Verbosity { get; }
|
int Verbosity { get; }
|
||||||
string WatchOSAppTemplate { get; }
|
|
||||||
string WatchOSContainerTemplate { get; }
|
|
||||||
string WatchOSExtensionTemplate { get; }
|
|
||||||
string XcodeRoot { get; }
|
|
||||||
Version XcodeVersion { get; }
|
|
||||||
XmlResultJargon XmlJargon { get; }
|
XmlResultJargon XmlJargon { get; }
|
||||||
Task<ProcessExecutionResult> ExecuteXcodeCommandAsync (string executable, IList<string> args, ILog log, TimeSpan timeout);
|
|
||||||
bool GetIncludeSystemPermissionTests (TestPlatform platform, bool device);
|
bool GetIncludeSystemPermissionTests (TestPlatform platform, bool device);
|
||||||
|
string GetStandardErrorTty ();
|
||||||
void Log (int min_level, string message, params object [] args);
|
void Log (int min_level, string message, params object [] args);
|
||||||
void Log (string message);
|
|
||||||
void Log (string message, params object [] args);
|
|
||||||
void Save (StringWriter doc, string path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Harness : IHarness {
|
public class Harness : IHarness {
|
||||||
readonly TestTarget target;
|
readonly TestTarget target;
|
||||||
readonly string buildConfiguration = "Debug";
|
readonly string buildConfiguration = "Debug";
|
||||||
|
|
||||||
|
IProcessManager processManager;
|
||||||
|
|
||||||
public HarnessAction Action { get; }
|
public HarnessAction Action { get; }
|
||||||
public int Verbosity { get; }
|
public int Verbosity { get; }
|
||||||
public ILog HarnessLog { get; set; }
|
public ILog HarnessLog { get; set; }
|
||||||
public HashSet<string> Labels { get; }
|
public HashSet<string> Labels { get; }
|
||||||
public XmlResultJargon XmlJargon { get; }
|
public XmlResultJargon XmlJargon { get; }
|
||||||
public IProcessManager ProcessManager { get; }
|
|
||||||
public IResultParser ResultParser { get; }
|
public IResultParser ResultParser { get; }
|
||||||
|
|
||||||
// This is the maccore/tests directory.
|
// This is the maccore/tests directory.
|
||||||
|
@ -150,6 +113,8 @@ namespace Xharness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string MlaunchPath => Path.Combine (IOS_DESTDIR, "Library", "Frameworks", "Xamarin.iOS.framework", "Versions", "Current", "bin", "mlaunch");
|
||||||
|
|
||||||
public List<iOSTestProject> IOSTestProjects { get; }
|
public List<iOSTestProject> IOSTestProjects { get; }
|
||||||
public List<MacTestProject> MacTestProjects { get; } = new List<MacTestProject> ();
|
public List<MacTestProject> MacTestProjects { get; } = new List<MacTestProject> ();
|
||||||
|
|
||||||
|
@ -164,19 +129,19 @@ namespace Xharness
|
||||||
public string TodayContainerTemplate { get; private set; }
|
public string TodayContainerTemplate { get; private set; }
|
||||||
public string TodayExtensionTemplate { get; private set; }
|
public string TodayExtensionTemplate { get; private set; }
|
||||||
public string BCLTodayExtensionTemplate { get; private set; }
|
public string BCLTodayExtensionTemplate { get; private set; }
|
||||||
public string MONO_PATH { get; private set; } // Use same name as in Makefiles, so that a grep finds it.
|
public string MONO_PATH { get; } // Use same name as in Makefiles, so that a grep finds it.
|
||||||
public string TVOS_MONO_PATH { get; private set; } // Use same name as in Makefiles, so that a grep finds it.
|
public string TVOS_MONO_PATH { get; } // Use same name as in Makefiles, so that a grep finds it.
|
||||||
public bool INCLUDE_IOS { get; private set; }
|
public bool INCLUDE_IOS { get; }
|
||||||
public bool INCLUDE_TVOS { get; private set; }
|
public bool INCLUDE_TVOS { get; }
|
||||||
public bool INCLUDE_WATCH { get; private set; }
|
public bool INCLUDE_WATCH { get; }
|
||||||
public bool INCLUDE_MAC { get; private set; }
|
public bool INCLUDE_MAC { get; }
|
||||||
public string JENKINS_RESULTS_DIRECTORY { get; private set; } // Use same name as in Makefiles, so that a grep finds it.
|
public string JENKINS_RESULTS_DIRECTORY { get; } // Use same name as in Makefiles, so that a grep finds it.
|
||||||
public string MAC_DESTDIR { get; private set; }
|
public string MAC_DESTDIR { get; }
|
||||||
public string IOS_DESTDIR { get; private set; }
|
public string IOS_DESTDIR { get; }
|
||||||
public string MONO_IOS_SDK_DESTDIR { get; private set; }
|
public string MONO_IOS_SDK_DESTDIR { get; }
|
||||||
public string MONO_MAC_SDK_DESTDIR { get; private set; }
|
public string MONO_MAC_SDK_DESTDIR { get; }
|
||||||
public bool ENABLE_XAMARIN { get; private set; }
|
public bool ENABLE_XAMARIN { get; }
|
||||||
public string DOTNET { get; private set; }
|
public string DOTNET { get; }
|
||||||
|
|
||||||
// Run
|
// Run
|
||||||
|
|
||||||
|
@ -196,9 +161,8 @@ namespace Xharness
|
||||||
|
|
||||||
public string GetStandardErrorTty () => Helpers.GetTerminalName (2);
|
public string GetStandardErrorTty () => Helpers.GetTerminalName (2);
|
||||||
|
|
||||||
public Harness (IProcessManager processManager, IResultParser resultParser, HarnessAction action, HarnessConfiguration configuration)
|
public Harness (IResultParser resultParser, HarnessAction action, HarnessConfiguration configuration)
|
||||||
{
|
{
|
||||||
ProcessManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
|
||||||
ResultParser = resultParser ?? throw new ArgumentNullException (nameof (resultParser));
|
ResultParser = resultParser ?? throw new ArgumentNullException (nameof (resultParser));
|
||||||
Action = action;
|
Action = action;
|
||||||
|
|
||||||
|
@ -217,7 +181,6 @@ namespace Xharness
|
||||||
PeriodicCommand = configuration.PeriodicCommand;
|
PeriodicCommand = configuration.PeriodicCommand;
|
||||||
PeriodicCommandArguments = configuration.PeriodicCommandArguments;
|
PeriodicCommandArguments = configuration.PeriodicCommandArguments;
|
||||||
PeriodicCommandInterval = configuration.PeriodicCommandInterval;
|
PeriodicCommandInterval = configuration.PeriodicCommandInterval;
|
||||||
SdkRoot = configuration.SdkRoot;
|
|
||||||
target = configuration.Target;
|
target = configuration.Target;
|
||||||
Timeout = configuration.TimeoutInMinutes;
|
Timeout = configuration.TimeoutInMinutes;
|
||||||
useSystemXamarinIOSMac = configuration.UseSystemXamarinIOSMac;
|
useSystemXamarinIOSMac = configuration.UseSystemXamarinIOSMac;
|
||||||
|
@ -233,6 +196,29 @@ namespace Xharness
|
||||||
EnvironmentVariables = new Dictionary<string, string> (configuration.EnvironmentVariables);
|
EnvironmentVariables = new Dictionary<string, string> (configuration.EnvironmentVariables);
|
||||||
|
|
||||||
LaunchTimeout = InCI ? 3 : 120;
|
LaunchTimeout = InCI ? 3 : 120;
|
||||||
|
|
||||||
|
var config = ParseConfigFiles ();
|
||||||
|
var src_root = Path.GetDirectoryName (Path.GetFullPath (RootDirectory));
|
||||||
|
|
||||||
|
MONO_PATH = Path.GetFullPath (Path.Combine (src_root, "external", "mono"));
|
||||||
|
TVOS_MONO_PATH = MONO_PATH;
|
||||||
|
INCLUDE_IOS = config.ContainsKey ("INCLUDE_IOS") && !string.IsNullOrEmpty (config ["INCLUDE_IOS"]);
|
||||||
|
INCLUDE_TVOS = config.ContainsKey ("INCLUDE_TVOS") && !string.IsNullOrEmpty (config ["INCLUDE_TVOS"]);
|
||||||
|
JENKINS_RESULTS_DIRECTORY = config ["JENKINS_RESULTS_DIRECTORY"];
|
||||||
|
INCLUDE_WATCH = config.ContainsKey ("INCLUDE_WATCH") && !string.IsNullOrEmpty (config ["INCLUDE_WATCH"]);
|
||||||
|
INCLUDE_MAC = config.ContainsKey ("INCLUDE_MAC") && !string.IsNullOrEmpty (config ["INCLUDE_MAC"]);
|
||||||
|
MAC_DESTDIR = config ["MAC_DESTDIR"];
|
||||||
|
|
||||||
|
IOS_DESTDIR = config ["IOS_DESTDIR"];
|
||||||
|
MONO_IOS_SDK_DESTDIR = config ["MONO_IOS_SDK_DESTDIR"];
|
||||||
|
MONO_MAC_SDK_DESTDIR = config ["MONO_MAC_SDK_DESTDIR"];
|
||||||
|
ENABLE_XAMARIN = config.ContainsKey ("ENABLE_XAMARIN") && !string.IsNullOrEmpty (config ["ENABLE_XAMARIN"]);
|
||||||
|
DOTNET = config ["DOTNET"];
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty (SdkRoot))
|
||||||
|
SdkRoot = config ["XCODE_DEVELOPER_ROOT"] ?? configuration.SdkRoot;
|
||||||
|
|
||||||
|
processManager = new ProcessManager (XcodeRoot, MlaunchPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetIncludeSystemPermissionTests (TestPlatform platform, bool device)
|
public bool GetIncludeSystemPermissionTests (TestPlatform platform, bool device)
|
||||||
|
@ -277,45 +263,6 @@ namespace Xharness
|
||||||
} while (true);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Version xcode_version;
|
|
||||||
public Version XcodeVersion {
|
|
||||||
get {
|
|
||||||
if (xcode_version == null) {
|
|
||||||
var doc = new XmlDocument ();
|
|
||||||
doc.Load (Path.Combine (XcodeRoot, "Contents", "version.plist"));
|
|
||||||
xcode_version = Version.Parse (doc.SelectSingleNode ("//key[text() = 'CFBundleShortVersionString']/following-sibling::string").InnerText);
|
|
||||||
}
|
|
||||||
return xcode_version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string MlaunchPath {
|
|
||||||
get {
|
|
||||||
return Path.Combine (IOS_DESTDIR, "Library", "Frameworks", "Xamarin.iOS.framework", "Versions", "Current", "bin", "mlaunch");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadConfig ()
|
|
||||||
{
|
|
||||||
ParseConfigFiles ();
|
|
||||||
var src_root = Path.GetDirectoryName (Path.GetFullPath (RootDirectory));
|
|
||||||
MONO_PATH = Path.GetFullPath (Path.Combine (src_root, "external", "mono"));
|
|
||||||
TVOS_MONO_PATH = MONO_PATH;
|
|
||||||
INCLUDE_IOS = make_config.ContainsKey ("INCLUDE_IOS") && !string.IsNullOrEmpty (make_config ["INCLUDE_IOS"]);
|
|
||||||
INCLUDE_TVOS = make_config.ContainsKey ("INCLUDE_TVOS") && !string.IsNullOrEmpty (make_config ["INCLUDE_TVOS"]);
|
|
||||||
JENKINS_RESULTS_DIRECTORY = make_config ["JENKINS_RESULTS_DIRECTORY"];
|
|
||||||
INCLUDE_WATCH = make_config.ContainsKey ("INCLUDE_WATCH") && !string.IsNullOrEmpty (make_config ["INCLUDE_WATCH"]);
|
|
||||||
INCLUDE_MAC = make_config.ContainsKey ("INCLUDE_MAC") && !string.IsNullOrEmpty (make_config ["INCLUDE_MAC"]);
|
|
||||||
MAC_DESTDIR = make_config ["MAC_DESTDIR"];
|
|
||||||
IOS_DESTDIR = make_config ["IOS_DESTDIR"];
|
|
||||||
if (string.IsNullOrEmpty (SdkRoot))
|
|
||||||
SdkRoot = make_config ["XCODE_DEVELOPER_ROOT"];
|
|
||||||
MONO_IOS_SDK_DESTDIR = make_config ["MONO_IOS_SDK_DESTDIR"];
|
|
||||||
MONO_MAC_SDK_DESTDIR = make_config ["MONO_MAC_SDK_DESTDIR"];
|
|
||||||
ENABLE_XAMARIN = make_config.ContainsKey ("ENABLE_XAMARIN") && !string.IsNullOrEmpty (make_config ["ENABLE_XAMARIN"]);
|
|
||||||
DOTNET = make_config ["DOTNET"];
|
|
||||||
}
|
|
||||||
|
|
||||||
int AutoConfigureMac (bool generate_projects)
|
int AutoConfigureMac (bool generate_projects)
|
||||||
{
|
{
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
@ -480,7 +427,7 @@ namespace Xharness
|
||||||
BCLTodayExtensionTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "bcl-test", "templates", "today"));
|
BCLTodayExtensionTemplate = Path.GetFullPath (Path.Combine (RootDirectory, "bcl-test", "templates", "today"));
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary<string, string> make_config = new Dictionary<string, string> ();
|
// Dictionary<string, string> make_config = new Dictionary<string, string> ();
|
||||||
IEnumerable<string> FindConfigFiles (string name)
|
IEnumerable<string> FindConfigFiles (string name)
|
||||||
{
|
{
|
||||||
var dir = Path.GetFullPath (RootDirectory);
|
var dir = Path.GetFullPath (RootDirectory);
|
||||||
|
@ -492,20 +439,24 @@ namespace Xharness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseConfigFiles ()
|
Dictionary<string, string> ParseConfigFiles ()
|
||||||
{
|
{
|
||||||
ParseConfigFiles (FindConfigFiles (useSystemXamarinIOSMac ? "test-system.config" : "test.config"));
|
var configuration = new Dictionary<string, string> ();
|
||||||
ParseConfigFiles (FindConfigFiles ("Make.config.local"));
|
foreach (var file in GetConfigFiles ()) {
|
||||||
ParseConfigFiles (FindConfigFiles ("Make.config"));
|
ParseConfigFile (file, configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseConfigFiles (IEnumerable<string> files)
|
return configuration;
|
||||||
{
|
|
||||||
foreach (var file in files)
|
|
||||||
ParseConfigFile (file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseConfigFile (string file)
|
IEnumerable <string> GetConfigFiles ()
|
||||||
|
{
|
||||||
|
return FindConfigFiles (useSystemXamarinIOSMac ? "test-system.config" : "test.config")
|
||||||
|
.Concat (FindConfigFiles ("Make.config"))
|
||||||
|
.Concat (FindConfigFiles ("Make.config.local"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParseConfigFile (string file, Dictionary<string, string> configuration)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty (file))
|
if (string.IsNullOrEmpty (file))
|
||||||
return;
|
return;
|
||||||
|
@ -514,9 +465,10 @@ namespace Xharness
|
||||||
var eq = line.IndexOf ('=');
|
var eq = line.IndexOf ('=');
|
||||||
if (eq == -1)
|
if (eq == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var key = line.Substring (0, eq);
|
var key = line.Substring (0, eq);
|
||||||
if (!make_config.ContainsKey (key))
|
if (!configuration.ContainsKey (key))
|
||||||
make_config [key] = line.Substring (eq + 1);
|
configuration [key] = line.Substring (eq + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,22 +556,7 @@ namespace Xharness
|
||||||
HarnessLog = new ConsoleLog ();
|
HarnessLog = new ConsoleLog ();
|
||||||
|
|
||||||
foreach (var project in IOSTestProjects) {
|
foreach (var project in IOSTestProjects) {
|
||||||
var runner = new AppRunner (ProcessManager,
|
var runner = CreateAppRunner (project);
|
||||||
new AppBundleInformationParser (),
|
|
||||||
new SimulatorsLoaderFactory (this, ProcessManager),
|
|
||||||
new SimpleListenerFactory (),
|
|
||||||
new DeviceLoaderFactory (this, ProcessManager),
|
|
||||||
new CrashSnapshotReporterFactory (ProcessManager, XcodeRoot, MlaunchPath),
|
|
||||||
new CaptureLogFactory (),
|
|
||||||
new DeviceLogCapturerFactory (ProcessManager, XcodeRoot, MlaunchPath),
|
|
||||||
new TestReporterFactory (),
|
|
||||||
target,
|
|
||||||
this,
|
|
||||||
HarnessLog,
|
|
||||||
new Logs (LogDirectory),
|
|
||||||
project.Path,
|
|
||||||
buildConfiguration);
|
|
||||||
|
|
||||||
using (var install_log = new AppInstallMonitorLog (runner.MainLog)) {
|
using (var install_log = new AppInstallMonitorLog (runner.MainLog)) {
|
||||||
var rv = runner.InstallAsync (install_log.CancellationToken).Result;
|
var rv = runner.InstallAsync (install_log.CancellationToken).Result;
|
||||||
if (!rv.Succeeded)
|
if (!rv.Succeeded)
|
||||||
|
@ -635,22 +572,7 @@ namespace Xharness
|
||||||
HarnessLog = new ConsoleLog ();
|
HarnessLog = new ConsoleLog ();
|
||||||
|
|
||||||
foreach (var project in IOSTestProjects) {
|
foreach (var project in IOSTestProjects) {
|
||||||
var runner = new AppRunner (ProcessManager,
|
var runner = CreateAppRunner (project);
|
||||||
new AppBundleInformationParser (),
|
|
||||||
new SimulatorsLoaderFactory (this, ProcessManager),
|
|
||||||
new SimpleListenerFactory (),
|
|
||||||
new DeviceLoaderFactory (this, ProcessManager),
|
|
||||||
new CrashSnapshotReporterFactory (ProcessManager, XcodeRoot, MlaunchPath),
|
|
||||||
new CaptureLogFactory (),
|
|
||||||
new DeviceLogCapturerFactory (ProcessManager, XcodeRoot, MlaunchPath),
|
|
||||||
new TestReporterFactory (),
|
|
||||||
target,
|
|
||||||
this,
|
|
||||||
HarnessLog,
|
|
||||||
new Logs (LogDirectory),
|
|
||||||
project.Path,
|
|
||||||
buildConfiguration);
|
|
||||||
|
|
||||||
var rv = runner.UninstallAsync ().Result;
|
var rv = runner.UninstallAsync ().Result;
|
||||||
if (!rv.Succeeded)
|
if (!rv.Succeeded)
|
||||||
return rv.ExitCode;
|
return rv.ExitCode;
|
||||||
|
@ -664,22 +586,7 @@ namespace Xharness
|
||||||
HarnessLog = new ConsoleLog ();
|
HarnessLog = new ConsoleLog ();
|
||||||
|
|
||||||
foreach (var project in IOSTestProjects) {
|
foreach (var project in IOSTestProjects) {
|
||||||
var runner = new AppRunner (ProcessManager,
|
var runner = CreateAppRunner (project);
|
||||||
new AppBundleInformationParser (),
|
|
||||||
new SimulatorsLoaderFactory (this, ProcessManager),
|
|
||||||
new SimpleListenerFactory (),
|
|
||||||
new DeviceLoaderFactory (this, ProcessManager),
|
|
||||||
new CrashSnapshotReporterFactory (ProcessManager, XcodeRoot, MlaunchPath),
|
|
||||||
new CaptureLogFactory (),
|
|
||||||
new DeviceLogCapturerFactory (ProcessManager, XcodeRoot, MlaunchPath),
|
|
||||||
new TestReporterFactory (),
|
|
||||||
target,
|
|
||||||
this,
|
|
||||||
HarnessLog,
|
|
||||||
new Logs (LogDirectory),
|
|
||||||
project.Path,
|
|
||||||
buildConfiguration);
|
|
||||||
|
|
||||||
var rv = runner.RunAsync ().Result;
|
var rv = runner.RunAsync ().Result;
|
||||||
if (rv != 0)
|
if (rv != 0)
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -729,7 +636,6 @@ namespace Xharness
|
||||||
|
|
||||||
public int Execute ()
|
public int Execute ()
|
||||||
{
|
{
|
||||||
LoadConfig ();
|
|
||||||
switch (Action) {
|
switch (Action) {
|
||||||
case HarnessAction.Configure:
|
case HarnessAction.Configure:
|
||||||
return Configure ();
|
return Configure ();
|
||||||
|
@ -753,7 +659,7 @@ namespace Xharness
|
||||||
AutoConfigureMac (false);
|
AutoConfigureMac (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var jenkins = new Jenkins.Jenkins (this, ProcessManager, ResultParser);
|
var jenkins = new Jenkins.Jenkins (this, processManager, ResultParser);
|
||||||
return jenkins.Run ();
|
return jenkins.Run ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,9 +713,23 @@ namespace Xharness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<ProcessExecutionResult> ExecuteXcodeCommandAsync (string executable, IList<string> args, ILog log, TimeSpan timeout)
|
private AppRunner CreateAppRunner (TestProject project)
|
||||||
{
|
{
|
||||||
return ProcessManager.ExecuteCommandAsync (Path.Combine (XcodeRoot, "Contents", "Developer", "usr", "bin", executable), args, log, timeout: timeout);
|
return new AppRunner (processManager,
|
||||||
|
new AppBundleInformationParser (),
|
||||||
|
new SimulatorsLoaderFactory (processManager),
|
||||||
|
new SimpleListenerFactory (),
|
||||||
|
new DeviceLoaderFactory (processManager),
|
||||||
|
new CrashSnapshotReporterFactory (processManager),
|
||||||
|
new CaptureLogFactory (),
|
||||||
|
new DeviceLogCapturerFactory (processManager),
|
||||||
|
new TestReporterFactory (),
|
||||||
|
target,
|
||||||
|
this,
|
||||||
|
HarnessLog,
|
||||||
|
new Logs (LogDirectory),
|
||||||
|
project.Path,
|
||||||
|
buildConfiguration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,11 @@ namespace Xharness {
|
||||||
// common interface that contains the basic info needed by the test result to be able to parse the results and
|
// common interface that contains the basic info needed by the test result to be able to parse the results and
|
||||||
// log all the required data.
|
// log all the required data.
|
||||||
public interface IAppRunner {
|
public interface IAppRunner {
|
||||||
|
IProcessManager ProcessManager { get; }
|
||||||
AppBundleInformation AppInformation { get; }
|
AppBundleInformation AppInformation { get; }
|
||||||
BuildToolTask BuildTask { get; }
|
BuildToolTask BuildTask { get; }
|
||||||
TimeSpan GetNewTimeout ();
|
TimeSpan GetNewTimeout ();
|
||||||
double LaunchTimeout { get; }
|
double LaunchTimeout { get; }
|
||||||
IProcessManager ProcessManager { get; }
|
|
||||||
ILogs Logs { get; }
|
ILogs Logs { get; }
|
||||||
ILog MainLog { get; }
|
ILog MainLog { get; }
|
||||||
RunMode RunMode { get; }
|
RunMode RunMode { get; }
|
||||||
|
|
|
@ -103,15 +103,15 @@ namespace Xharness.Jenkins
|
||||||
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
||||||
this.resultParser = resultParser ?? throw new ArgumentNullException (nameof (resultParser));
|
this.resultParser = resultParser ?? throw new ArgumentNullException (nameof (resultParser));
|
||||||
Harness = harness ?? throw new ArgumentNullException (nameof (harness));
|
Harness = harness ?? throw new ArgumentNullException (nameof (harness));
|
||||||
simulators = new Simulators (harness, processManager);
|
simulators = new Simulators (processManager);
|
||||||
devices = new Devices (harness, processManager);
|
devices = new Devices (processManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
Task LoadAsync (ref ILog log, ILoadAsync loadable, string name)
|
Task LoadAsync (ref ILog log, ILoadAsync loadable, string name)
|
||||||
{
|
{
|
||||||
loadable.Harness = Harness;
|
|
||||||
if (log == null)
|
if (log == null)
|
||||||
log = Logs.Create ($"{name}-list-{Helpers.Timestamp}.log", $"{name} Listing");
|
log = Logs.Create ($"{name}-list-{Helpers.Timestamp}.log", $"{name} Listing");
|
||||||
|
|
||||||
log.Description = $"{name} Listing (in progress)";
|
log.Description = $"{name} Listing (in progress)";
|
||||||
|
|
||||||
var capturedLog = log;
|
var capturedLog = log;
|
||||||
|
@ -481,7 +481,7 @@ namespace Xharness.Jenkins
|
||||||
clone.Xml.Save (clone.Path);
|
clone.Xml.Save (clone.Path);
|
||||||
});
|
});
|
||||||
|
|
||||||
var build = new MSBuildTask {
|
var build = new MSBuildTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
TestProject = clone,
|
TestProject = clone,
|
||||||
ProjectConfiguration = configuration,
|
ProjectConfiguration = configuration,
|
||||||
|
@ -530,7 +530,7 @@ namespace Xharness.Jenkins
|
||||||
configurations = new string [] { "Debug" };
|
configurations = new string [] { "Debug" };
|
||||||
foreach (var config in configurations) {
|
foreach (var config in configurations) {
|
||||||
foreach (var pair in ps) {
|
foreach (var pair in ps) {
|
||||||
var derived = new MSBuildTask () {
|
var derived = new MSBuildTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
ProjectConfiguration = config,
|
ProjectConfiguration = config,
|
||||||
ProjectPlatform = "iPhoneSimulator",
|
ProjectPlatform = "iPhoneSimulator",
|
||||||
|
@ -584,7 +584,7 @@ namespace Xharness.Jenkins
|
||||||
|
|
||||||
projectTasks.Clear ();
|
projectTasks.Clear ();
|
||||||
if (!project.SkipiOSVariation) {
|
if (!project.SkipiOSVariation) {
|
||||||
var build64 = new MSBuildTask {
|
var build64 = new MSBuildTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
ProjectConfiguration = "Debug64",
|
ProjectConfiguration = "Debug64",
|
||||||
ProjectPlatform = "iPhone",
|
ProjectPlatform = "iPhone",
|
||||||
|
@ -594,7 +594,7 @@ namespace Xharness.Jenkins
|
||||||
build64.CloneTestProject (project);
|
build64.CloneTestProject (project);
|
||||||
projectTasks.Add (new RunDeviceTask (devices, build64, processManager, devices.Connected64BitIOS.Where (d => d.IsSupported (project))) { Ignored = !IncludeiOS64 });
|
projectTasks.Add (new RunDeviceTask (devices, build64, processManager, devices.Connected64BitIOS.Where (d => d.IsSupported (project))) { Ignored = !IncludeiOS64 });
|
||||||
|
|
||||||
var build32 = new MSBuildTask {
|
var build32 = new MSBuildTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
ProjectConfiguration = project.Name != "dont link" ? "Debug32" : "Release32",
|
ProjectConfiguration = project.Name != "dont link" ? "Debug32" : "Release32",
|
||||||
ProjectPlatform = "iPhone",
|
ProjectPlatform = "iPhone",
|
||||||
|
@ -605,7 +605,7 @@ namespace Xharness.Jenkins
|
||||||
projectTasks.Add (new RunDeviceTask (devices, build32, processManager, devices.Connected32BitIOS.Where (d => d.IsSupported (project))) { Ignored = !IncludeiOS32 });
|
projectTasks.Add (new RunDeviceTask (devices, build32, processManager, devices.Connected32BitIOS.Where (d => d.IsSupported (project))) { Ignored = !IncludeiOS32 });
|
||||||
|
|
||||||
var todayProject = project.AsTodayExtensionProject ();
|
var todayProject = project.AsTodayExtensionProject ();
|
||||||
var buildToday = new MSBuildTask {
|
var buildToday = new MSBuildTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
ProjectConfiguration = "Debug64",
|
ProjectConfiguration = "Debug64",
|
||||||
ProjectPlatform = "iPhone",
|
ProjectPlatform = "iPhone",
|
||||||
|
@ -618,7 +618,7 @@ namespace Xharness.Jenkins
|
||||||
|
|
||||||
if (!project.SkiptvOSVariation) {
|
if (!project.SkiptvOSVariation) {
|
||||||
var tvOSProject = project.AsTvOSProject ();
|
var tvOSProject = project.AsTvOSProject ();
|
||||||
var buildTV = new MSBuildTask {
|
var buildTV = new MSBuildTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
ProjectConfiguration = "Debug",
|
ProjectConfiguration = "Debug",
|
||||||
ProjectPlatform = "iPhone",
|
ProjectPlatform = "iPhone",
|
||||||
|
@ -632,7 +632,7 @@ namespace Xharness.Jenkins
|
||||||
if (!project.SkipwatchOSVariation) {
|
if (!project.SkipwatchOSVariation) {
|
||||||
var watchOSProject = project.AsWatchOSProject ();
|
var watchOSProject = project.AsWatchOSProject ();
|
||||||
if (!project.SkipwatchOS32Variation) {
|
if (!project.SkipwatchOS32Variation) {
|
||||||
var buildWatch32 = new MSBuildTask {
|
var buildWatch32 = new MSBuildTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
ProjectConfiguration = "Debug32",
|
ProjectConfiguration = "Debug32",
|
||||||
ProjectPlatform = "iPhone",
|
ProjectPlatform = "iPhone",
|
||||||
|
@ -644,7 +644,7 @@ namespace Xharness.Jenkins
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!project.SkipwatchOSARM64_32Variation) {
|
if (!project.SkipwatchOSARM64_32Variation) {
|
||||||
var buildWatch64_32 = new MSBuildTask {
|
var buildWatch64_32 = new MSBuildTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
ProjectConfiguration = "Release64_32", // We don't support Debug for ARM64_32 yet.
|
ProjectConfiguration = "Release64_32", // We don't support Debug for ARM64_32 yet.
|
||||||
ProjectPlatform = "iPhone",
|
ProjectPlatform = "iPhone",
|
||||||
|
@ -720,7 +720,7 @@ namespace Xharness.Jenkins
|
||||||
|
|
||||||
void SelectTestsByModifiedFiles (int pull_request)
|
void SelectTestsByModifiedFiles (int pull_request)
|
||||||
{
|
{
|
||||||
var files = GitHub.GetModifiedFiles (Harness, pull_request);
|
var files = GitHub.GetModifiedFiles (processManager, Harness, pull_request);
|
||||||
|
|
||||||
MainLog.WriteLine ("Found {0} modified file(s) in the pull request #{1}.", files.Count (), pull_request);
|
MainLog.WriteLine ("Found {0} modified file(s) in the pull request #{1}.", files.Count (), pull_request);
|
||||||
foreach (var f in files)
|
foreach (var f in files)
|
||||||
|
@ -938,9 +938,9 @@ namespace Xharness.Jenkins
|
||||||
|
|
||||||
//Tasks.AddRange (await CreateRunSimulatorTasksAsync ());
|
//Tasks.AddRange (await CreateRunSimulatorTasksAsync ());
|
||||||
|
|
||||||
var crashReportSnapshotFactory = new CrashSnapshotReporterFactory (processManager, Harness.XcodeRoot, Harness.MlaunchPath);
|
var crashReportSnapshotFactory = new CrashSnapshotReporterFactory (processManager);
|
||||||
|
|
||||||
var buildiOSMSBuild_net461 = new MSBuildTask ()
|
var buildiOSMSBuild_net461 = new MSBuildTask (processManager)
|
||||||
{
|
{
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "..", "msbuild", "tests", "Xamarin.iOS.Tasks.Tests", "Xamarin.iOS.Tasks.Tests.csproj"))),
|
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "..", "msbuild", "tests", "Xamarin.iOS.Tasks.Tests", "Xamarin.iOS.Tasks.Tests.csproj"))),
|
||||||
|
@ -965,7 +965,7 @@ namespace Xharness.Jenkins
|
||||||
};
|
};
|
||||||
Tasks.Add (nunitExecutioniOSMSBuild_net461);
|
Tasks.Add (nunitExecutioniOSMSBuild_net461);
|
||||||
|
|
||||||
var buildiOSMSBuild_netstandard2 = new MSBuildTask () {
|
var buildiOSMSBuild_netstandard2 = new MSBuildTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "..", "msbuild", "tests", "Xamarin.iOS.Tasks.Tests", "Xamarin.iOS.Tasks.Tests.csproj"))),
|
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "..", "msbuild", "tests", "Xamarin.iOS.Tasks.Tests", "Xamarin.iOS.Tasks.Tests.csproj"))),
|
||||||
SpecifyPlatform = false,
|
SpecifyPlatform = false,
|
||||||
|
@ -988,7 +988,7 @@ namespace Xharness.Jenkins
|
||||||
};
|
};
|
||||||
Tasks.Add (nunitExecutioniOSMSBuild_netstandard2);
|
Tasks.Add (nunitExecutioniOSMSBuild_netstandard2);
|
||||||
|
|
||||||
var buildInstallSources = new MSBuildTask ()
|
var buildInstallSources = new MSBuildTask (processManager)
|
||||||
{
|
{
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "..", "tools", "install-source", "InstallSourcesTests", "InstallSourcesTests.csproj"))),
|
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "..", "tools", "install-source", "InstallSourcesTests", "InstallSourcesTests.csproj"))),
|
||||||
|
@ -1039,7 +1039,7 @@ namespace Xharness.Jenkins
|
||||||
throw new NotImplementedException (project.TargetFrameworkFlavors.ToString ());
|
throw new NotImplementedException (project.TargetFrameworkFlavors.ToString ());
|
||||||
}
|
}
|
||||||
foreach (var config in configurations) {
|
foreach (var config in configurations) {
|
||||||
MSBuildTask build = new MSBuildTask ();
|
MSBuildTask build = new MSBuildTask (processManager);
|
||||||
build.Platform = platform;
|
build.Platform = platform;
|
||||||
build.CloneTestProject (project);
|
build.CloneTestProject (project);
|
||||||
build.Jenkins = this;
|
build.Jenkins = this;
|
||||||
|
@ -1082,7 +1082,7 @@ namespace Xharness.Jenkins
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var buildMTouch = new MakeTask ()
|
var buildMTouch = new MakeTask (processManager)
|
||||||
{
|
{
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "mtouch", "mtouch.sln"))),
|
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "mtouch", "mtouch.sln"))),
|
||||||
|
@ -1104,7 +1104,7 @@ namespace Xharness.Jenkins
|
||||||
};
|
};
|
||||||
Tasks.Add (nunitExecutionMTouch);
|
Tasks.Add (nunitExecutionMTouch);
|
||||||
|
|
||||||
var buildGenerator = new MakeTask {
|
var buildGenerator = new MakeTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "..", "src", "generator.sln"))),
|
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "..", "src", "generator.sln"))),
|
||||||
SpecifyPlatform = false,
|
SpecifyPlatform = false,
|
||||||
|
@ -1124,7 +1124,7 @@ namespace Xharness.Jenkins
|
||||||
};
|
};
|
||||||
Tasks.Add (runGenerator);
|
Tasks.Add (runGenerator);
|
||||||
|
|
||||||
var buildDotNetGenerator = new DotNetBuildTask {
|
var buildDotNetGenerator = new DotNetBuildTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "bgen", "bgen-tests.csproj"))),
|
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "bgen", "bgen-tests.csproj"))),
|
||||||
SpecifyPlatform = false,
|
SpecifyPlatform = false,
|
||||||
|
@ -1140,7 +1140,7 @@ namespace Xharness.Jenkins
|
||||||
};
|
};
|
||||||
Tasks.Add (runDotNetGenerator);
|
Tasks.Add (runDotNetGenerator);
|
||||||
|
|
||||||
var run_mmp = new MakeTask
|
var run_mmp = new MakeTask (processManager)
|
||||||
{
|
{
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
Platform = TestPlatform.Mac,
|
Platform = TestPlatform.Mac,
|
||||||
|
@ -1159,7 +1159,7 @@ namespace Xharness.Jenkins
|
||||||
run_mmp.Environment.Add ("BUILD_REVISION", "jenkins"); // This will print "@MonkeyWrench: AddFile: <log path>" lines, which we can use to get the log filenames.
|
run_mmp.Environment.Add ("BUILD_REVISION", "jenkins"); // This will print "@MonkeyWrench: AddFile: <log path>" lines, which we can use to get the log filenames.
|
||||||
Tasks.Add (run_mmp);
|
Tasks.Add (run_mmp);
|
||||||
|
|
||||||
var runMacBindingProject = new MakeTask
|
var runMacBindingProject = new MakeTask (processManager)
|
||||||
{
|
{
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
Platform = TestPlatform.Mac,
|
Platform = TestPlatform.Mac,
|
||||||
|
@ -1171,7 +1171,7 @@ namespace Xharness.Jenkins
|
||||||
};
|
};
|
||||||
Tasks.Add (runMacBindingProject);
|
Tasks.Add (runMacBindingProject);
|
||||||
|
|
||||||
var buildXtroTests = new MakeTask {
|
var buildXtroTests = new MakeTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
Platform = TestPlatform.All,
|
Platform = TestPlatform.All,
|
||||||
TestName = "Xtro",
|
TestName = "Xtro",
|
||||||
|
@ -1189,7 +1189,7 @@ namespace Xharness.Jenkins
|
||||||
};
|
};
|
||||||
Tasks.Add (runXtroReporter);
|
Tasks.Add (runXtroReporter);
|
||||||
|
|
||||||
var buildCecilTests = new MakeTask {
|
var buildCecilTests = new MakeTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
Platform = TestPlatform.All,
|
Platform = TestPlatform.All,
|
||||||
TestName = "Cecil",
|
TestName = "Cecil",
|
||||||
|
@ -1209,7 +1209,7 @@ namespace Xharness.Jenkins
|
||||||
};
|
};
|
||||||
Tasks.Add (runCecilTests);
|
Tasks.Add (runCecilTests);
|
||||||
|
|
||||||
var runDocsTests = new MakeTask {
|
var runDocsTests = new MakeTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
Platform = TestPlatform.All,
|
Platform = TestPlatform.All,
|
||||||
TestName = "Documentation",
|
TestName = "Documentation",
|
||||||
|
@ -1220,7 +1220,7 @@ namespace Xharness.Jenkins
|
||||||
};
|
};
|
||||||
Tasks.Add (runDocsTests);
|
Tasks.Add (runDocsTests);
|
||||||
|
|
||||||
var buildSampleTests = new MSBuildTask {
|
var buildSampleTests = new MSBuildTask (processManager) {
|
||||||
Jenkins = this,
|
Jenkins = this,
|
||||||
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "sampletester", "sampletester.sln"))),
|
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "sampletester", "sampletester.sln"))),
|
||||||
SpecifyPlatform = false,
|
SpecifyPlatform = false,
|
||||||
|
@ -1253,7 +1253,7 @@ namespace Xharness.Jenkins
|
||||||
using (var process = new Process ()) {
|
using (var process = new Process ()) {
|
||||||
process.StartInfo.FileName = Harness.PeriodicCommand;
|
process.StartInfo.FileName = Harness.PeriodicCommand;
|
||||||
process.StartInfo.Arguments = Harness.PeriodicCommandArguments;
|
process.StartInfo.Arguments = Harness.PeriodicCommandArguments;
|
||||||
var rv = await Harness.ProcessManager.RunAsync (process, periodic_loc, timeout: Harness.PeriodicCommandInterval);
|
var rv = await processManager.RunAsync (process, periodic_loc, timeout: Harness.PeriodicCommandInterval);
|
||||||
if (!rv.Succeeded)
|
if (!rv.Succeeded)
|
||||||
periodic_loc.WriteLine ($"Periodic command failed with exit code {rv.ExitCode} (Timed out: {rv.TimedOut})");
|
periodic_loc.WriteLine ($"Periodic command failed with exit code {rv.ExitCode} (Timed out: {rv.TimedOut})");
|
||||||
}
|
}
|
||||||
|
@ -1293,7 +1293,7 @@ namespace Xharness.Jenkins
|
||||||
|
|
||||||
// We can populate and build test-libraries in parallel.
|
// We can populate and build test-libraries in parallel.
|
||||||
var populate = Task.Run (async () => {
|
var populate = Task.Run (async () => {
|
||||||
var simulator = new SimulatorDevice (Harness, processManager);
|
var simulator = new SimulatorDevice (processManager, new TCCDatabase (processManager));
|
||||||
await simulator.KillEverythingAsync (MainLog);
|
await simulator.KillEverythingAsync (MainLog);
|
||||||
await PopulateTasksAsync ();
|
await PopulateTasksAsync ();
|
||||||
populating = false;
|
populating = false;
|
||||||
|
@ -1328,7 +1328,7 @@ namespace Xharness.Jenkins
|
||||||
var sb = new StringBuilder ();
|
var sb = new StringBuilder ();
|
||||||
var callback_log = new CallbackLog ((v) => sb.Append (v));
|
var callback_log = new CallbackLog ((v) => sb.Append (v));
|
||||||
var log = Log.CreateAggregatedLog (callback_log, MainLog);
|
var log = Log.CreateAggregatedLog (callback_log, MainLog);
|
||||||
return Harness.ProcessManager.ExecuteCommandAsync ("make", new [] { "all", $"-j{Environment.ProcessorCount}", "-C", Path.Combine (Harness.RootDirectory, "test-libraries") }, log, TimeSpan.FromMinutes (10)).ContinueWith ((v) => {
|
return processManager.ExecuteCommandAsync ("make", new [] { "all", $"-j{Environment.ProcessorCount}", "-C", Path.Combine (Harness.RootDirectory, "test-libraries") }, log, TimeSpan.FromMinutes (10)).ContinueWith ((v) => {
|
||||||
var per = v.Result;
|
var per = v.Result;
|
||||||
if (!per.Succeeded) {
|
if (!per.Succeeded) {
|
||||||
// Only show the log if something went wrong.
|
// Only show the log if something went wrong.
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using Xharness.Execution;
|
||||||
using Xharness.Logging;
|
using Xharness.Logging;
|
||||||
using Xharness.Utilities;
|
using Xharness.Utilities;
|
||||||
|
|
||||||
|
@ -13,6 +14,10 @@ namespace Xharness.Jenkins.TestTasks
|
||||||
{
|
{
|
||||||
public string SolutionPath;
|
public string SolutionPath;
|
||||||
|
|
||||||
|
protected BuildProjectTask (IProcessManager processManager) : base (processManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public bool RestoreNugets {
|
public bool RestoreNugets {
|
||||||
get {
|
get {
|
||||||
return TestProject.RestoreNugetsInProject || !string.IsNullOrEmpty (SolutionPath);
|
return TestProject.RestoreNugetsInProject || !string.IsNullOrEmpty (SolutionPath);
|
||||||
|
|
|
@ -6,9 +6,15 @@ namespace Xharness.Jenkins.TestTasks
|
||||||
{
|
{
|
||||||
public abstract class BuildToolTask : TestTask
|
public abstract class BuildToolTask : TestTask
|
||||||
{
|
{
|
||||||
|
protected readonly IProcessManager ProcessManager;
|
||||||
|
|
||||||
public bool SpecifyPlatform = true;
|
public bool SpecifyPlatform = true;
|
||||||
public bool SpecifyConfiguration = true;
|
public bool SpecifyConfiguration = true;
|
||||||
public IProcessManager ProcessManager { get; set; } = new ProcessManager ();
|
|
||||||
|
protected BuildToolTask (IProcessManager processManager)
|
||||||
|
{
|
||||||
|
ProcessManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
|
||||||
|
}
|
||||||
|
|
||||||
public override string Mode {
|
public override string Mode {
|
||||||
get { return Platform.ToString (); }
|
get { return Platform.ToString (); }
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using Xharness.Execution;
|
||||||
|
|
||||||
namespace Xharness.Jenkins.TestTasks {
|
namespace Xharness.Jenkins.TestTasks {
|
||||||
class DotNetBuildTask : MSBuildTask {
|
class DotNetBuildTask : MSBuildTask {
|
||||||
|
|
||||||
public DotNetBuildTask ()
|
public DotNetBuildTask (IProcessManager processManager) : base (processManager)
|
||||||
{
|
{
|
||||||
SetDotNetEnvironmentVariables (Environment);
|
SetDotNetEnvironmentVariables (Environment);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using Xharness.Execution;
|
||||||
using Xharness.Logging;
|
using Xharness.Logging;
|
||||||
using Xharness.Utilities;
|
using Xharness.Utilities;
|
||||||
|
|
||||||
|
@ -31,6 +32,10 @@ namespace Xharness.Jenkins.TestTasks
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MSBuildTask (IProcessManager processManager) : base (processManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task ExecuteAsync ()
|
protected override async Task ExecuteAsync ()
|
||||||
{
|
{
|
||||||
using (var resource = await NotifyAndAcquireDesktopResourceAsync ()) {
|
using (var resource = await NotifyAndAcquireDesktopResourceAsync ()) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Xharness.Execution;
|
||||||
using Xharness.Logging;
|
using Xharness.Logging;
|
||||||
|
|
||||||
namespace Xharness.Jenkins.TestTasks
|
namespace Xharness.Jenkins.TestTasks
|
||||||
|
@ -11,6 +12,10 @@ namespace Xharness.Jenkins.TestTasks
|
||||||
public string WorkingDirectory;
|
public string WorkingDirectory;
|
||||||
public TimeSpan Timeout = TimeSpan.FromMinutes (5);
|
public TimeSpan Timeout = TimeSpan.FromMinutes (5);
|
||||||
|
|
||||||
|
public MakeTask (IProcessManager processManager) : base (processManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task ExecuteAsync ()
|
protected override async Task ExecuteAsync ()
|
||||||
{
|
{
|
||||||
using (var resource = await NotifyAndAcquireDesktopResourceAsync ()) {
|
using (var resource = await NotifyAndAcquireDesktopResourceAsync ()) {
|
||||||
|
|
|
@ -11,9 +11,9 @@ namespace Xharness.Jenkins.TestTasks
|
||||||
{
|
{
|
||||||
class RunDeviceTask : RunXITask<IHardwareDevice>
|
class RunDeviceTask : RunXITask<IHardwareDevice>
|
||||||
{
|
{
|
||||||
readonly IProcessManager processManager = new ProcessManager ();
|
|
||||||
readonly IResultParser resultParser = new XmlResultParser ();
|
readonly IResultParser resultParser = new XmlResultParser ();
|
||||||
readonly IDeviceLoader devices;
|
readonly IDeviceLoader devices;
|
||||||
|
|
||||||
AppInstallMonitorLog install_log;
|
AppInstallMonitorLog install_log;
|
||||||
|
|
||||||
public override string ProgressMessage {
|
public override string ProgressMessage {
|
||||||
|
@ -81,14 +81,14 @@ namespace Xharness.Jenkins.TestTasks
|
||||||
CompanionDevice = devices.FindCompanionDevice (Jenkins.DeviceLoadLog, Device);
|
CompanionDevice = devices.FindCompanionDevice (Jenkins.DeviceLoadLog, Device);
|
||||||
Jenkins.MainLog.WriteLine ("Acquired device '{0}' for '{1}'", Device.Name, ProjectFile);
|
Jenkins.MainLog.WriteLine ("Acquired device '{0}' for '{1}'", Device.Name, ProjectFile);
|
||||||
|
|
||||||
runner = new AppRunner (processManager,
|
runner = new AppRunner (ProcessManager,
|
||||||
new AppBundleInformationParser (),
|
new AppBundleInformationParser (),
|
||||||
new SimulatorsLoaderFactory (Harness, processManager),
|
new SimulatorsLoaderFactory (ProcessManager),
|
||||||
new SimpleListenerFactory (),
|
new SimpleListenerFactory (),
|
||||||
new DeviceLoaderFactory (Harness, processManager),
|
new DeviceLoaderFactory (ProcessManager),
|
||||||
new CrashSnapshotReporterFactory (ProcessManager, Harness.XcodeRoot, Harness.MlaunchPath),
|
new CrashSnapshotReporterFactory (ProcessManager),
|
||||||
new CaptureLogFactory (),
|
new CaptureLogFactory (),
|
||||||
new DeviceLogCapturerFactory (processManager, Harness.XcodeRoot, Harness.MlaunchPath),
|
new DeviceLogCapturerFactory (ProcessManager),
|
||||||
new TestReporterFactory (),
|
new TestReporterFactory (),
|
||||||
AppRunnerTarget,
|
AppRunnerTarget,
|
||||||
Harness,
|
Harness,
|
||||||
|
@ -148,14 +148,14 @@ namespace Xharness.Jenkins.TestTasks
|
||||||
// nor will it close & reopen the today app (but launching the main app
|
// nor will it close & reopen the today app (but launching the main app
|
||||||
// will do both of these things, preparing the device for launching the today extension).
|
// will do both of these things, preparing the device for launching the today extension).
|
||||||
|
|
||||||
AppRunner todayRunner = new AppRunner (processManager,
|
AppRunner todayRunner = new AppRunner (ProcessManager,
|
||||||
new AppBundleInformationParser (),
|
new AppBundleInformationParser (),
|
||||||
new SimulatorsLoaderFactory (Harness, processManager),
|
new SimulatorsLoaderFactory (ProcessManager),
|
||||||
new SimpleListenerFactory (),
|
new SimpleListenerFactory (),
|
||||||
new DeviceLoaderFactory (Harness, processManager),
|
new DeviceLoaderFactory (ProcessManager),
|
||||||
new CrashSnapshotReporterFactory (ProcessManager, Harness.XcodeRoot, Harness.MlaunchPath),
|
new CrashSnapshotReporterFactory (ProcessManager),
|
||||||
new CaptureLogFactory (),
|
new CaptureLogFactory (),
|
||||||
new DeviceLogCapturerFactory (processManager, Harness.XcodeRoot, Harness.MlaunchPath),
|
new DeviceLogCapturerFactory (ProcessManager),
|
||||||
new TestReporterFactory (),
|
new TestReporterFactory (),
|
||||||
AppRunnerTarget,
|
AppRunnerTarget,
|
||||||
Harness,
|
Harness,
|
||||||
|
|
|
@ -13,7 +13,6 @@ namespace Xharness.Jenkins.TestTasks
|
||||||
{
|
{
|
||||||
class RunSimulatorTask : RunXITask<ISimulatorDevice>
|
class RunSimulatorTask : RunXITask<ISimulatorDevice>
|
||||||
{
|
{
|
||||||
readonly IProcessManager processManager = new ProcessManager ();
|
|
||||||
readonly ISimulatorsLoader simulators;
|
readonly ISimulatorsLoader simulators;
|
||||||
public IAcquiredResource AcquiredResource;
|
public IAcquiredResource AcquiredResource;
|
||||||
|
|
||||||
|
@ -77,14 +76,14 @@ namespace Xharness.Jenkins.TestTasks
|
||||||
await FindSimulatorAsync ();
|
await FindSimulatorAsync ();
|
||||||
|
|
||||||
var clean_state = false;//Platform == TestPlatform.watchOS;
|
var clean_state = false;//Platform == TestPlatform.watchOS;
|
||||||
runner = new AppRunner (processManager,
|
runner = new AppRunner (ProcessManager,
|
||||||
new AppBundleInformationParser (),
|
new AppBundleInformationParser (),
|
||||||
new SimulatorsLoaderFactory (Harness, processManager),
|
new SimulatorsLoaderFactory (ProcessManager),
|
||||||
new SimpleListenerFactory (),
|
new SimpleListenerFactory (),
|
||||||
new DeviceLoaderFactory (Harness, processManager),
|
new DeviceLoaderFactory (ProcessManager),
|
||||||
new CrashSnapshotReporterFactory (ProcessManager, Harness.XcodeRoot, Harness.MlaunchPath),
|
new CrashSnapshotReporterFactory (ProcessManager),
|
||||||
new CaptureLogFactory (),
|
new CaptureLogFactory (),
|
||||||
new DeviceLogCapturerFactory (processManager, Harness.XcodeRoot, Harness.MlaunchPath),
|
new DeviceLogCapturerFactory (ProcessManager),
|
||||||
new TestReporterFactory (),
|
new TestReporterFactory (),
|
||||||
AppRunnerTarget,
|
AppRunnerTarget,
|
||||||
Harness,
|
Harness,
|
||||||
|
|
|
@ -105,7 +105,7 @@ namespace Xharness {
|
||||||
// XS sets this, which breaks pretty much everything if it doesn't match what was passed to --sdkroot.
|
// XS sets this, which breaks pretty much everything if it doesn't match what was passed to --sdkroot.
|
||||||
Environment.SetEnvironmentVariable ("XCODE_DEVELOPER_DIR_PATH", null);
|
Environment.SetEnvironmentVariable ("XCODE_DEVELOPER_DIR_PATH", null);
|
||||||
|
|
||||||
var harness = new Harness (new ProcessManager(), new XmlResultParser (), action, configuration);
|
var harness = new Harness (new XmlResultParser (), action, configuration);
|
||||||
|
|
||||||
return harness.Execute ();
|
return harness.Execute ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace Xharness.Tests.Execution.Tests {
|
||||||
stdoutLog = new LogFile ("my stdout log", stdoutLogPath);
|
stdoutLog = new LogFile ("my stdout log", stdoutLogPath);
|
||||||
stderrLog = new LogFile ("my stderr log", stderrLogPath);
|
stderrLog = new LogFile ("my stderr log", stderrLogPath);
|
||||||
dummyProcess = Path.Combine (Path.GetDirectoryName (GetType ().Assembly.Location), "DummyTestProcess.exe");
|
dummyProcess = Path.Combine (Path.GetDirectoryName (GetType ().Assembly.Location), "DummyTestProcess.exe");
|
||||||
manager = new ProcessManager ();
|
manager = new ProcessManager ("/path/to/xcode", "/path/to/mlaunch");
|
||||||
testProcess = new Process ();
|
testProcess = new Process ();
|
||||||
testProcess.StartInfo.FileName = "mono";
|
testProcess.StartInfo.FileName = "mono";
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ namespace Xharness.Tests.Execution.Tests {
|
||||||
{
|
{
|
||||||
var source = new CancellationTokenSource ();
|
var source = new CancellationTokenSource ();
|
||||||
testProcess.StartInfo.Arguments = $"{dummyProcess} --exit-code={resultCode} --timeout={timeoutCount} --stdout=\"{stdoutMessage}\" --stderr=\"{stderrMessage}\"";
|
testProcess.StartInfo.Arguments = $"{dummyProcess} --exit-code={resultCode} --timeout={timeoutCount} --stdout=\"{stdoutMessage}\" --stderr=\"{stderrMessage}\"";
|
||||||
var result = await manager.RunAsync (testProcess, executionLog, source.Token);
|
var result = await manager.RunAsync (testProcess, executionLog, executionLog, executionLog, cancellationToken: source.Token);
|
||||||
if (!timeout)
|
if (!timeout)
|
||||||
Assert.AreEqual (resultCode, result.ExitCode, "exit code");
|
Assert.AreEqual (resultCode, result.ExitCode, "exit code");
|
||||||
Assert.AreEqual (success, result.Succeeded, "success");
|
Assert.AreEqual (success, result.Succeeded, "success");
|
||||||
|
|
|
@ -20,16 +20,14 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
Devices devices;
|
Devices devices;
|
||||||
string mlaunchPath;
|
string mlaunchPath;
|
||||||
string sdkPath;
|
string sdkPath;
|
||||||
Mock<IHarness> harness;
|
|
||||||
Mock<IProcessManager> processManager;
|
Mock<IProcessManager> processManager;
|
||||||
Mock<ILog> executionLog;
|
Mock<ILog> executionLog;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp ()
|
public void SetUp ()
|
||||||
{
|
{
|
||||||
harness = new Mock<IHarness> ();
|
|
||||||
processManager = new Mock<IProcessManager> ();
|
processManager = new Mock<IProcessManager> ();
|
||||||
devices = new Devices (harness.Object, processManager.Object);
|
devices = new Devices (processManager.Object);
|
||||||
executionLog = new Mock<ILog> ();
|
executionLog = new Mock<ILog> ();
|
||||||
mlaunchPath = "/usr/bin/mlaunch"; // any will be ok, is mocked
|
mlaunchPath = "/usr/bin/mlaunch"; // any will be ok, is mocked
|
||||||
sdkPath = "/Applications/Xcode.app";
|
sdkPath = "/Applications/Xcode.app";
|
||||||
|
@ -38,7 +36,6 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
[TearDown]
|
[TearDown]
|
||||||
public void TearDown ()
|
public void TearDown ()
|
||||||
{
|
{
|
||||||
harness = null;
|
|
||||||
processManager = null;
|
processManager = null;
|
||||||
executionLog = null;
|
executionLog = null;
|
||||||
devices = null;
|
devices = null;
|
||||||
|
@ -50,10 +47,7 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
{
|
{
|
||||||
string processPath = null;
|
string processPath = null;
|
||||||
MlaunchArguments passedArguments = null;
|
MlaunchArguments passedArguments = null;
|
||||||
// set the expectations of the mocks to get an error when
|
|
||||||
// executing the process
|
|
||||||
harness.Setup (h => h.MlaunchPath).Returns (mlaunchPath);
|
|
||||||
harness.Setup (h => h.XcodeRoot).Returns (sdkPath);
|
|
||||||
// moq It.Is is not working as nicelly as we would like it, we capture data and use asserts
|
// moq It.Is is not working as nicelly as we would like it, we capture data and use asserts
|
||||||
processManager.Setup (p => p.RunAsync (It.IsAny<Process> (), It.IsAny<MlaunchArguments> (), It.IsAny<ILog> (), It.IsAny<TimeSpan?> (), It.IsAny<Dictionary<string, string>>(), It.IsAny<CancellationToken?> (), It.IsAny<bool?> ()))
|
processManager.Setup (p => p.RunAsync (It.IsAny<Process> (), It.IsAny<MlaunchArguments> (), It.IsAny<ILog> (), It.IsAny<TimeSpan?> (), It.IsAny<Dictionary<string, string>>(), It.IsAny<CancellationToken?> (), It.IsAny<bool?> ()))
|
||||||
.Returns<Process, MlaunchArguments, ILog, TimeSpan?, Dictionary< string, string>, CancellationToken?, bool?> ((p, args, log, t, env, token, d) => {
|
.Returns<Process, MlaunchArguments, ILog, TimeSpan?, Dictionary< string, string>, CancellationToken?, bool?> ((p, args, log, t, env, token, d) => {
|
||||||
|
@ -87,10 +81,7 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
{
|
{
|
||||||
string processPath = null;
|
string processPath = null;
|
||||||
MlaunchArguments passedArguments = null;
|
MlaunchArguments passedArguments = null;
|
||||||
// set the expectations of the mocks to get an error when
|
|
||||||
// executing the process
|
|
||||||
harness.Setup (h => h.MlaunchPath).Returns (mlaunchPath);
|
|
||||||
harness.Setup (h => h.XcodeRoot).Returns (sdkPath);
|
|
||||||
// moq It.Is is not working as nicelly as we would like it, we capture data and use asserts
|
// moq It.Is is not working as nicelly as we would like it, we capture data and use asserts
|
||||||
processManager.Setup (p => p.RunAsync (It.IsAny<Process> (), It.IsAny<MlaunchArguments> (), It.IsAny<ILog> (), It.IsAny<TimeSpan?> (), It.IsAny<Dictionary<string, string>> (), It.IsAny<CancellationToken?> (), It.IsAny<bool?> ()))
|
processManager.Setup (p => p.RunAsync (It.IsAny<Process> (), It.IsAny<MlaunchArguments> (), It.IsAny<ILog> (), It.IsAny<TimeSpan?> (), It.IsAny<Dictionary<string, string>> (), It.IsAny<CancellationToken?> (), It.IsAny<bool?> ()))
|
||||||
.Returns<Process, MlaunchArguments, ILog, TimeSpan?, Dictionary<string, string>, CancellationToken?, bool?> ((p, args, log, t, env, token, d) => {
|
.Returns<Process, MlaunchArguments, ILog, TimeSpan?, Dictionary<string, string>, CancellationToken?, bool?> ((p, args, log, t, env, token, d) => {
|
||||||
|
|
|
@ -14,7 +14,6 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
|
|
||||||
Mock<ILog> executionLog;
|
Mock<ILog> executionLog;
|
||||||
Mock<IProcessManager> processManager;
|
Mock<IProcessManager> processManager;
|
||||||
Mock<IHarness> harness;
|
|
||||||
SimulatorDevice simulator;
|
SimulatorDevice simulator;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
|
@ -22,8 +21,7 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
{
|
{
|
||||||
executionLog = new Mock<ILog> ();
|
executionLog = new Mock<ILog> ();
|
||||||
processManager = new Mock<IProcessManager> ();
|
processManager = new Mock<IProcessManager> ();
|
||||||
harness = new Mock<IHarness> ();
|
simulator = new SimulatorDevice (processManager.Object, new TCCDatabase (processManager.Object)) {
|
||||||
simulator = new SimulatorDevice (harness.Object, processManager.Object) {
|
|
||||||
UDID = Guid.NewGuid ().ToString ()
|
UDID = Guid.NewGuid ().ToString ()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -57,10 +55,10 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
{
|
{
|
||||||
// just call and verify the correct args are pass
|
// just call and verify the correct args are pass
|
||||||
await simulator.EraseAsync (executionLog.Object);
|
await simulator.EraseAsync (executionLog.Object);
|
||||||
harness.Verify (h => h.ExecuteXcodeCommandAsync (It.Is<string> (s => s == "simctl"), It.Is<string []> (args => args.Where (a => a == simulator.UDID || a == "shutdown").Count () == 2), It.IsAny<ILog> (), It.IsAny<TimeSpan> ()));
|
processManager.Verify (h => h.ExecuteXcodeCommandAsync (It.Is<string> (s => s == "simctl"), It.Is<string []> (args => args.Where (a => a == simulator.UDID || a == "shutdown").Count () == 2), It.IsAny<ILog> (), It.IsAny<TimeSpan> ()));
|
||||||
harness.Verify (h => h.ExecuteXcodeCommandAsync (It.Is<string> (s => s == "simctl"), It.Is<string []> (args => args.Where (a => a == simulator.UDID || a == "erase").Count () == 2), It.IsAny<ILog> (), It.IsAny<TimeSpan> ()));
|
processManager.Verify (h => h.ExecuteXcodeCommandAsync (It.Is<string> (s => s == "simctl"), It.Is<string []> (args => args.Where (a => a == simulator.UDID || a == "erase").Count () == 2), It.IsAny<ILog> (), It.IsAny<TimeSpan> ()));
|
||||||
harness.Verify (h => h.ExecuteXcodeCommandAsync (It.Is<string> (s => s == "simctl"), It.Is<string []> (args => args.Where (a => a == simulator.UDID || a == "boot").Count () == 2), It.IsAny<ILog> (), It.IsAny<TimeSpan> ()));
|
processManager.Verify (h => h.ExecuteXcodeCommandAsync (It.Is<string> (s => s == "simctl"), It.Is<string []> (args => args.Where (a => a == simulator.UDID || a == "boot").Count () == 2), It.IsAny<ILog> (), It.IsAny<TimeSpan> ()));
|
||||||
harness.Verify (h => h.ExecuteXcodeCommandAsync (It.Is<string> (s => s == "simctl"), It.Is<string []> (args => args.Where (a => a == simulator.UDID || a == "shutdown").Count () == 2), It.IsAny<ILog> (), It.IsAny<TimeSpan> ()));
|
processManager.Verify (h => h.ExecuteXcodeCommandAsync (It.Is<string> (s => s == "simctl"), It.Is<string []> (args => args.Where (a => a == simulator.UDID || a == "shutdown").Count () == 2), It.IsAny<ILog> (), It.IsAny<TimeSpan> ()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +67,7 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
{
|
{
|
||||||
await simulator.ShutdownAsync (executionLog.Object);
|
await simulator.ShutdownAsync (executionLog.Object);
|
||||||
// just call and verify the correct args are pass
|
// just call and verify the correct args are pass
|
||||||
harness.Verify (h => h.ExecuteXcodeCommandAsync (It.Is<string> (s => s == "simctl"), It.Is<string []> (args => args.Where (a => a == simulator.UDID || a == "shutdown").Count () == 2), It.IsAny<ILog> (), It.IsAny<TimeSpan> ()));
|
processManager.Verify (h => h.ExecuteXcodeCommandAsync (It.Is<string> (s => s == "simctl"), It.Is<string []> (args => args.Where (a => a == simulator.UDID || a == "shutdown").Count () == 2), It.IsAny<ILog> (), It.IsAny<TimeSpan> ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -81,7 +79,7 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
return args.Where (a => toKill.Contains (a)).Count () == toKill.Count;
|
return args.Where (a => toKill.Contains (a)).Count () == toKill.Count;
|
||||||
};
|
};
|
||||||
|
|
||||||
var simulator = new SimulatorDevice (Mock.Of<IHarness> (), processManager.Object);
|
var simulator = new SimulatorDevice (processManager.Object, new TCCDatabase (processManager.Object));
|
||||||
await simulator.KillEverythingAsync (executionLog.Object);
|
await simulator.KillEverythingAsync (executionLog.Object);
|
||||||
|
|
||||||
// verify that all the diff process have been killed making sure args are correct
|
// verify that all the diff process have been killed making sure args are correct
|
||||||
|
|
|
@ -19,7 +19,6 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
|
|
||||||
string mlaunchPath;
|
string mlaunchPath;
|
||||||
string sdkPath;
|
string sdkPath;
|
||||||
Mock<IHarness> harness;
|
|
||||||
Mock<ILog> executionLog;
|
Mock<ILog> executionLog;
|
||||||
Mock<IProcessManager> processManager;
|
Mock<IProcessManager> processManager;
|
||||||
Simulators simulators;
|
Simulators simulators;
|
||||||
|
@ -29,10 +28,9 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
{
|
{
|
||||||
mlaunchPath = "/usr/bin/mlaunch"; // any will be ok, is mocked
|
mlaunchPath = "/usr/bin/mlaunch"; // any will be ok, is mocked
|
||||||
sdkPath = "/Applications/Xcode.app";
|
sdkPath = "/Applications/Xcode.app";
|
||||||
harness = new Mock<IHarness> ();
|
|
||||||
executionLog = new Mock<ILog> ();
|
executionLog = new Mock<ILog> ();
|
||||||
processManager = new Mock<IProcessManager> ();
|
processManager = new Mock<IProcessManager> ();
|
||||||
simulators = new Simulators (harness.Object, processManager.Object);
|
simulators = new Simulators (processManager.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TearDown]
|
[TearDown]
|
||||||
|
@ -49,10 +47,7 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
{
|
{
|
||||||
string processPath = null;
|
string processPath = null;
|
||||||
MlaunchArguments passedArguments = null;
|
MlaunchArguments passedArguments = null;
|
||||||
// set the expectations of the mocks to get an error when
|
|
||||||
// executing the process
|
|
||||||
harness.Setup (h => h.MlaunchPath).Returns (mlaunchPath);
|
|
||||||
harness.Setup (h => h.XcodeRoot).Returns (sdkPath);
|
|
||||||
// moq It.Is is not working as nicelly as we would like it, we capture data and use asserts
|
// moq It.Is is not working as nicelly as we would like it, we capture data and use asserts
|
||||||
processManager.Setup (p => p.RunAsync (It.IsAny<Process> (), It.IsAny<MlaunchArguments> (), It.IsAny<ILog> (), It.IsAny<TimeSpan?> (), It.IsAny<Dictionary<string, string>> (), It.IsAny<CancellationToken?> (), It.IsAny<bool?> ()))
|
processManager.Setup (p => p.RunAsync (It.IsAny<Process> (), It.IsAny<MlaunchArguments> (), It.IsAny<ILog> (), It.IsAny<TimeSpan?> (), It.IsAny<Dictionary<string, string>> (), It.IsAny<CancellationToken?> (), It.IsAny<bool?> ()))
|
||||||
.Returns<Process, MlaunchArguments, ILog, TimeSpan?, Dictionary<string, string>, CancellationToken?, bool?> ((p, args, log, t, env, token, d) => {
|
.Returns<Process, MlaunchArguments, ILog, TimeSpan?, Dictionary<string, string>, CancellationToken?, bool?> ((p, args, log, t, env, token, d) => {
|
||||||
|
@ -97,10 +92,7 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
{
|
{
|
||||||
string processPath = null;
|
string processPath = null;
|
||||||
MlaunchArguments passedArguments = null;
|
MlaunchArguments passedArguments = null;
|
||||||
// set the expectations of the mocks to get an error when
|
|
||||||
// executing the process
|
|
||||||
harness.Setup (h => h.MlaunchPath).Returns (mlaunchPath);
|
|
||||||
harness.Setup (h => h.XcodeRoot).Returns (sdkPath);
|
|
||||||
// moq It.Is is not working as nicelly as we would like it, we capture data and use asserts
|
// moq It.Is is not working as nicelly as we would like it, we capture data and use asserts
|
||||||
processManager.Setup (p => p.RunAsync (It.IsAny<Process> (), It.IsAny<MlaunchArguments> (), It.IsAny<ILog> (), It.IsAny<TimeSpan?> (), It.IsAny<Dictionary<string, string>> (), It.IsAny<CancellationToken?> (), It.IsAny<bool?> ()))
|
processManager.Setup (p => p.RunAsync (It.IsAny<Process> (), It.IsAny<MlaunchArguments> (), It.IsAny<ILog> (), It.IsAny<TimeSpan?> (), It.IsAny<Dictionary<string, string>> (), It.IsAny<CancellationToken?> (), It.IsAny<bool?> ()))
|
||||||
.Returns<Process, MlaunchArguments, ILog, TimeSpan?, Dictionary<string, string>, CancellationToken?, bool?> ((p, args, log, t, env, token, d) => {
|
.Returns<Process, MlaunchArguments, ILog, TimeSpan?, Dictionary<string, string>, CancellationToken?, bool?> ((p, args, log, t, env, token, d) => {
|
||||||
|
@ -141,11 +133,8 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
{
|
{
|
||||||
string processPath = null;
|
string processPath = null;
|
||||||
MlaunchArguments passedArguments = null;
|
MlaunchArguments passedArguments = null;
|
||||||
// set the expectations of the mocks to get an error when
|
|
||||||
// executing the process
|
processManager
|
||||||
harness.Setup (h => h.MlaunchPath).Returns (mlaunchPath);
|
|
||||||
harness.Setup (h => h.XcodeRoot).Returns (sdkPath);
|
|
||||||
harness
|
|
||||||
.Setup (h => h.ExecuteXcodeCommandAsync ("simctl", It.Is<string []> (args => args[0] == "create"), executionLog.Object, TimeSpan.FromMinutes (1)))
|
.Setup (h => h.ExecuteXcodeCommandAsync ("simctl", It.Is<string []> (args => args[0] == "create"), executionLog.Object, TimeSpan.FromMinutes (1)))
|
||||||
.ReturnsAsync (new ProcessExecutionResult () { ExitCode = 0 });
|
.ReturnsAsync (new ProcessExecutionResult () { ExitCode = 0 });
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -25,9 +24,7 @@ namespace Xharness.Tests.Hardware.Tests {
|
||||||
public void SetUp ()
|
public void SetUp ()
|
||||||
{
|
{
|
||||||
processManager = new Mock<IProcessManager> ();
|
processManager = new Mock<IProcessManager> ();
|
||||||
database = new TCCDatabase {
|
database = new TCCDatabase (processManager.Object);
|
||||||
ProcessManager = processManager.Object,
|
|
||||||
};
|
|
||||||
executionLog = new Mock<ILog> ();
|
executionLog = new Mock<ILog> ();
|
||||||
simRuntime = "com.apple.CoreSimulator.SimRuntime.iOS-12-1";
|
simRuntime = "com.apple.CoreSimulator.SimRuntime.iOS-12-1";
|
||||||
dataPath = "/path/to/my/data";
|
dataPath = "/path/to/my/data";
|
||||||
|
|
|
@ -218,9 +218,7 @@ namespace Xharness.Tests {
|
||||||
[Test]
|
[Test]
|
||||||
public async Task InstallOnDeviceTest ()
|
public async Task InstallOnDeviceTest ()
|
||||||
{
|
{
|
||||||
var harness = Mock.Of<IHarness> (x => x.XcodeRoot == "/path/to/xcode"
|
var harness = Mock.Of<IHarness> (x => x.Verbosity == 2);
|
||||||
&& x.MlaunchPath == "/path/to/mlaunch"
|
|
||||||
&& x.Verbosity == 2);
|
|
||||||
|
|
||||||
var processResult = new ProcessExecutionResult () { ExitCode = 1, TimedOut = false };
|
var processResult = new ProcessExecutionResult () { ExitCode = 1, TimedOut = false };
|
||||||
processManager.SetReturnsDefault (Task.FromResult (processResult));
|
processManager.SetReturnsDefault (Task.FromResult (processResult));
|
||||||
|
@ -250,12 +248,9 @@ namespace Xharness.Tests {
|
||||||
// Verify
|
// Verify
|
||||||
Assert.AreEqual (1, result.ExitCode);
|
Assert.AreEqual (1, result.ExitCode);
|
||||||
|
|
||||||
var expectedArgs = $"--sdkroot /path/to/xcode -v -v -v " +
|
var expectedArgs = $"-v -v -v --installdev {StringUtils.FormatArguments (appPath)} --devname \"Test iPad\"";
|
||||||
$"--installdev {StringUtils.FormatArguments (appPath)} " +
|
|
||||||
$"--devname \"Test iPad\"";
|
|
||||||
|
|
||||||
processManager.Verify (x => x.ExecuteCommandAsync (
|
processManager.Verify (x => x.ExecuteCommandAsync (
|
||||||
"/path/to/mlaunch",
|
|
||||||
It.Is<MlaunchArguments> (args => args.AsCommandLine() == expectedArgs),
|
It.Is<MlaunchArguments> (args => args.AsCommandLine() == expectedArgs),
|
||||||
mainLog.Object,
|
mainLog.Object,
|
||||||
TimeSpan.FromHours (1),
|
TimeSpan.FromHours (1),
|
||||||
|
@ -266,9 +261,7 @@ namespace Xharness.Tests {
|
||||||
[Test]
|
[Test]
|
||||||
public async Task UninstallFromDeviceTest ()
|
public async Task UninstallFromDeviceTest ()
|
||||||
{
|
{
|
||||||
var harness = Mock.Of<IHarness> (x => x.XcodeRoot == "/path/to/xcode"
|
var harness = Mock.Of<IHarness> (x => x.Verbosity == 1);
|
||||||
&& x.MlaunchPath == "/path/to/mlaunch"
|
|
||||||
&& x.Verbosity == 1);
|
|
||||||
|
|
||||||
var processResult = new ProcessExecutionResult () { ExitCode = 3, TimedOut = false };
|
var processResult = new ProcessExecutionResult () { ExitCode = 3, TimedOut = false };
|
||||||
processManager.SetReturnsDefault (Task.FromResult (processResult));
|
processManager.SetReturnsDefault (Task.FromResult (processResult));
|
||||||
|
@ -297,12 +290,9 @@ namespace Xharness.Tests {
|
||||||
// Verify
|
// Verify
|
||||||
Assert.AreEqual (3, result.ExitCode);
|
Assert.AreEqual (3, result.ExitCode);
|
||||||
|
|
||||||
var expectedArgs = $"--sdkroot /path/to/xcode -v -v " +
|
var expectedArgs = $"-v -v --uninstalldevbundleid {StringUtils.FormatArguments (appName)} --devname \"Test iPad\"";
|
||||||
$"--uninstalldevbundleid {StringUtils.FormatArguments (appName)} " +
|
|
||||||
$"--devname \"Test iPad\"";
|
|
||||||
|
|
||||||
processManager.Verify (x => x.ExecuteCommandAsync (
|
processManager.Verify (x => x.ExecuteCommandAsync (
|
||||||
"/path/to/mlaunch",
|
|
||||||
It.Is<MlaunchArguments> (args => args.AsCommandLine() == expectedArgs),
|
It.Is<MlaunchArguments> (args => args.AsCommandLine() == expectedArgs),
|
||||||
mainLog.Object,
|
mainLog.Object,
|
||||||
TimeSpan.FromMinutes (1),
|
TimeSpan.FromMinutes (1),
|
||||||
|
@ -461,7 +451,6 @@ namespace Xharness.Tests {
|
||||||
|
|
||||||
processManager
|
processManager
|
||||||
.Setup (x => x.ExecuteCommandAsync (
|
.Setup (x => x.ExecuteCommandAsync (
|
||||||
mlaunchPath,
|
|
||||||
It.Is<MlaunchArguments> (args => args.AsCommandLine() == expectedArgs),
|
It.Is<MlaunchArguments> (args => args.AsCommandLine() == expectedArgs),
|
||||||
mainLog.Object,
|
mainLog.Object,
|
||||||
TimeSpan.FromMinutes (harness.Timeout * 2),
|
TimeSpan.FromMinutes (harness.Timeout * 2),
|
||||||
|
@ -612,7 +601,7 @@ namespace Xharness.Tests {
|
||||||
ips.Append (ipAddresses [i].ToString ());
|
ips.Append (ipAddresses [i].ToString ());
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedArgs = $"--sdkroot {StringUtils.FormatArguments (xcodePath)} -v -v -argument=-connection-mode -argument=none " +
|
var expectedArgs = $"-v -v -argument=-connection-mode -argument=none " +
|
||||||
$"-argument=-app-arg:-autostart -setenv=NUNIT_AUTOSTART=true -argument=-app-arg:-autoexit " +
|
$"-argument=-app-arg:-autostart -setenv=NUNIT_AUTOSTART=true -argument=-app-arg:-autoexit " +
|
||||||
$"-setenv=NUNIT_AUTOEXIT=true -argument=-app-arg:-enablenetwork -setenv=NUNIT_ENABLE_NETWORK=true " +
|
$"-setenv=NUNIT_AUTOEXIT=true -argument=-app-arg:-enablenetwork -setenv=NUNIT_ENABLE_NETWORK=true " +
|
||||||
$"-setenv=DISABLE_SYSTEM_PERMISSION_TESTS=1 -argument=-app-arg:-hostname:{ips} -setenv=NUNIT_HOSTNAME={ips} " +
|
$"-setenv=DISABLE_SYSTEM_PERMISSION_TESTS=1 -argument=-app-arg:-hostname:{ips} -setenv=NUNIT_HOSTNAME={ips} " +
|
||||||
|
@ -622,7 +611,6 @@ namespace Xharness.Tests {
|
||||||
|
|
||||||
processManager
|
processManager
|
||||||
.Setup (x => x.ExecuteCommandAsync (
|
.Setup (x => x.ExecuteCommandAsync (
|
||||||
mlaunchPath,
|
|
||||||
It.Is<MlaunchArguments> (args => args.AsCommandLine () == expectedArgs),
|
It.Is<MlaunchArguments> (args => args.AsCommandLine () == expectedArgs),
|
||||||
It.IsAny<ILog> (),
|
It.IsAny<ILog> (),
|
||||||
TimeSpan.FromMinutes (harness.Timeout * 2),
|
TimeSpan.FromMinutes (harness.Timeout * 2),
|
||||||
|
@ -633,18 +621,18 @@ namespace Xharness.Tests {
|
||||||
var xmlResultFile = Path.ChangeExtension (testResultFilePath, "xml");
|
var xmlResultFile = Path.ChangeExtension (testResultFilePath, "xml");
|
||||||
var testReporterFactory = new Mock<ITestReporterFactory> ();
|
var testReporterFactory = new Mock<ITestReporterFactory> ();
|
||||||
var testReporter = new Mock<ITestReporter> ();
|
var testReporter = new Mock<ITestReporter> ();
|
||||||
testReporterFactory.Setup (f => f.Create (
|
testReporterFactory
|
||||||
|
.Setup (f => f.Create (
|
||||||
It.IsAny<IAppRunner> (),
|
It.IsAny<IAppRunner> (),
|
||||||
It.IsAny<string> (),
|
"Test iPad",
|
||||||
It.IsAny<ISimpleListener> (),
|
It.IsAny<ISimpleListener> (),
|
||||||
It.IsAny<ILog> (),
|
mainLog.Object,
|
||||||
It.IsAny<ICrashSnapshotReporter> (),
|
snapshotReporter.Object,
|
||||||
It.IsAny<IResultParser> ())).Returns (testReporter.Object);
|
It.IsAny<IResultParser> ()))
|
||||||
|
.Returns (testReporter.Object);
|
||||||
testReporter.Setup (r => r.Timeout).Returns (TimeSpan.FromMinutes (harness.Timeout * 2));
|
testReporter.Setup (r => r.Timeout).Returns (TimeSpan.FromMinutes (harness.Timeout * 2));
|
||||||
testReporter.Setup (r => r.TimeoutWatch).Returns (new System.Diagnostics.Stopwatch ());
|
testReporter.Setup (r => r.TimeoutWatch).Returns (new System.Diagnostics.Stopwatch ());
|
||||||
testReporter.Setup (r => r.ParseResult ()).Returns (() => {
|
testReporter.Setup (r => r.ParseResult ()).Returns (() => Task.FromResult<(TestExecutingResult, string)> ((TestExecutingResult.Succeeded, null)));
|
||||||
return Task.FromResult<(TestExecutingResult, string)> ((TestExecutingResult.Succeeded, null));
|
|
||||||
});
|
|
||||||
testReporter.Setup (r => r.Success).Returns (true);
|
testReporter.Setup (r => r.Success).Returns (true);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
@ -728,7 +716,7 @@ namespace Xharness.Tests {
|
||||||
ips.Append (ipAddresses [i].ToString ());
|
ips.Append (ipAddresses [i].ToString ());
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedArgs = $"--sdkroot {StringUtils.FormatArguments (xcodePath)} -v -v -argument=-connection-mode -argument=none " +
|
var expectedArgs = $"-v -v -argument=-connection-mode -argument=none " +
|
||||||
$"-argument=-app-arg:-autostart -setenv=NUNIT_AUTOSTART=true -argument=-app-arg:-autoexit " +
|
$"-argument=-app-arg:-autostart -setenv=NUNIT_AUTOSTART=true -argument=-app-arg:-autoexit " +
|
||||||
$"-setenv=NUNIT_AUTOEXIT=true -argument=-app-arg:-enablenetwork -setenv=NUNIT_ENABLE_NETWORK=true " +
|
$"-setenv=NUNIT_AUTOEXIT=true -argument=-app-arg:-enablenetwork -setenv=NUNIT_ENABLE_NETWORK=true " +
|
||||||
$"-setenv=DISABLE_SYSTEM_PERMISSION_TESTS=1 -argument=-app-arg:-hostname:{ips} -setenv=NUNIT_HOSTNAME={ips} " +
|
$"-setenv=DISABLE_SYSTEM_PERMISSION_TESTS=1 -argument=-app-arg:-hostname:{ips} -setenv=NUNIT_HOSTNAME={ips} " +
|
||||||
|
@ -738,7 +726,6 @@ namespace Xharness.Tests {
|
||||||
|
|
||||||
processManager
|
processManager
|
||||||
.Setup (x => x.ExecuteCommandAsync (
|
.Setup (x => x.ExecuteCommandAsync (
|
||||||
mlaunchPath,
|
|
||||||
It.Is<MlaunchArguments> (args => args.AsCommandLine () == expectedArgs),
|
It.Is<MlaunchArguments> (args => args.AsCommandLine () == expectedArgs),
|
||||||
It.IsAny<ILog> (),
|
It.IsAny<ILog> (),
|
||||||
TimeSpan.FromMinutes (harness.Timeout * 2),
|
TimeSpan.FromMinutes (harness.Timeout * 2),
|
||||||
|
@ -749,13 +736,15 @@ namespace Xharness.Tests {
|
||||||
var xmlResultFile = Path.ChangeExtension (testResultFilePath, "xml");
|
var xmlResultFile = Path.ChangeExtension (testResultFilePath, "xml");
|
||||||
var testReporterFactory = new Mock<ITestReporterFactory> ();
|
var testReporterFactory = new Mock<ITestReporterFactory> ();
|
||||||
var testReporter = new Mock<ITestReporter> ();
|
var testReporter = new Mock<ITestReporter> ();
|
||||||
testReporterFactory.Setup (f => f.Create (
|
testReporterFactory
|
||||||
|
.Setup (f => f.Create (
|
||||||
It.IsAny<IAppRunner> (),
|
It.IsAny<IAppRunner> (),
|
||||||
It.IsAny<string> (),
|
"Test iPad",
|
||||||
It.IsAny<ISimpleListener> (),
|
It.IsAny<ISimpleListener> (),
|
||||||
It.IsAny<ILog> (),
|
mainLog.Object,
|
||||||
It.IsAny<ICrashSnapshotReporter> (),
|
snapshotReporter.Object,
|
||||||
It.IsAny<IResultParser> ())).Returns (testReporter.Object);
|
It.IsAny<IResultParser> ()))
|
||||||
|
.Returns (testReporter.Object);
|
||||||
testReporter.Setup (r => r.Timeout).Returns (TimeSpan.FromMinutes (harness.Timeout * 2));
|
testReporter.Setup (r => r.Timeout).Returns (TimeSpan.FromMinutes (harness.Timeout * 2));
|
||||||
testReporter.Setup (r => r.TimeoutWatch).Returns (new System.Diagnostics.Stopwatch ());
|
testReporter.Setup (r => r.TimeoutWatch).Returns (new System.Diagnostics.Stopwatch ());
|
||||||
testReporter.Setup (r => r.ParseResult ()).Returns (() => {
|
testReporter.Setup (r => r.ParseResult ()).Returns (() => {
|
||||||
|
@ -802,11 +791,8 @@ namespace Xharness.Tests {
|
||||||
IHarness GetMockedHarness ()
|
IHarness GetMockedHarness ()
|
||||||
{
|
{
|
||||||
return Mock.Of<IHarness> (x => x.Action == HarnessAction.Run
|
return Mock.Of<IHarness> (x => x.Action == HarnessAction.Run
|
||||||
&& x.XcodeRoot == xcodePath
|
|
||||||
&& x.MlaunchPath == mlaunchPath
|
|
||||||
&& x.Verbosity == 1
|
&& x.Verbosity == 1
|
||||||
&& x.HarnessLog == mainLog.Object
|
&& x.HarnessLog == mainLog.Object
|
||||||
&& x.LogDirectory == logs.Object.Directory
|
|
||||||
&& x.InCI == false
|
&& x.InCI == false
|
||||||
&& x.EnvironmentVariables == new Dictionary<string, string> () {
|
&& x.EnvironmentVariables == new Dictionary<string, string> () {
|
||||||
{ "env1", "value1" },
|
{ "env1", "value1" },
|
||||||
|
|
|
@ -12,8 +12,8 @@ using Xharness.Utilities;
|
||||||
|
|
||||||
namespace Xharness.Tests {
|
namespace Xharness.Tests {
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class CrashSnapshotReporterTests {
|
public class CrashReportSnapshotTests {
|
||||||
readonly string mlaunchPath = "./mlaunch";
|
|
||||||
string tempXcodeRoot;
|
string tempXcodeRoot;
|
||||||
string symbolicatePath;
|
string symbolicatePath;
|
||||||
|
|
||||||
|
@ -31,6 +31,9 @@ namespace Xharness.Tests {
|
||||||
tempXcodeRoot = Path.Combine (Path.GetTempPath (), Guid.NewGuid ().ToString ());
|
tempXcodeRoot = Path.Combine (Path.GetTempPath (), Guid.NewGuid ().ToString ());
|
||||||
symbolicatePath = Path.Combine (tempXcodeRoot, "Contents", "SharedFrameworks", "DTDeviceKitBase.framework", "Versions", "A", "Resources");
|
symbolicatePath = Path.Combine (tempXcodeRoot, "Contents", "SharedFrameworks", "DTDeviceKitBase.framework", "Versions", "A", "Resources");
|
||||||
|
|
||||||
|
processManager.SetupGet (x => x.XcodeRoot).Returns (tempXcodeRoot);
|
||||||
|
processManager.SetupGet (x => x.MlaunchPath).Returns ("/var/bin/mlaunch");
|
||||||
|
|
||||||
// Create fake place for device logs
|
// Create fake place for device logs
|
||||||
Directory.CreateDirectory (tempXcodeRoot);
|
Directory.CreateDirectory (tempXcodeRoot);
|
||||||
|
|
||||||
|
@ -71,8 +74,6 @@ namespace Xharness.Tests {
|
||||||
var snapshotReport = new CrashSnapshotReporter (processManager.Object,
|
var snapshotReport = new CrashSnapshotReporter (processManager.Object,
|
||||||
log.Object,
|
log.Object,
|
||||||
logs.Object,
|
logs.Object,
|
||||||
tempXcodeRoot,
|
|
||||||
mlaunchPath,
|
|
||||||
true,
|
true,
|
||||||
deviceName,
|
deviceName,
|
||||||
() => tempFilePath);
|
() => tempFilePath);
|
||||||
|
@ -91,10 +92,9 @@ namespace Xharness.Tests {
|
||||||
// List of crash reports is retrieved
|
// List of crash reports is retrieved
|
||||||
processManager.Verify (
|
processManager.Verify (
|
||||||
x => x.ExecuteCommandAsync (
|
x => x.ExecuteCommandAsync (
|
||||||
mlaunchPath,
|
|
||||||
It.Is<MlaunchArguments> (args => args.AsCommandLine () ==
|
It.Is<MlaunchArguments> (args => args.AsCommandLine () ==
|
||||||
StringUtils.FormatArguments ($"--list-crash-reports={tempFilePath}") + " " +
|
StringUtils.FormatArguments (
|
||||||
$"--sdkroot {StringUtils.FormatArguments (tempXcodeRoot)} " +
|
$"--list-crash-reports={tempFilePath}") + " " +
|
||||||
$"--devname {StringUtils.FormatArguments (deviceName)}"),
|
$"--devname {StringUtils.FormatArguments (deviceName)}"),
|
||||||
log.Object,
|
log.Object,
|
||||||
TimeSpan.FromMinutes (1),
|
TimeSpan.FromMinutes (1),
|
||||||
|
@ -105,11 +105,10 @@ namespace Xharness.Tests {
|
||||||
// Device crash log is downloaded
|
// Device crash log is downloaded
|
||||||
processManager.Verify (
|
processManager.Verify (
|
||||||
x => x.ExecuteCommandAsync (
|
x => x.ExecuteCommandAsync (
|
||||||
mlaunchPath,
|
|
||||||
It.Is<MlaunchArguments> (args => args.AsCommandLine () ==
|
It.Is<MlaunchArguments> (args => args.AsCommandLine () ==
|
||||||
StringUtils.FormatArguments ($"--download-crash-report={deviceName}") + " " +
|
StringUtils.FormatArguments (
|
||||||
|
$"--download-crash-report={deviceName}") + " " +
|
||||||
StringUtils.FormatArguments ($"--download-crash-report-to={crashLogPath}") + " " +
|
StringUtils.FormatArguments ($"--download-crash-report-to={crashLogPath}") + " " +
|
||||||
$"--sdkroot {StringUtils.FormatArguments (tempXcodeRoot)} " +
|
|
||||||
$"--devname {StringUtils.FormatArguments (deviceName)}"),
|
$"--devname {StringUtils.FormatArguments (deviceName)}"),
|
||||||
log.Object,
|
log.Object,
|
||||||
TimeSpan.FromMinutes (1),
|
TimeSpan.FromMinutes (1),
|
||||||
|
|
Загрузка…
Ссылка в новой задаче