Commit 54becbf3 authored by mattijsf's avatar mattijsf Committed by Todd Volkert

Ignore unreachable iOS devices in IOSDevice.getAttachedDevices (#23776)

parent b8c29a14
...@@ -29,3 +29,4 @@ Lukasz Piliszczuk <lukasz@intheloup.io> ...@@ -29,3 +29,4 @@ Lukasz Piliszczuk <lukasz@intheloup.io>
Felix Schmidt <felix.free@gmx.de> Felix Schmidt <felix.free@gmx.de>
Artur Rymarz <artur.rymarz@gmail.com> Artur Rymarz <artur.rymarz@gmail.com>
Stefan Mitev <mr.mitew@gmail.com> Stefan Mitev <mr.mitew@gmail.com>
Mattijs Fuijkschot <mattijs.fuijkschot@gmail.com>
...@@ -149,9 +149,14 @@ class IOSDevice extends Device { ...@@ -149,9 +149,14 @@ class IOSDevice extends Device {
if (id.isEmpty) if (id.isEmpty)
continue; continue;
final String deviceName = await iMobileDevice.getInfoForDevice(id, 'DeviceName'); try {
final String sdkVersion = await iMobileDevice.getInfoForDevice(id, 'ProductVersion'); final String deviceName = await iMobileDevice.getInfoForDevice(id, 'DeviceName');
devices.add(IOSDevice(id, name: deviceName, sdkVersion: sdkVersion)); final String sdkVersion = await iMobileDevice.getInfoForDevice(id, 'ProductVersion');
devices.add(IOSDevice(id, name: deviceName, sdkVersion: sdkVersion));
} on IOSDeviceNotFoundError catch (error) {
// Unable to find device with given udid. Possibly a network device.
printTrace('Error getting attached iOS device: $error');
}
} }
return devices; return devices;
} }
......
...@@ -83,6 +83,17 @@ class PropertyList { ...@@ -83,6 +83,17 @@ class PropertyList {
} }
} }
/// Specialized exception for expected situations where the ideviceinfo
/// tool responds with exit code 255 / 'No device found' message
class IOSDeviceNotFoundError implements Exception {
IOSDeviceNotFoundError(this.message);
final String message;
@override
String toString() => message;
}
class IMobileDevice { class IMobileDevice {
const IMobileDevice(); const IMobileDevice();
...@@ -118,11 +129,13 @@ class IMobileDevice { ...@@ -118,11 +129,13 @@ class IMobileDevice {
Future<String> getInfoForDevice(String deviceID, String key) async { Future<String> getInfoForDevice(String deviceID, String key) async {
try { try {
final ProcessResult result = await processManager.run(<String>['ideviceinfo', '-u', deviceID, '-k', key, '--simple']); final ProcessResult result = await processManager.run(<String>['ideviceinfo', '-u', deviceID, '-k', key, '--simple']);
if (result.exitCode == 255 && result.stdout != null && result.stdout.contains('No device found'))
throw IOSDeviceNotFoundError('ideviceinfo could not find device:\n${result.stdout}');
if (result.exitCode != 0) if (result.exitCode != 0)
throw ToolExit('idevice_id returned an error:\n${result.stderr}'); throw ToolExit('ideviceinfo returned an error:\n${result.stderr}');
return result.stdout.trim(); return result.stdout.trim();
} on ProcessException { } on ProcessException {
throw ToolExit('Failed to invoke idevice_id. Run flutter doctor.'); throw ToolExit('Failed to invoke ideviceinfo. Run flutter doctor.');
} }
} }
......
...@@ -77,6 +77,25 @@ f577a7903cc54959be2e34bc4f7f80b7009efcf4 ...@@ -77,6 +77,25 @@ f577a7903cc54959be2e34bc4f7f80b7009efcf4
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
IMobileDevice: () => mockIMobileDevice, IMobileDevice: () => mockIMobileDevice,
}); });
testUsingContext('returns attached devices and ignores devices that cannot be found by ideviceinfo', () async {
when(iMobileDevice.isInstalled).thenReturn(true);
when(iMobileDevice.getAvailableDeviceIDs())
.thenAnswer((Invocation invocation) => Future<String>.value('''
98206e7a4afd4aedaff06e687594e089dede3c44
f577a7903cc54959be2e34bc4f7f80b7009efcf4
'''));
when(iMobileDevice.getInfoForDevice('98206e7a4afd4aedaff06e687594e089dede3c44', 'DeviceName'))
.thenAnswer((_) => Future<String>.value('La tele me regarde'));
when(iMobileDevice.getInfoForDevice('f577a7903cc54959be2e34bc4f7f80b7009efcf4', 'DeviceName'))
.thenThrow(IOSDeviceNotFoundError('Device not found'));
final List<IOSDevice> devices = await IOSDevice.getAttachedDevices();
expect(devices, hasLength(1));
expect(devices[0].id, '98206e7a4afd4aedaff06e687594e089dede3c44');
expect(devices[0].name, 'La tele me regarde');
}, overrides: <Type, Generator>{
IMobileDevice: () => mockIMobileDevice,
});
}); });
group('decodeSyslog', () { group('decodeSyslog', () {
......
...@@ -127,6 +127,14 @@ void main() { ...@@ -127,6 +127,14 @@ void main() {
ProcessManager: () => mockProcessManager, ProcessManager: () => mockProcessManager,
}); });
testUsingContext('getInfoForDevice throws IOSDeviceNotFoundError when ideviceinfo returns specific error code and message', () async {
when(mockProcessManager.run(<String>['ideviceinfo', '-u', 'foo', '-k', 'bar', '--simple']))
.thenAnswer((_) => Future<ProcessResult>.value(ProcessResult(1, 255, 'No device found with udid foo, is it plugged in?', '')));
expect(() async => await iMobileDevice.getInfoForDevice('foo', 'bar'), throwsA(isInstanceOf<IOSDeviceNotFoundError>()));
}, overrides: <Type, Generator>{
ProcessManager: () => mockProcessManager,
});
group('screenshot', () { group('screenshot', () {
final String outputPath = fs.path.join('some', 'test', 'path', 'image.png'); final String outputPath = fs.path.join('some', 'test', 'path', 'image.png');
MockProcessManager mockProcessManager; MockProcessManager mockProcessManager;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment