[Harness] Remove Harness as a dependency (#8203)

This commit is contained in:
Přemek Vysoký 2020-03-27 17:41:31 +01:00 коммит произвёл GitHub
Родитель dddcba9dc4
Коммит 6209719f51
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
30 изменённых файлов: 400 добавлений и 526 удалений

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

@ -188,10 +188,6 @@ namespace Xharness {
var args = new MlaunchArguments ();
if (!string.IsNullOrEmpty (harness.XcodeRoot)) {
args.Add (new SdkRootArgument (harness.XcodeRoot));
}
for (int i = -1; i < harness.Verbosity; i++)
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 ();
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 ()
@ -217,17 +213,13 @@ namespace Xharness {
var args = new MlaunchArguments ();
if (!string.IsNullOrEmpty (harness.XcodeRoot)) {
args.Add (new SdkRootArgument (harness.XcodeRoot));
}
for (int i = -1; i < harness.Verbosity; i++)
args.Add (new VerbosityArgument ());
args.Add (new UninstallAppFromDeviceArgument (AppInformation.BundleIdentifier));
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);
@ -241,10 +233,6 @@ namespace Xharness {
var args = new MlaunchArguments ();
if (!string.IsNullOrEmpty (harness.XcodeRoot)) {
args.Add (new SdkRootArgument (harness.XcodeRoot));
}
for (int i = -1; i < harness.Verbosity; i++)
args.Add (new VerbosityArgument ());
@ -387,7 +375,7 @@ namespace Xharness {
MainLog.WriteLine ("Starting test run");
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
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).
var runLog = Log.CreateAggregatedLog (testReporter.CallbackLog, MainLog);
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 {
deviceLogCapturer.StopCapture ();
deviceSystemLog.Dispose ();

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

@ -5,6 +5,5 @@ using Xharness.Logging;
namespace Xharness.Collections{
public interface ILoadAsync {
Task LoadAsync (ILog log, bool include_locked, bool force);
IHarness Harness { get; set; }
}
}

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

@ -17,18 +17,14 @@ namespace Xharness
public class CrashSnapshotReporterFactory : ICrashSnapshotReporterFactory {
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.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) =>
new CrashSnapshotReporter (processManager, log, logs, xcodeRoot, mlaunchPath, isDevice, deviceName);
new CrashSnapshotReporter (processManager, log, logs, isDevice, deviceName);
}
public interface ICrashSnapshotReporter {
@ -40,8 +36,6 @@ namespace Xharness
readonly IProcessManager processManager;
readonly ILog log;
readonly ILogs logs;
readonly string xcodeRoot;
readonly string mlaunchPath;
readonly bool isDevice;
readonly string deviceName;
readonly Func<string> tempFileProvider;
@ -52,8 +46,6 @@ namespace Xharness
public CrashSnapshotReporter (IProcessManager processManager,
ILog log,
ILogs logs,
string xcodeRoot,
string mlaunchPath,
bool isDevice,
string deviceName,
Func<string> tempFileProvider = null)
@ -61,15 +53,13 @@ namespace Xharness
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
this.log = log ?? throw new ArgumentNullException (nameof (log));
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.deviceName = deviceName;
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))
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))
symbolicateCrashPath = null;
}
@ -135,14 +125,13 @@ namespace Xharness
var crashReportFile = logs.Create (name, $"Crash report: {name}", timestamp: false);
var args = new MlaunchArguments (
new DownloadCrashReportArgument (crashFile),
new DownloadCrashReportToArgument (crashReportFile.FullPath),
new SdkRootArgument (xcodeRoot));
new DownloadCrashReportToArgument (crashReportFile.FullPath));
if (!string.IsNullOrEmpty (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) {
log.WriteLine ("Downloaded crash report {0} to {1}", crashFile, crashReportFile.FullPath);
@ -162,7 +151,7 @@ namespace Xharness
var name = Path.GetFileName (report.FullPath);
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);
if (result.Succeeded) {
log.WriteLine ("Symbolicated {0} successfully.", report.FullPath);
@ -184,15 +173,13 @@ namespace Xharness
} else {
var tempFile = tempFileProvider ();
try {
var args = new MlaunchArguments (
new ListCrashReportsArgument (tempFile),
new SdkRootArgument (xcodeRoot));
var args = new MlaunchArguments (new ListCrashReportsArgument (tempFile));
if (!string.IsNullOrEmpty (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)
crashes.UnionWith (File.ReadAllLines (tempFile));
} finally {

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

@ -14,19 +14,15 @@ namespace Xharness
public class DeviceLogCapturerFactory : IDeviceLogCapturerFactory {
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.xcodeRoot = xcodeRoot ?? throw new ArgumentNullException (nameof (xcodeRoot));
this.mlaunchPath = mlaunchPath ?? throw new ArgumentNullException (nameof (mlaunchPath));
}
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 deviceLog;
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.mainLog = mainLog ?? throw new ArgumentNullException (nameof (mainLog));
this.deviceLog = deviceLog ?? throw new ArgumentNullException (nameof (deviceLog));
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;
@ -60,17 +52,17 @@ namespace Xharness
{
streamEnds = new CountdownEvent (2);
var sb = new List<string> {
var args = new List<string> {
"--logdev",
"--sdkroot",
xcodeRoot,
processManager.XcodeRoot,
"--devname",
deviceName
};
process = new Process ();
process.StartInfo.FileName = mlaunchPath;
process.StartInfo.Arguments = StringUtils.FormatArguments (sb);
process.StartInfo.FileName = processManager.MlaunchPath;
process.StartInfo.Arguments = StringUtils.FormatArguments (args);
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;

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

@ -17,15 +17,17 @@ namespace Xharness.Execution {
// interface that helps to manage the different processes in the app.
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, 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> ExecuteCommandAsync (MlaunchArguments args, ILog log, TimeSpan timeout, Dictionary<string, string> environment_variables = null, CancellationToken? cancellation_token = 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, 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<bool> WaitForExitAsync (Process process, TimeSpan? timeout = null);
Task KillTreeAsync (Process process, 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.Threading;
using System.Threading.Tasks;
using System.Xml;
using Xharness.Execution.Mlaunch;
using Xharness.Logging;
using Xharness.Utilities;
namespace Xharness.Execution {
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,
IList<string> args,
ILog log,
TimeSpan timeout,
Dictionary<string, string> environment_variables = null,
CancellationToken? cancellation_token = null)
Dictionary<string, string> environmentVariables = null,
CancellationToken? cancellationToken = null)
{
using (var p = new Process ()) {
p.StartInfo.FileName = filename;
using var p = new Process ();
p.StartInfo.FileName = filename ?? throw new ArgumentNullException (nameof (filename));
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,
MlaunchArguments args,
public async Task<ProcessExecutionResult> ExecuteCommandAsync (MlaunchArguments args,
ILog log,
TimeSpan timeout,
Dictionary<string, string> environment_variables = null,
CancellationToken? cancellation_token = null)
Dictionary<string, string> environmentVariables = null,
CancellationToken? cancellationToken = null)
{
using (var p = new Process ()) {
p.StartInfo.FileName = filename;
p.StartInfo.Arguments = args.AsCommandLine ();
return await RunAsync (p, log, timeout, environment_variables, cancellation_token);
using var p = new Process ();
return await RunAsync (p, args, log, timeout, environmentVariables, cancellationToken);
}
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")]
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> ();
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));
return RunAsync (process, log, log, log, timeout, environment_variables, cancellationToken, diagnostics);
}
rv.SetResult (false);
});
return rv.Task;
}
public async Task<ProcessExecutionResult> RunAsync (Process process, ILog log, CancellationToken? cancellation_token = null, bool? diagnostics = null)
public Task<ProcessExecutionResult> RunAsync (Process process,
MlaunchArguments args,
ILog log,
TimeSpan? timeout = null,
Dictionary<string, string> environmentVariables = 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)
{
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.FileName = MlaunchPath;
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 stderr_completion = new TaskCompletionSource<bool> ();
@ -105,9 +122,9 @@ namespace Xharness.Execution {
process.OutputDataReceived += (object sender, DataReceivedEventArgs e) =>
{
if (e.Data != null) {
lock (StdoutStream) {
StdoutStream.WriteLine (e.Data);
StdoutStream.Flush ();
lock (stdout) {
stdout.WriteLine (e.Data);
stdout.Flush ();
}
} else {
stdout_completion.TrySetResult (true);
@ -117,9 +134,9 @@ namespace Xharness.Execution {
process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) =>
{
if (e.Data != null) {
lock (StderrStream) {
StderrStream.WriteLine (e.Data);
StderrStream.Flush ();
lock (stderr) {
stderr.WriteLine (e.Data);
stderr.Flush ();
}
} else {
stderr_completion.TrySetResult (true);
@ -148,7 +165,7 @@ namespace Xharness.Execution {
process.BeginErrorReadLine ();
process.BeginOutputReadLine ();
cancellation_token?.Register (() => {
cancellationToken?.Register (() => {
var hasExited = false;
try {
hasExited = process.HasExited;
@ -159,7 +176,7 @@ namespace Xharness.Execution {
// processes behind).
}
if (!hasExited) {
StderrStream.WriteLine ($"Execution of {pid} was cancelled.");
stderr.WriteLine ($"Execution of {pid} was cancelled.");
kill (pid, 9);
}
});
@ -168,7 +185,7 @@ namespace Xharness.Execution {
if (!await WaitForExitAsync (process, timeout.Value)) {
await KillTreeAsync (process, log, diagnostics ?? true);
rv.TimedOut = true;
lock (StderrStream)
lock (stderr)
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;
}
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)
{
return KillTreeAsync (process.Id, log, diagnostics);
@ -223,8 +208,8 @@ namespace Xharness.Execution {
public async Task KillTreeAsync (int pid, ILog log, bool? diagnostics = true)
{
var pids = new List<int> ();
GetChildrenPS (log, pids, pid);
var pids = GetChildrenPS (log, pid);
if (diagnostics == true) {
log.WriteLine ($"Pids to kill: {string.Join (", ", pids.Select ((v) => v.ToString ()).ToArray ())}");
using (var ps = new Process ()) {
@ -271,9 +256,41 @@ namespace Xharness.Execution {
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 ()) {
ps.StartInfo.FileName = "ps";
@ -281,20 +298,21 @@ namespace Xharness.Execution {
ps.StartInfo.UseShellExecute = false;
ps.StartInfo.RedirectStandardOutput = true;
ps.Start ();
stdout = ps.StandardOutput.ReadToEnd ();
string stdout = ps.StandardOutput.ReadToEnd ();
if (!ps.WaitForExit (1000)) {
log.WriteLine ("ps didn't finish in a reasonable amount of time (1 second).");
return;
return list;
}
if (ps.ExitCode != 0)
return;
return list;
stdout = stdout.Trim ();
if (string.IsNullOrEmpty (stdout))
return;
return list;
var dict = new Dictionary<int, List<int>> ();
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 process = l.Substring (space + 1);
int parent_id, process_id;
if (int.TryParse (parent, out parent_id) && int.TryParse (process, out process_id)) {
List<int> children;
if (!dict.TryGetValue (parent_id, out children))
if (int.TryParse (parent, out var parent_id) && int.TryParse (process, out var process_id)) {
if (!dict.TryGetValue (parent_id, out var children))
dict [parent_id] = children = new List<int> ();
children.Add (process_id);
}
}
@ -319,15 +336,16 @@ namespace Xharness.Execution {
queue.Enqueue (pid);
do {
List<int> children;
var parent_id = queue.Dequeue ();
list.Add (parent_id);
if (dict.TryGetValue (parent_id, out children)) {
if (dict.TryGetValue (parent_id, out var children)) {
foreach (var child in children)
queue.Enqueue (child);
}
} while (queue.Count > 0);
}
return list;
}
}
}

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

@ -6,8 +6,6 @@ using System.Linq;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Xml;
using System.Text;
using Xamarin;
using Xharness.Execution;
using Xharness.Logging;
@ -15,7 +13,6 @@ namespace Xharness
{
public static class GitHub
{
static IProcessManager ProcessManager { get; set; } = new ProcessManager ();
static WebClient CreateClient ()
{
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");
if (!File.Exists (path)) {
var rv = GetModifiedFilesLocally (harness, pull_request);
var rv = GetModifiedFilesLocally (processManager, harness, pull_request);
if (rv == null || rv.Count () == 0) {
rv = GetModifiedFilesRemotely (harness, pull_request);
if (rv == null)
@ -141,7 +138,7 @@ namespace Xharness
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 head_commit = $"origin/pr/{pull_request}/merge";
@ -155,7 +152,7 @@ namespace Xharness
git.StartInfo.FileName = "git";
git.StartInfo.Arguments = $"diff-tree --no-commit-id --name-only -r {base_commit}..{head_commit}";
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)
return output.ToString ().Split (new char [] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

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

@ -4,6 +4,7 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Web.UI.WebControls;
using System.Xml;
using Xharness.Collections;
using Xharness.Execution;
@ -18,24 +19,20 @@ namespace Xharness.Hardware {
}
public class DeviceLoaderFactory : IDeviceLoaderFactory {
readonly IHarness harness;
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));
}
public IDeviceLoader CreateLoader () => new Devices (harness, processManager);
public IDeviceLoader CreateLoader () => new Devices (processManager);
}
public class Devices : IDeviceLoader {
readonly IProcessManager processManager;
bool loaded;
public IHarness Harness { get; set; }
BlockingEnumerableCollection<IHardwareDevice> connected_devices = new BlockingEnumerableCollection<IHardwareDevice> ();
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));
}
@ -76,18 +72,19 @@ namespace Xharness.Hardware {
var tmpfile = Path.GetTempFileName ();
try {
using (var process = new Process ()) {
process.StartInfo.FileName = Harness.MlaunchPath;
var arguments = new MlaunchArguments (
new SdkRootArgument (Harness.XcodeRoot),
new ListDevicesArgument (tmpfile),
new XmlOutputFormatArgument ());
if (extra_data)
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);
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.");
log.WriteLine ("Result:");
log.WriteLine (File.ReadAllText (tmpfile));

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

@ -33,7 +33,6 @@ namespace Xharness.Hardware {
}
public interface ISimulatorDevice : IDevice {
ITCCDatabase TCCDatabase { get; set; }
string SimRuntime { get; set; }
string SimDeviceType { get; set; }
string DataPath { get; set; }

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

@ -9,10 +9,8 @@ using Xharness.Logging;
namespace Xharness.Hardware {
public class SimulatorDevice : ISimulatorDevice {
readonly IHarness harness;
readonly IProcessManager processManager;
public ITCCDatabase TCCDatabase { get; set; } = new TCCDatabase ();
readonly ITCCDatabase tCCDatabase;
public string UDID { get; set; }
public string Name { get; set; }
@ -23,10 +21,10 @@ namespace Xharness.Hardware {
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.tCCDatabase = tccDatabase ?? throw new ArgumentNullException (nameof (tccDatabase));
}
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.
// erase the simulator (make sure the device isn't running first)
await harness.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 [] { "shutdown", UDID }, log, TimeSpan.FromMinutes (1));
await processManager.ExecuteXcodeCommandAsync ("simctl", new [] { "erase", UDID }, log, TimeSpan.FromMinutes (1));
// boot & shutdown to make sure it actually works
await harness.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 [] { "boot", UDID }, log, TimeSpan.FromMinutes (1));
await processManager.ExecuteXcodeCommandAsync ("simctl", new [] { "shutdown", UDID }, log, TimeSpan.FromMinutes (1));
}
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)
@ -86,12 +84,12 @@ namespace Xharness.Hardware {
{
string simulator_app;
if (IsWatchSimulator && harness.XcodeVersion.Major < 9) {
simulator_app = Path.Combine (harness.XcodeRoot, "Contents", "Developer", "Applications", "Simulator (Watch).app");
if (IsWatchSimulator && processManager.XcodeVersion.Major < 9) {
simulator_app = Path.Combine (processManager.XcodeRoot, "Contents", "Developer", "Applications", "Simulator (Watch).app");
} 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))
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));
@ -121,7 +119,7 @@ namespace Xharness.Hardware {
}
if (File.Exists (TCC_db)) {
await TCCDatabase.AgreeToPromptsAsync (SimRuntime, TCC_db, log, bundle_identifiers);
await tCCDatabase.AgreeToPromptsAsync (SimRuntime, TCC_db, log, bundle_identifiers);
} else {
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 {
readonly IHarness harness;
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));
}
public ISimulatorsLoader CreateLoader () => new Simulators (harness, processManager);
public ISimulatorsLoader CreateLoader () => new Simulators (processManager);
}
public class Simulators : ISimulatorsLoader {
@ -44,16 +42,13 @@ namespace Xharness.Hardware {
bool loaded;
public IHarness Harness { get; set; }
public IEnumerable<SimRuntime> SupportedRuntimes => supported_runtimes;
public IEnumerable<SimDeviceType> SupportedDeviceTypes => supported_device_types;
public IEnumerable<SimulatorDevice> AvailableDevices => available_devices;
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));
}
@ -76,18 +71,18 @@ namespace Xharness.Hardware {
var tmpfile = Path.GetTempFileName ();
try {
using (var process = new Process ()) {
process.StartInfo.FileName = Harness.MlaunchPath;
var arguments = new MlaunchArguments (
new SdkRootArgument(Harness.XcodeRoot),
new ListSimulatorsArgument(tmpfile),
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);
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.");
log.WriteLine ("Result:");
log.WriteLine (File.ReadAllText (tmpfile));
var simulator_data = new XmlDocument ();
@ -112,7 +107,7 @@ namespace Xharness.Hardware {
}
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,
UDID = sim.Attributes ["UDID"].Value,
SimRuntime = sim.SelectSingleNode ("SimRuntime").InnerText,
@ -168,7 +163,7 @@ namespace Xharness.Hardware {
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) {
log.WriteLine ($"Could not create device for runtime={runtime} and device type={devicetype}.");
return null;
@ -207,8 +202,7 @@ namespace Xharness.Hardware {
log.Write (value);
capturedLog.Append (value);
});
var rv = await Harness.ExecuteXcodeCommandAsync ("simctl", new [] { "pair", device.UDID, companion_device.UDID }, pairLog, TimeSpan.FromMinutes (1));
var rv = await processManager.ExecuteXcodeCommandAsync ("simctl", new [] { "pair", device.UDID, companion_device.UDID }, pairLog, TimeSpan.FromMinutes (1));
if (!rv.Succeeded) {
if (!create_device) {
var try_creating_device = false;

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

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using Xharness.Execution;
using Xharness.Logging;
@ -9,7 +8,6 @@ using Xharness.Logging;
namespace Xharness.Hardware {
public interface ITCCDatabase {
IProcessManager ProcessManager { get; set; }
Task AgreeToPromptsAsync (string simRuntime, string dataPath, ILog log, params string [] bundle_identifiers);
int GetTCCFormat (string simRuntime);
}
@ -19,7 +17,12 @@ namespace Xharness.Hardware {
static readonly string tvOSSimRuntimePrefix = "com.apple.CoreSimulator.SimRuntime.tvOS-";
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) {
@ -109,7 +112,7 @@ namespace Xharness.Hardware {
}
}
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) {
failure = true;
break;
@ -124,7 +127,7 @@ namespace Xharness.Hardware {
}
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.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Xml;
using Xharness.BCLTestImporter;
using Xharness.Logging;
@ -51,66 +50,30 @@ namespace Xharness
public interface IHarness {
HarnessAction Action { get; }
bool DisableWatchOSOnWrench { get; }
string DOTNET { get; }
bool DryRun { get; }
bool ENABLE_XAMARIN { get; }
Dictionary<string, string> EnvironmentVariables { get; }
ILog HarnessLog { get; set; }
string GetStandardErrorTty ();
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; }
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; }
string TodayContainerTemplate { get; }
string TodayExtensionTemplate { get; }
bool UseGroupedApps { get; }
int Verbosity { get; }
string WatchOSAppTemplate { get; }
string WatchOSContainerTemplate { get; }
string WatchOSExtensionTemplate { get; }
string XcodeRoot { get; }
Version XcodeVersion { get; }
XmlResultJargon XmlJargon { get; }
Task<ProcessExecutionResult> ExecuteXcodeCommandAsync (string executable, IList<string> args, ILog log, TimeSpan timeout);
bool GetIncludeSystemPermissionTests (TestPlatform platform, bool device);
string GetStandardErrorTty ();
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 {
readonly TestTarget target;
readonly string buildConfiguration = "Debug";
IProcessManager processManager;
public HarnessAction Action { get; }
public int Verbosity { get; }
public ILog HarnessLog { get; set; }
public HashSet<string> Labels { get; }
public XmlResultJargon XmlJargon { get; }
public IProcessManager ProcessManager { get; }
public IResultParser ResultParser { get; }
// 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<MacTestProject> MacTestProjects { get; } = new List<MacTestProject> ();
@ -164,19 +129,19 @@ namespace Xharness
public string TodayContainerTemplate { get; private set; }
public string TodayExtensionTemplate { 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 TVOS_MONO_PATH { get; private set; } // Use same name as in Makefiles, so that a grep finds it.
public bool INCLUDE_IOS { get; private set; }
public bool INCLUDE_TVOS { get; private set; }
public bool INCLUDE_WATCH { get; private set; }
public bool INCLUDE_MAC { get; private set; }
public string JENKINS_RESULTS_DIRECTORY { get; private set; } // Use same name as in Makefiles, so that a grep finds it.
public string MAC_DESTDIR { get; private set; }
public string IOS_DESTDIR { get; private set; }
public string MONO_IOS_SDK_DESTDIR { get; private set; }
public string MONO_MAC_SDK_DESTDIR { get; private set; }
public bool ENABLE_XAMARIN { get; private set; }
public string DOTNET { get; private set; }
public string MONO_PATH { get; } // 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; }
public bool INCLUDE_TVOS { get; }
public bool INCLUDE_WATCH { get; }
public bool INCLUDE_MAC { get; }
public string JENKINS_RESULTS_DIRECTORY { get; } // Use same name as in Makefiles, so that a grep finds it.
public string MAC_DESTDIR { get; }
public string IOS_DESTDIR { get; }
public string MONO_IOS_SDK_DESTDIR { get; }
public string MONO_MAC_SDK_DESTDIR { get; }
public bool ENABLE_XAMARIN { get; }
public string DOTNET { get; }
// Run
@ -196,9 +161,8 @@ namespace Xharness
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));
Action = action;
@ -217,7 +181,6 @@ namespace Xharness
PeriodicCommand = configuration.PeriodicCommand;
PeriodicCommandArguments = configuration.PeriodicCommandArguments;
PeriodicCommandInterval = configuration.PeriodicCommandInterval;
SdkRoot = configuration.SdkRoot;
target = configuration.Target;
Timeout = configuration.TimeoutInMinutes;
useSystemXamarinIOSMac = configuration.UseSystemXamarinIOSMac;
@ -233,6 +196,29 @@ namespace Xharness
EnvironmentVariables = new Dictionary<string, string> (configuration.EnvironmentVariables);
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)
@ -277,45 +263,6 @@ namespace Xharness
} 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 rv = 0;
@ -480,7 +427,7 @@ namespace Xharness
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)
{
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"));
ParseConfigFiles (FindConfigFiles ("Make.config.local"));
ParseConfigFiles (FindConfigFiles ("Make.config"));
var configuration = new Dictionary<string, string> ();
foreach (var file in GetConfigFiles ()) {
ParseConfigFile (file, configuration);
}
void ParseConfigFiles (IEnumerable<string> files)
{
foreach (var file in files)
ParseConfigFile (file);
return configuration;
}
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))
return;
@ -514,9 +465,10 @@ namespace Xharness
var eq = line.IndexOf ('=');
if (eq == -1)
continue;
var key = line.Substring (0, eq);
if (!make_config.ContainsKey (key))
make_config [key] = line.Substring (eq + 1);
if (!configuration.ContainsKey (key))
configuration [key] = line.Substring (eq + 1);
}
}
@ -604,22 +556,7 @@ namespace Xharness
HarnessLog = new ConsoleLog ();
foreach (var project in IOSTestProjects) {
var runner = new AppRunner (ProcessManager,
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 runner = CreateAppRunner (project);
using (var install_log = new AppInstallMonitorLog (runner.MainLog)) {
var rv = runner.InstallAsync (install_log.CancellationToken).Result;
if (!rv.Succeeded)
@ -635,22 +572,7 @@ namespace Xharness
HarnessLog = new ConsoleLog ();
foreach (var project in IOSTestProjects) {
var runner = new AppRunner (ProcessManager,
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 runner = CreateAppRunner (project);
var rv = runner.UninstallAsync ().Result;
if (!rv.Succeeded)
return rv.ExitCode;
@ -664,22 +586,7 @@ namespace Xharness
HarnessLog = new ConsoleLog ();
foreach (var project in IOSTestProjects) {
var runner = new AppRunner (ProcessManager,
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 runner = CreateAppRunner (project);
var rv = runner.RunAsync ().Result;
if (rv != 0)
return rv;
@ -729,7 +636,6 @@ namespace Xharness
public int Execute ()
{
LoadConfig ();
switch (Action) {
case HarnessAction.Configure:
return Configure ();
@ -753,7 +659,7 @@ namespace Xharness
AutoConfigureMac (false);
}
var jenkins = new Jenkins.Jenkins (this, ProcessManager, ResultParser);
var jenkins = new Jenkins.Jenkins (this, processManager, ResultParser);
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
// log all the required data.
public interface IAppRunner {
IProcessManager ProcessManager { get; }
AppBundleInformation AppInformation { get; }
BuildToolTask BuildTask { get; }
TimeSpan GetNewTimeout ();
double LaunchTimeout { get; }
IProcessManager ProcessManager { get; }
ILogs Logs { get; }
ILog MainLog { get; }
RunMode RunMode { get; }

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

@ -103,15 +103,15 @@ namespace Xharness.Jenkins
this.processManager = processManager ?? throw new ArgumentNullException (nameof (processManager));
this.resultParser = resultParser ?? throw new ArgumentNullException (nameof (resultParser));
Harness = harness ?? throw new ArgumentNullException (nameof (harness));
simulators = new Simulators (harness, processManager);
devices = new Devices (harness, processManager);
simulators = new Simulators (processManager);
devices = new Devices (processManager);
}
Task LoadAsync (ref ILog log, ILoadAsync loadable, string name)
{
loadable.Harness = Harness;
if (log == null)
log = Logs.Create ($"{name}-list-{Helpers.Timestamp}.log", $"{name} Listing");
log.Description = $"{name} Listing (in progress)";
var capturedLog = log;
@ -481,7 +481,7 @@ namespace Xharness.Jenkins
clone.Xml.Save (clone.Path);
});
var build = new MSBuildTask {
var build = new MSBuildTask (processManager) {
Jenkins = this,
TestProject = clone,
ProjectConfiguration = configuration,
@ -530,7 +530,7 @@ namespace Xharness.Jenkins
configurations = new string [] { "Debug" };
foreach (var config in configurations) {
foreach (var pair in ps) {
var derived = new MSBuildTask () {
var derived = new MSBuildTask (processManager) {
Jenkins = this,
ProjectConfiguration = config,
ProjectPlatform = "iPhoneSimulator",
@ -584,7 +584,7 @@ namespace Xharness.Jenkins
projectTasks.Clear ();
if (!project.SkipiOSVariation) {
var build64 = new MSBuildTask {
var build64 = new MSBuildTask (processManager) {
Jenkins = this,
ProjectConfiguration = "Debug64",
ProjectPlatform = "iPhone",
@ -594,7 +594,7 @@ namespace Xharness.Jenkins
build64.CloneTestProject (project);
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,
ProjectConfiguration = project.Name != "dont link" ? "Debug32" : "Release32",
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 });
var todayProject = project.AsTodayExtensionProject ();
var buildToday = new MSBuildTask {
var buildToday = new MSBuildTask (processManager) {
Jenkins = this,
ProjectConfiguration = "Debug64",
ProjectPlatform = "iPhone",
@ -618,7 +618,7 @@ namespace Xharness.Jenkins
if (!project.SkiptvOSVariation) {
var tvOSProject = project.AsTvOSProject ();
var buildTV = new MSBuildTask {
var buildTV = new MSBuildTask (processManager) {
Jenkins = this,
ProjectConfiguration = "Debug",
ProjectPlatform = "iPhone",
@ -632,7 +632,7 @@ namespace Xharness.Jenkins
if (!project.SkipwatchOSVariation) {
var watchOSProject = project.AsWatchOSProject ();
if (!project.SkipwatchOS32Variation) {
var buildWatch32 = new MSBuildTask {
var buildWatch32 = new MSBuildTask (processManager) {
Jenkins = this,
ProjectConfiguration = "Debug32",
ProjectPlatform = "iPhone",
@ -644,7 +644,7 @@ namespace Xharness.Jenkins
}
if (!project.SkipwatchOSARM64_32Variation) {
var buildWatch64_32 = new MSBuildTask {
var buildWatch64_32 = new MSBuildTask (processManager) {
Jenkins = this,
ProjectConfiguration = "Release64_32", // We don't support Debug for ARM64_32 yet.
ProjectPlatform = "iPhone",
@ -720,7 +720,7 @@ namespace Xharness.Jenkins
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);
foreach (var f in files)
@ -938,9 +938,9 @@ namespace Xharness.Jenkins
//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,
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);
var buildiOSMSBuild_netstandard2 = new MSBuildTask () {
var buildiOSMSBuild_netstandard2 = new MSBuildTask (processManager) {
Jenkins = this,
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "..", "msbuild", "tests", "Xamarin.iOS.Tasks.Tests", "Xamarin.iOS.Tasks.Tests.csproj"))),
SpecifyPlatform = false,
@ -988,7 +988,7 @@ namespace Xharness.Jenkins
};
Tasks.Add (nunitExecutioniOSMSBuild_netstandard2);
var buildInstallSources = new MSBuildTask ()
var buildInstallSources = new MSBuildTask (processManager)
{
Jenkins = this,
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 ());
}
foreach (var config in configurations) {
MSBuildTask build = new MSBuildTask ();
MSBuildTask build = new MSBuildTask (processManager);
build.Platform = platform;
build.CloneTestProject (project);
build.Jenkins = this;
@ -1082,7 +1082,7 @@ namespace Xharness.Jenkins
}
}
var buildMTouch = new MakeTask ()
var buildMTouch = new MakeTask (processManager)
{
Jenkins = this,
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "mtouch", "mtouch.sln"))),
@ -1104,7 +1104,7 @@ namespace Xharness.Jenkins
};
Tasks.Add (nunitExecutionMTouch);
var buildGenerator = new MakeTask {
var buildGenerator = new MakeTask (processManager) {
Jenkins = this,
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "..", "src", "generator.sln"))),
SpecifyPlatform = false,
@ -1124,7 +1124,7 @@ namespace Xharness.Jenkins
};
Tasks.Add (runGenerator);
var buildDotNetGenerator = new DotNetBuildTask {
var buildDotNetGenerator = new DotNetBuildTask (processManager) {
Jenkins = this,
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "bgen", "bgen-tests.csproj"))),
SpecifyPlatform = false,
@ -1140,7 +1140,7 @@ namespace Xharness.Jenkins
};
Tasks.Add (runDotNetGenerator);
var run_mmp = new MakeTask
var run_mmp = new MakeTask (processManager)
{
Jenkins = this,
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.
Tasks.Add (run_mmp);
var runMacBindingProject = new MakeTask
var runMacBindingProject = new MakeTask (processManager)
{
Jenkins = this,
Platform = TestPlatform.Mac,
@ -1171,7 +1171,7 @@ namespace Xharness.Jenkins
};
Tasks.Add (runMacBindingProject);
var buildXtroTests = new MakeTask {
var buildXtroTests = new MakeTask (processManager) {
Jenkins = this,
Platform = TestPlatform.All,
TestName = "Xtro",
@ -1189,7 +1189,7 @@ namespace Xharness.Jenkins
};
Tasks.Add (runXtroReporter);
var buildCecilTests = new MakeTask {
var buildCecilTests = new MakeTask (processManager) {
Jenkins = this,
Platform = TestPlatform.All,
TestName = "Cecil",
@ -1209,7 +1209,7 @@ namespace Xharness.Jenkins
};
Tasks.Add (runCecilTests);
var runDocsTests = new MakeTask {
var runDocsTests = new MakeTask (processManager) {
Jenkins = this,
Platform = TestPlatform.All,
TestName = "Documentation",
@ -1220,7 +1220,7 @@ namespace Xharness.Jenkins
};
Tasks.Add (runDocsTests);
var buildSampleTests = new MSBuildTask {
var buildSampleTests = new MSBuildTask (processManager) {
Jenkins = this,
TestProject = new TestProject (Path.GetFullPath (Path.Combine (Harness.RootDirectory, "sampletester", "sampletester.sln"))),
SpecifyPlatform = false,
@ -1253,7 +1253,7 @@ namespace Xharness.Jenkins
using (var process = new Process ()) {
process.StartInfo.FileName = Harness.PeriodicCommand;
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)
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.
var populate = Task.Run (async () => {
var simulator = new SimulatorDevice (Harness, processManager);
var simulator = new SimulatorDevice (processManager, new TCCDatabase (processManager));
await simulator.KillEverythingAsync (MainLog);
await PopulateTasksAsync ();
populating = false;
@ -1328,7 +1328,7 @@ namespace Xharness.Jenkins
var sb = new StringBuilder ();
var callback_log = new CallbackLog ((v) => sb.Append (v));
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;
if (!per.Succeeded) {
// Only show the log if something went wrong.

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

@ -4,6 +4,7 @@ using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Xml;
using Xharness.Execution;
using Xharness.Logging;
using Xharness.Utilities;
@ -13,6 +14,10 @@ namespace Xharness.Jenkins.TestTasks
{
public string SolutionPath;
protected BuildProjectTask (IProcessManager processManager) : base (processManager)
{
}
public bool RestoreNugets {
get {
return TestProject.RestoreNugetsInProject || !string.IsNullOrEmpty (SolutionPath);

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

@ -6,9 +6,15 @@ namespace Xharness.Jenkins.TestTasks
{
public abstract class BuildToolTask : TestTask
{
protected readonly IProcessManager ProcessManager;
public bool SpecifyPlatform = 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 {
get { return Platform.ToString (); }

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

@ -1,10 +1,10 @@
using System.Collections.Generic;
using System.Diagnostics;
using Xharness.Execution;
namespace Xharness.Jenkins.TestTasks {
class DotNetBuildTask : MSBuildTask {
public DotNetBuildTask ()
public DotNetBuildTask (IProcessManager processManager) : base (processManager)
{
SetDotNetEnvironmentVariables (Environment);
}

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

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Xml;
using Xharness.Execution;
using Xharness.Logging;
using Xharness.Utilities;
@ -31,6 +32,10 @@ namespace Xharness.Jenkins.TestTasks
}
}
public MSBuildTask (IProcessManager processManager) : base (processManager)
{
}
protected override async Task ExecuteAsync ()
{
using (var resource = await NotifyAndAcquireDesktopResourceAsync ()) {

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

@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Xharness.Execution;
using Xharness.Logging;
namespace Xharness.Jenkins.TestTasks
@ -11,6 +12,10 @@ namespace Xharness.Jenkins.TestTasks
public string WorkingDirectory;
public TimeSpan Timeout = TimeSpan.FromMinutes (5);
public MakeTask (IProcessManager processManager) : base (processManager)
{
}
protected override async Task ExecuteAsync ()
{
using (var resource = await NotifyAndAcquireDesktopResourceAsync ()) {

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

@ -11,9 +11,9 @@ namespace Xharness.Jenkins.TestTasks
{
class RunDeviceTask : RunXITask<IHardwareDevice>
{
readonly IProcessManager processManager = new ProcessManager ();
readonly IResultParser resultParser = new XmlResultParser ();
readonly IDeviceLoader devices;
AppInstallMonitorLog install_log;
public override string ProgressMessage {
@ -81,14 +81,14 @@ namespace Xharness.Jenkins.TestTasks
CompanionDevice = devices.FindCompanionDevice (Jenkins.DeviceLoadLog, Device);
Jenkins.MainLog.WriteLine ("Acquired device '{0}' for '{1}'", Device.Name, ProjectFile);
runner = new AppRunner (processManager,
runner = new AppRunner (ProcessManager,
new AppBundleInformationParser (),
new SimulatorsLoaderFactory (Harness, processManager),
new SimulatorsLoaderFactory (ProcessManager),
new SimpleListenerFactory (),
new DeviceLoaderFactory (Harness, processManager),
new CrashSnapshotReporterFactory (ProcessManager, Harness.XcodeRoot, Harness.MlaunchPath),
new DeviceLoaderFactory (ProcessManager),
new CrashSnapshotReporterFactory (ProcessManager),
new CaptureLogFactory (),
new DeviceLogCapturerFactory (processManager, Harness.XcodeRoot, Harness.MlaunchPath),
new DeviceLogCapturerFactory (ProcessManager),
new TestReporterFactory (),
AppRunnerTarget,
Harness,
@ -148,14 +148,14 @@ namespace Xharness.Jenkins.TestTasks
// 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).
AppRunner todayRunner = new AppRunner (processManager,
AppRunner todayRunner = new AppRunner (ProcessManager,
new AppBundleInformationParser (),
new SimulatorsLoaderFactory (Harness, processManager),
new SimulatorsLoaderFactory (ProcessManager),
new SimpleListenerFactory (),
new DeviceLoaderFactory (Harness, processManager),
new CrashSnapshotReporterFactory (ProcessManager, Harness.XcodeRoot, Harness.MlaunchPath),
new DeviceLoaderFactory (ProcessManager),
new CrashSnapshotReporterFactory (ProcessManager),
new CaptureLogFactory (),
new DeviceLogCapturerFactory (processManager, Harness.XcodeRoot, Harness.MlaunchPath),
new DeviceLogCapturerFactory (ProcessManager),
new TestReporterFactory (),
AppRunnerTarget,
Harness,

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

@ -13,7 +13,6 @@ namespace Xharness.Jenkins.TestTasks
{
class RunSimulatorTask : RunXITask<ISimulatorDevice>
{
readonly IProcessManager processManager = new ProcessManager ();
readonly ISimulatorsLoader simulators;
public IAcquiredResource AcquiredResource;
@ -77,14 +76,14 @@ namespace Xharness.Jenkins.TestTasks
await FindSimulatorAsync ();
var clean_state = false;//Platform == TestPlatform.watchOS;
runner = new AppRunner (processManager,
runner = new AppRunner (ProcessManager,
new AppBundleInformationParser (),
new SimulatorsLoaderFactory (Harness, processManager),
new SimulatorsLoaderFactory (ProcessManager),
new SimpleListenerFactory (),
new DeviceLoaderFactory (Harness, processManager),
new CrashSnapshotReporterFactory (ProcessManager, Harness.XcodeRoot, Harness.MlaunchPath),
new DeviceLoaderFactory (ProcessManager),
new CrashSnapshotReporterFactory (ProcessManager),
new CaptureLogFactory (),
new DeviceLogCapturerFactory (processManager, Harness.XcodeRoot, Harness.MlaunchPath),
new DeviceLogCapturerFactory (ProcessManager),
new TestReporterFactory (),
AppRunnerTarget,
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.
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 ();
}

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

@ -40,7 +40,7 @@ namespace Xharness.Tests.Execution.Tests {
stdoutLog = new LogFile ("my stdout log", stdoutLogPath);
stderrLog = new LogFile ("my stderr log", stderrLogPath);
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.StartInfo.FileName = "mono";
}
@ -112,7 +112,7 @@ namespace Xharness.Tests.Execution.Tests {
{
var source = new CancellationTokenSource ();
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)
Assert.AreEqual (resultCode, result.ExitCode, "exit code");
Assert.AreEqual (success, result.Succeeded, "success");

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

@ -20,16 +20,14 @@ namespace Xharness.Tests.Hardware.Tests {
Devices devices;
string mlaunchPath;
string sdkPath;
Mock<IHarness> harness;
Mock<IProcessManager> processManager;
Mock<ILog> executionLog;
[SetUp]
public void SetUp ()
{
harness = new Mock<IHarness> ();
processManager = new Mock<IProcessManager> ();
devices = new Devices (harness.Object, processManager.Object);
devices = new Devices (processManager.Object);
executionLog = new Mock<ILog> ();
mlaunchPath = "/usr/bin/mlaunch"; // any will be ok, is mocked
sdkPath = "/Applications/Xcode.app";
@ -38,7 +36,6 @@ namespace Xharness.Tests.Hardware.Tests {
[TearDown]
public void TearDown ()
{
harness = null;
processManager = null;
executionLog = null;
devices = null;
@ -50,10 +47,7 @@ namespace Xharness.Tests.Hardware.Tests {
{
string processPath = 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
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) => {
@ -87,10 +81,7 @@ namespace Xharness.Tests.Hardware.Tests {
{
string processPath = 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
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) => {

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

@ -14,7 +14,6 @@ namespace Xharness.Tests.Hardware.Tests {
Mock<ILog> executionLog;
Mock<IProcessManager> processManager;
Mock<IHarness> harness;
SimulatorDevice simulator;
[SetUp]
@ -22,8 +21,7 @@ namespace Xharness.Tests.Hardware.Tests {
{
executionLog = new Mock<ILog> ();
processManager = new Mock<IProcessManager> ();
harness = new Mock<IHarness> ();
simulator = new SimulatorDevice (harness.Object, processManager.Object) {
simulator = new SimulatorDevice (processManager.Object, new TCCDatabase (processManager.Object)) {
UDID = Guid.NewGuid ().ToString ()
};
}
@ -57,10 +55,10 @@ namespace Xharness.Tests.Hardware.Tests {
{
// just call and verify the correct args are pass
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> ()));
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> ()));
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> ()));
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> ()));
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> ()));
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> ()));
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);
// 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]
@ -81,7 +79,7 @@ namespace Xharness.Tests.Hardware.Tests {
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);
// 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 sdkPath;
Mock<IHarness> harness;
Mock<ILog> executionLog;
Mock<IProcessManager> processManager;
Simulators simulators;
@ -29,10 +28,9 @@ namespace Xharness.Tests.Hardware.Tests {
{
mlaunchPath = "/usr/bin/mlaunch"; // any will be ok, is mocked
sdkPath = "/Applications/Xcode.app";
harness = new Mock<IHarness> ();
executionLog = new Mock<ILog> ();
processManager = new Mock<IProcessManager> ();
simulators = new Simulators (harness.Object, processManager.Object);
simulators = new Simulators (processManager.Object);
}
[TearDown]
@ -49,10 +47,7 @@ namespace Xharness.Tests.Hardware.Tests {
{
string processPath = 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
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) => {
@ -97,10 +92,7 @@ namespace Xharness.Tests.Hardware.Tests {
{
string processPath = 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
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) => {
@ -141,11 +133,8 @@ namespace Xharness.Tests.Hardware.Tests {
{
string processPath = 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);
harness
processManager
.Setup (h => h.ExecuteXcodeCommandAsync ("simctl", It.Is<string []> (args => args[0] == "create"), executionLog.Object, TimeSpan.FromMinutes (1)))
.ReturnsAsync (new ProcessExecutionResult () { ExitCode = 0 });

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

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@ -25,9 +24,7 @@ namespace Xharness.Tests.Hardware.Tests {
public void SetUp ()
{
processManager = new Mock<IProcessManager> ();
database = new TCCDatabase {
ProcessManager = processManager.Object,
};
database = new TCCDatabase (processManager.Object);
executionLog = new Mock<ILog> ();
simRuntime = "com.apple.CoreSimulator.SimRuntime.iOS-12-1";
dataPath = "/path/to/my/data";

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

@ -218,9 +218,7 @@ namespace Xharness.Tests {
[Test]
public async Task InstallOnDeviceTest ()
{
var harness = Mock.Of<IHarness> (x => x.XcodeRoot == "/path/to/xcode"
&& x.MlaunchPath == "/path/to/mlaunch"
&& x.Verbosity == 2);
var harness = Mock.Of<IHarness> (x => x.Verbosity == 2);
var processResult = new ProcessExecutionResult () { ExitCode = 1, TimedOut = false };
processManager.SetReturnsDefault (Task.FromResult (processResult));
@ -250,12 +248,9 @@ namespace Xharness.Tests {
// Verify
Assert.AreEqual (1, result.ExitCode);
var expectedArgs = $"--sdkroot /path/to/xcode -v -v -v " +
$"--installdev {StringUtils.FormatArguments (appPath)} " +
$"--devname \"Test iPad\"";
var expectedArgs = $"-v -v -v --installdev {StringUtils.FormatArguments (appPath)} --devname \"Test iPad\"";
processManager.Verify (x => x.ExecuteCommandAsync (
"/path/to/mlaunch",
It.Is<MlaunchArguments> (args => args.AsCommandLine() == expectedArgs),
mainLog.Object,
TimeSpan.FromHours (1),
@ -266,9 +261,7 @@ namespace Xharness.Tests {
[Test]
public async Task UninstallFromDeviceTest ()
{
var harness = Mock.Of<IHarness> (x => x.XcodeRoot == "/path/to/xcode"
&& x.MlaunchPath == "/path/to/mlaunch"
&& x.Verbosity == 1);
var harness = Mock.Of<IHarness> (x => x.Verbosity == 1);
var processResult = new ProcessExecutionResult () { ExitCode = 3, TimedOut = false };
processManager.SetReturnsDefault (Task.FromResult (processResult));
@ -297,12 +290,9 @@ namespace Xharness.Tests {
// Verify
Assert.AreEqual (3, result.ExitCode);
var expectedArgs = $"--sdkroot /path/to/xcode -v -v " +
$"--uninstalldevbundleid {StringUtils.FormatArguments (appName)} " +
$"--devname \"Test iPad\"";
var expectedArgs = $"-v -v --uninstalldevbundleid {StringUtils.FormatArguments (appName)} --devname \"Test iPad\"";
processManager.Verify (x => x.ExecuteCommandAsync (
"/path/to/mlaunch",
It.Is<MlaunchArguments> (args => args.AsCommandLine() == expectedArgs),
mainLog.Object,
TimeSpan.FromMinutes (1),
@ -461,7 +451,6 @@ namespace Xharness.Tests {
processManager
.Setup (x => x.ExecuteCommandAsync (
mlaunchPath,
It.Is<MlaunchArguments> (args => args.AsCommandLine() == expectedArgs),
mainLog.Object,
TimeSpan.FromMinutes (harness.Timeout * 2),
@ -612,7 +601,7 @@ namespace Xharness.Tests {
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 " +
$"-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} " +
@ -622,7 +611,6 @@ namespace Xharness.Tests {
processManager
.Setup (x => x.ExecuteCommandAsync (
mlaunchPath,
It.Is<MlaunchArguments> (args => args.AsCommandLine () == expectedArgs),
It.IsAny<ILog> (),
TimeSpan.FromMinutes (harness.Timeout * 2),
@ -633,18 +621,18 @@ namespace Xharness.Tests {
var xmlResultFile = Path.ChangeExtension (testResultFilePath, "xml");
var testReporterFactory = new Mock<ITestReporterFactory> ();
var testReporter = new Mock<ITestReporter> ();
testReporterFactory.Setup (f => f.Create (
testReporterFactory
.Setup (f => f.Create (
It.IsAny<IAppRunner> (),
It.IsAny<string> (),
"Test iPad",
It.IsAny<ISimpleListener> (),
It.IsAny<ILog> (),
It.IsAny<ICrashSnapshotReporter> (),
It.IsAny<IResultParser> ())).Returns (testReporter.Object);
mainLog.Object,
snapshotReporter.Object,
It.IsAny<IResultParser> ()))
.Returns (testReporter.Object);
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.ParseResult ()).Returns (() => {
return Task.FromResult<(TestExecutingResult, string)> ((TestExecutingResult.Succeeded, null));
});
testReporter.Setup (r => r.ParseResult ()).Returns (() => Task.FromResult<(TestExecutingResult, string)> ((TestExecutingResult.Succeeded, null)));
testReporter.Setup (r => r.Success).Returns (true);
// Act
@ -728,7 +716,7 @@ namespace Xharness.Tests {
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 " +
$"-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} " +
@ -738,7 +726,6 @@ namespace Xharness.Tests {
processManager
.Setup (x => x.ExecuteCommandAsync (
mlaunchPath,
It.Is<MlaunchArguments> (args => args.AsCommandLine () == expectedArgs),
It.IsAny<ILog> (),
TimeSpan.FromMinutes (harness.Timeout * 2),
@ -749,13 +736,15 @@ namespace Xharness.Tests {
var xmlResultFile = Path.ChangeExtension (testResultFilePath, "xml");
var testReporterFactory = new Mock<ITestReporterFactory> ();
var testReporter = new Mock<ITestReporter> ();
testReporterFactory.Setup (f => f.Create (
testReporterFactory
.Setup (f => f.Create (
It.IsAny<IAppRunner> (),
It.IsAny<string> (),
"Test iPad",
It.IsAny<ISimpleListener> (),
It.IsAny<ILog> (),
It.IsAny<ICrashSnapshotReporter> (),
It.IsAny<IResultParser> ())).Returns (testReporter.Object);
mainLog.Object,
snapshotReporter.Object,
It.IsAny<IResultParser> ()))
.Returns (testReporter.Object);
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.ParseResult ()).Returns (() => {
@ -802,11 +791,8 @@ namespace Xharness.Tests {
IHarness GetMockedHarness ()
{
return Mock.Of<IHarness> (x => x.Action == HarnessAction.Run
&& x.XcodeRoot == xcodePath
&& x.MlaunchPath == mlaunchPath
&& x.Verbosity == 1
&& x.HarnessLog == mainLog.Object
&& x.LogDirectory == logs.Object.Directory
&& x.InCI == false
&& x.EnvironmentVariables == new Dictionary<string, string> () {
{ "env1", "value1" },

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

@ -12,8 +12,8 @@ using Xharness.Utilities;
namespace Xharness.Tests {
[TestFixture]
public class CrashSnapshotReporterTests {
readonly string mlaunchPath = "./mlaunch";
public class CrashReportSnapshotTests {
string tempXcodeRoot;
string symbolicatePath;
@ -31,6 +31,9 @@ namespace Xharness.Tests {
tempXcodeRoot = Path.Combine (Path.GetTempPath (), Guid.NewGuid ().ToString ());
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
Directory.CreateDirectory (tempXcodeRoot);
@ -71,8 +74,6 @@ namespace Xharness.Tests {
var snapshotReport = new CrashSnapshotReporter (processManager.Object,
log.Object,
logs.Object,
tempXcodeRoot,
mlaunchPath,
true,
deviceName,
() => tempFilePath);
@ -91,10 +92,9 @@ namespace Xharness.Tests {
// List of crash reports is retrieved
processManager.Verify (
x => x.ExecuteCommandAsync (
mlaunchPath,
It.Is<MlaunchArguments> (args => args.AsCommandLine () ==
StringUtils.FormatArguments ($"--list-crash-reports={tempFilePath}") + " " +
$"--sdkroot {StringUtils.FormatArguments (tempXcodeRoot)} " +
StringUtils.FormatArguments (
$"--list-crash-reports={tempFilePath}") + " " +
$"--devname {StringUtils.FormatArguments (deviceName)}"),
log.Object,
TimeSpan.FromMinutes (1),
@ -105,11 +105,10 @@ namespace Xharness.Tests {
// Device crash log is downloaded
processManager.Verify (
x => x.ExecuteCommandAsync (
mlaunchPath,
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}") + " " +
$"--sdkroot {StringUtils.FormatArguments (tempXcodeRoot)} " +
$"--devname {StringUtils.FormatArguments (deviceName)}"),
log.Object,
TimeSpan.FromMinutes (1),