[xharness] Handle failure to create a device pair for the simulator better. Fixes xamarin/maccore#830.

Detect if we failed to create a simulator device pair due to trying with a
watch that's already paired. We were already detecting this scenario if the
watch was a member of an available pair, but not if the watch was a member of
an _unavailable_ pair (since mlaunch doesn't list unavailable device pairs).

So detect this scenario from the error message simctl gives us instead, and in
that case create a new watch device and try to create the pair again.

Fixes https://github.com/xamarin/maccore/issues/830.
This commit is contained in:
Rolf Bjarne Kvinge 2018-05-31 17:48:55 +02:00
Родитель 30d644d5a1
Коммит 11a23af2de
2 изменённых файлов: 43 добавлений и 20 удалений

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

@ -25,7 +25,7 @@ namespace xharness
public abstract string FullPath { get; }
protected virtual void WriteImpl (string value)
internal protected virtual void WriteImpl (string value)
{
Write (Encoding.UTF8.GetBytes (value));
}
@ -100,7 +100,7 @@ namespace xharness
public override string FullPath => throw new NotImplementedException ();
protected override void WriteImpl (string value)
internal protected override void WriteImpl (string value)
{
foreach (var log in logs)
log.WriteImpl (value);
@ -258,7 +258,7 @@ namespace xharness
{
}
protected override void WriteImpl (string value)
internal protected override void WriteImpl (string value)
{
captured.Append (value);
Console.Write (value);
@ -373,7 +373,7 @@ namespace xharness
Capture ();
}
protected override void WriteImpl (string value)
internal protected override void WriteImpl (string value)
{
throw new InvalidOperationException ();
}
@ -398,7 +398,7 @@ namespace xharness
public override string FullPath => throw new NotImplementedException ();
protected override void WriteImpl (string value)
internal protected override void WriteImpl (string value)
{
OnWrite (value);
}

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

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
@ -151,6 +152,39 @@ namespace xharness
return devices;
}
async Task<bool> CreateDevicePair (Log log, SimDevice device, SimDevice companion_device, string runtime, string devicetype, bool create_device)
{
if (create_device) {
// watch device is already paired to some other phone. Create a new watch device
var matchingDevices = await FindOrCreateDevicesAsync (log, runtime, devicetype, force: true);
var unPairedDevices = matchingDevices.Where ((v) => !AvailableDevicePairs.Any ((SimDevicePair p) => { return p.Gizmo == v.UDID; }));
if (device != null) {
// If we're creating a new watch device, assume that the one we were given is not usable.
unPairedDevices = unPairedDevices.Where ((v) => v.UDID != device.UDID);
}
if (unPairedDevices?.Any () != true)
return false;
device = unPairedDevices.First ();
}
log.WriteLine ($"Creating device pair for '{device.Name}' and '{companion_device.Name}'");
var capturedLog = new StringBuilder ();
var pairLog = new CallbackLog ((string value) => {
log.WriteImpl (value);
capturedLog.Append (value);
});
var rv = await Harness.ExecuteXcodeCommandAsync ("simctl", $"pair {device.UDID} {companion_device.UDID}", pairLog, TimeSpan.FromMinutes (1));
if (!rv.Succeeded) {
if (!create_device && capturedLog.ToString ().Contains ("At least one of the requested devices is already paired with the maximum number of supported devices and cannot accept another pairing.")) {
log.WriteLine ($"Could not create device pair for '{device.Name}' ({device.UDID}) and '{companion_device.Name}' ({companion_device.UDID}), but will create a new watch device and try again.");
return await CreateDevicePair (log, device, companion_device, runtime, devicetype, true);
}
log.WriteLine ($"Could not create device pair for '{device.Name}' ({device.UDID}) and '{companion_device.Name}' ({companion_device.UDID})");
return false;
}
return true;
}
async Task<SimDevicePair> FindOrCreateDevicePairAsync (Log log, IEnumerable<SimDevice> devices, IEnumerable<SimDevice> companion_devices)
{
// Check if we already have a device pair with the specified devices
@ -166,23 +200,12 @@ namespace xharness
// No device pair. Create one.
// First check if the watch is already paired
var unPairedDevices = devices.Where ((v) => !AvailableDevicePairs.Any ((SimDevicePair p) => { return p.Gizmo == v.UDID; }));
var device = unPairedDevices.FirstOrDefault ();
if (device == null) {
// watch device is already paired. Create a new device
var pairedDevice = devices.First ();
var matchingDevices = await FindOrCreateDevicesAsync (log, pairedDevice.SimRuntime, pairedDevice.SimDeviceType, force: true);
unPairedDevices = matchingDevices.Where ((v) => !AvailableDevicePairs.Any ((SimDevicePair p) => { return p.Gizmo == v.UDID; }));
if (unPairedDevices?.Any () != true)
return null;
device = unPairedDevices.First ();
}
var unpairedDevice = unPairedDevices.FirstOrDefault ();
var companion_device = companion_devices.First ();
log.WriteLine ($"Creating device pair for '{device.Name}' and '{companion_device.Name}'");
var rv = await Harness.ExecuteXcodeCommandAsync ("simctl", $"pair {device.UDID} {companion_device.UDID}", log, TimeSpan.FromMinutes (1));
if (!rv.Succeeded) {
log.WriteLine ($"Could not create device pair for '{device.Name}' ({device.UDID}) and '{companion_device.Name}' ({companion_device.UDID})");
var device = devices.First ();
if (!await CreateDevicePair (log, unpairedDevice, companion_device, device.SimRuntime, device.SimDeviceType, device == null))
return null;
}
await LoadAsync (log, force: true);
pairs = AvailableDevicePairs.Where ((SimDevicePair pair) => {