Fix duplicate devices from xcdevice with iOS 17 (#128802)
This PR fixes issue of duplicate entries from `xcdevice list` cause devices to not show in `flutter devices`, `flutter run`, etc. When a duplicate entry is found, use the entry without errors as the authority. If both have errors, use the one with the higher SDK as the authority. Fixes https://github.com/flutter/flutter/issues/128719.
This commit is contained in:
parent
fadcaee842
commit
25e98b54d7
@ -16,6 +16,7 @@ import '../base/logger.dart';
|
|||||||
import '../base/os.dart';
|
import '../base/os.dart';
|
||||||
import '../base/platform.dart';
|
import '../base/platform.dart';
|
||||||
import '../base/utils.dart';
|
import '../base/utils.dart';
|
||||||
|
import '../base/version.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../convert.dart';
|
import '../convert.dart';
|
||||||
import '../device.dart';
|
import '../device.dart';
|
||||||
@ -295,10 +296,13 @@ class IOSDevice extends Device {
|
|||||||
final IMobileDevice _iMobileDevice;
|
final IMobileDevice _iMobileDevice;
|
||||||
final IProxy _iproxy;
|
final IProxy _iproxy;
|
||||||
|
|
||||||
|
Version? get sdkVersion {
|
||||||
|
return Version.parse(_sdkVersion);
|
||||||
|
}
|
||||||
|
|
||||||
/// May be 0 if version cannot be parsed.
|
/// May be 0 if version cannot be parsed.
|
||||||
int get majorSdkVersion {
|
int get majorSdkVersion {
|
||||||
final String? majorVersionString = _sdkVersion?.split('.').first.trim();
|
return sdkVersion?.major ?? 0;
|
||||||
return majorVersionString != null ? int.tryParse(majorVersionString) ?? 0 : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -12,6 +12,7 @@ import '../base/io.dart';
|
|||||||
import '../base/logger.dart';
|
import '../base/logger.dart';
|
||||||
import '../base/platform.dart';
|
import '../base/platform.dart';
|
||||||
import '../base/process.dart';
|
import '../base/process.dart';
|
||||||
|
import '../base/version.dart';
|
||||||
import '../build_info.dart';
|
import '../build_info.dart';
|
||||||
import '../cache.dart';
|
import '../cache.dart';
|
||||||
import '../convert.dart';
|
import '../convert.dart';
|
||||||
@ -493,7 +494,7 @@ class XCDevice {
|
|||||||
// },
|
// },
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
final List<IOSDevice> devices = <IOSDevice>[];
|
final Map<String, IOSDevice> deviceMap = <String, IOSDevice>{};
|
||||||
for (final Object device in allAvailableDevices) {
|
for (final Object device in allAvailableDevices) {
|
||||||
if (device is Map<String, Object?>) {
|
if (device is Map<String, Object?>) {
|
||||||
// Only include iPhone, iPad, iPod, or other iOS devices.
|
// Only include iPhone, iPad, iPod, or other iOS devices.
|
||||||
@ -531,33 +532,57 @@ class XCDevice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String? sdkVersion = _sdkVersion(device);
|
String? sdkVersionString = _sdkVersion(device);
|
||||||
|
|
||||||
if (sdkVersion != null) {
|
if (sdkVersionString != null) {
|
||||||
final String? buildVersion = _buildVersion(device);
|
final String? buildVersion = _buildVersion(device);
|
||||||
if (buildVersion != null) {
|
if (buildVersion != null) {
|
||||||
sdkVersion = '$sdkVersion $buildVersion';
|
sdkVersionString = '$sdkVersionString $buildVersion';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
devices.add(IOSDevice(
|
// Duplicate entries started appearing in Xcode 15, possibly due to
|
||||||
|
// Xcode's new device connectivity stack.
|
||||||
|
// If a duplicate entry is found in `xcdevice list`, don't overwrite
|
||||||
|
// existing entry when the existing entry indicates the device is
|
||||||
|
// connected and the current entry indicates the device is not connected.
|
||||||
|
// Don't overwrite if current entry's sdkVersion is null.
|
||||||
|
// Don't overwrite if both entries indicate the device is not
|
||||||
|
// connected and the existing entry has a higher sdkVersion.
|
||||||
|
if (deviceMap.containsKey(identifier)) {
|
||||||
|
final IOSDevice deviceInMap = deviceMap[identifier]!;
|
||||||
|
if ((deviceInMap.isConnected && !isConnected) || sdkVersionString == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Version? sdkVersion = Version.parse(sdkVersionString);
|
||||||
|
if (!deviceInMap.isConnected &&
|
||||||
|
!isConnected &&
|
||||||
|
sdkVersion != null &&
|
||||||
|
deviceInMap.sdkVersion != null &&
|
||||||
|
deviceInMap.sdkVersion!.compareTo(sdkVersion) > 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceMap[identifier] = IOSDevice(
|
||||||
identifier,
|
identifier,
|
||||||
name: name,
|
name: name,
|
||||||
cpuArchitecture: _cpuArchitecture(device),
|
cpuArchitecture: _cpuArchitecture(device),
|
||||||
connectionInterface: _interfaceType(device),
|
connectionInterface: _interfaceType(device),
|
||||||
isConnected: isConnected,
|
isConnected: isConnected,
|
||||||
sdkVersion: sdkVersion,
|
sdkVersion: sdkVersionString,
|
||||||
iProxy: _iProxy,
|
iProxy: _iProxy,
|
||||||
fileSystem: globals.fs,
|
fileSystem: globals.fs,
|
||||||
logger: _logger,
|
logger: _logger,
|
||||||
iosDeploy: _iosDeploy,
|
iosDeploy: _iosDeploy,
|
||||||
iMobileDevice: _iMobileDevice,
|
iMobileDevice: _iMobileDevice,
|
||||||
platform: globals.platform,
|
platform: globals.platform,
|
||||||
devModeEnabled: devModeEnabled
|
devModeEnabled: devModeEnabled,
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return devices;
|
return deviceMap.values.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Despite the name, com.apple.platform.iphoneos includes iPhone, iPads, and all iOS devices.
|
/// Despite the name, com.apple.platform.iphoneos includes iPhone, iPads, and all iOS devices.
|
||||||
|
@ -13,6 +13,7 @@ import 'package:flutter_tools/src/base/io.dart';
|
|||||||
import 'package:flutter_tools/src/base/logger.dart';
|
import 'package:flutter_tools/src/base/logger.dart';
|
||||||
import 'package:flutter_tools/src/base/os.dart';
|
import 'package:flutter_tools/src/base/os.dart';
|
||||||
import 'package:flutter_tools/src/base/platform.dart';
|
import 'package:flutter_tools/src/base/platform.dart';
|
||||||
|
import 'package:flutter_tools/src/base/version.dart';
|
||||||
import 'package:flutter_tools/src/build_info.dart';
|
import 'package:flutter_tools/src/build_info.dart';
|
||||||
import 'package:flutter_tools/src/cache.dart';
|
import 'package:flutter_tools/src/cache.dart';
|
||||||
import 'package:flutter_tools/src/device.dart';
|
import 'package:flutter_tools/src/device.dart';
|
||||||
@ -177,6 +178,121 @@ void main() {
|
|||||||
).majorSdkVersion, 0);
|
).majorSdkVersion, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWithoutContext('parses sdk version', () {
|
||||||
|
Version? sdkVersion = IOSDevice(
|
||||||
|
'device-123',
|
||||||
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: logger,
|
||||||
|
platform: macPlatform,
|
||||||
|
iosDeploy: iosDeploy,
|
||||||
|
iMobileDevice: iMobileDevice,
|
||||||
|
name: 'iPhone 1',
|
||||||
|
cpuArchitecture: DarwinArch.arm64,
|
||||||
|
sdkVersion: '13.3.1',
|
||||||
|
connectionInterface: DeviceConnectionInterface.attached,
|
||||||
|
isConnected: true,
|
||||||
|
devModeEnabled: true,
|
||||||
|
).sdkVersion;
|
||||||
|
Version expectedVersion = Version(13, 3, 1, text: '13.3.1');
|
||||||
|
expect(sdkVersion, isNotNull);
|
||||||
|
expect(sdkVersion!.toString(), expectedVersion.toString());
|
||||||
|
expect(sdkVersion.compareTo(expectedVersion), 0);
|
||||||
|
|
||||||
|
sdkVersion = IOSDevice(
|
||||||
|
'device-123',
|
||||||
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: logger,
|
||||||
|
platform: macPlatform,
|
||||||
|
iosDeploy: iosDeploy,
|
||||||
|
iMobileDevice: iMobileDevice,
|
||||||
|
name: 'iPhone 1',
|
||||||
|
cpuArchitecture: DarwinArch.arm64,
|
||||||
|
sdkVersion: '13.3.1 (20ADBC)',
|
||||||
|
connectionInterface: DeviceConnectionInterface.attached,
|
||||||
|
isConnected: true,
|
||||||
|
devModeEnabled: true,
|
||||||
|
).sdkVersion;
|
||||||
|
expectedVersion = Version(13, 3, 1, text: '13.3.1 (20ADBC)');
|
||||||
|
expect(sdkVersion, isNotNull);
|
||||||
|
expect(sdkVersion!.toString(), expectedVersion.toString());
|
||||||
|
expect(sdkVersion.compareTo(expectedVersion), 0);
|
||||||
|
|
||||||
|
sdkVersion = IOSDevice(
|
||||||
|
'device-123',
|
||||||
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: logger,
|
||||||
|
platform: macPlatform,
|
||||||
|
iosDeploy: iosDeploy,
|
||||||
|
iMobileDevice: iMobileDevice,
|
||||||
|
name: 'iPhone 1',
|
||||||
|
cpuArchitecture: DarwinArch.arm64,
|
||||||
|
sdkVersion: '16.4.1(a) (20ADBC)',
|
||||||
|
connectionInterface: DeviceConnectionInterface.attached,
|
||||||
|
isConnected: true,
|
||||||
|
devModeEnabled: true,
|
||||||
|
).sdkVersion;
|
||||||
|
expectedVersion = Version(16, 4, 1, text: '16.4.1(a) (20ADBC)');
|
||||||
|
expect(sdkVersion, isNotNull);
|
||||||
|
expect(sdkVersion!.toString(), expectedVersion.toString());
|
||||||
|
expect(sdkVersion.compareTo(expectedVersion), 0);
|
||||||
|
|
||||||
|
sdkVersion = IOSDevice(
|
||||||
|
'device-123',
|
||||||
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: logger,
|
||||||
|
platform: macPlatform,
|
||||||
|
iosDeploy: iosDeploy,
|
||||||
|
iMobileDevice: iMobileDevice,
|
||||||
|
name: 'iPhone 1',
|
||||||
|
cpuArchitecture: DarwinArch.arm64,
|
||||||
|
sdkVersion: '0',
|
||||||
|
connectionInterface: DeviceConnectionInterface.attached,
|
||||||
|
isConnected: true,
|
||||||
|
devModeEnabled: true,
|
||||||
|
).sdkVersion;
|
||||||
|
expectedVersion = Version(0, 0, 0, text: '0');
|
||||||
|
expect(sdkVersion, isNotNull);
|
||||||
|
expect(sdkVersion!.toString(), expectedVersion.toString());
|
||||||
|
expect(sdkVersion.compareTo(expectedVersion), 0);
|
||||||
|
|
||||||
|
sdkVersion = IOSDevice(
|
||||||
|
'device-123',
|
||||||
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: logger,
|
||||||
|
platform: macPlatform,
|
||||||
|
iosDeploy: iosDeploy,
|
||||||
|
iMobileDevice: iMobileDevice,
|
||||||
|
name: 'iPhone 1',
|
||||||
|
cpuArchitecture: DarwinArch.arm64,
|
||||||
|
connectionInterface: DeviceConnectionInterface.attached,
|
||||||
|
isConnected: true,
|
||||||
|
devModeEnabled: true,
|
||||||
|
).sdkVersion;
|
||||||
|
expect(sdkVersion, isNull);
|
||||||
|
|
||||||
|
sdkVersion = IOSDevice(
|
||||||
|
'device-123',
|
||||||
|
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: logger,
|
||||||
|
platform: macPlatform,
|
||||||
|
iosDeploy: iosDeploy,
|
||||||
|
iMobileDevice: iMobileDevice,
|
||||||
|
name: 'iPhone 1',
|
||||||
|
cpuArchitecture: DarwinArch.arm64,
|
||||||
|
sdkVersion: 'bogus',
|
||||||
|
connectionInterface: DeviceConnectionInterface.attached,
|
||||||
|
isConnected: true,
|
||||||
|
devModeEnabled: true,
|
||||||
|
).sdkVersion;
|
||||||
|
expect(sdkVersion, isNull);
|
||||||
|
});
|
||||||
|
|
||||||
testWithoutContext('has build number in sdkNameAndVersion', () async {
|
testWithoutContext('has build number in sdkNameAndVersion', () async {
|
||||||
final IOSDevice device = IOSDevice(
|
final IOSDevice device = IOSDevice(
|
||||||
'device-123',
|
'device-123',
|
||||||
|
@ -791,7 +791,7 @@ void main() {
|
|||||||
"available" : true,
|
"available" : true,
|
||||||
"platform" : "com.apple.platform.iphoneos",
|
"platform" : "com.apple.platform.iphoneos",
|
||||||
"modelCode" : "iPhone8,1",
|
"modelCode" : "iPhone8,1",
|
||||||
"identifier" : "d83d5bc53967baa0ee18626ba87b6254b2ab5418",
|
"identifier" : "43ad2fda7991b34fe1acbda82f9e2fd3d6ddc9f7",
|
||||||
"architecture" : "BOGUS",
|
"architecture" : "BOGUS",
|
||||||
"modelName" : "Future iPad",
|
"modelName" : "Future iPad",
|
||||||
"name" : "iPad"
|
"name" : "iPad"
|
||||||
@ -865,6 +865,190 @@ void main() {
|
|||||||
Platform: () => macPlatform,
|
Platform: () => macPlatform,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testUsingContext('use connected entry when filtering out duplicates', () async {
|
||||||
|
const String devicesOutput = '''
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"simulator" : false,
|
||||||
|
"operatingSystemVersion" : "13.3 (17C54)",
|
||||||
|
"interface" : "usb",
|
||||||
|
"available" : false,
|
||||||
|
"platform" : "com.apple.platform.iphoneos",
|
||||||
|
"modelCode" : "iPhone8,1",
|
||||||
|
"identifier" : "c4ca6f7a53027d1b7e4972e28478e7a28e2faee2",
|
||||||
|
"architecture" : "arm64",
|
||||||
|
"modelName" : "iPhone 6s",
|
||||||
|
"name" : "iPhone"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"simulator" : false,
|
||||||
|
"operatingSystemVersion" : "13.3 (17C54)",
|
||||||
|
"interface" : "usb",
|
||||||
|
"available" : false,
|
||||||
|
"platform" : "com.apple.platform.iphoneos",
|
||||||
|
"modelCode" : "iPhone8,1",
|
||||||
|
"identifier" : "c4ca6f7a53027d1b7e4972e28478e7a28e2faee2",
|
||||||
|
"architecture" : "arm64",
|
||||||
|
"modelName" : "iPhone 6s",
|
||||||
|
"name" : "iPhone",
|
||||||
|
"error" : {
|
||||||
|
"code" : -13,
|
||||||
|
"failureReason" : "",
|
||||||
|
"description" : "iPhone iPad is not connected",
|
||||||
|
"recoverySuggestion" : "Xcode will continue when iPhone is connected and unlocked.",
|
||||||
|
"domain" : "com.apple.platform.iphoneos"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
''';
|
||||||
|
|
||||||
|
fakeProcessManager.addCommand(const FakeCommand(
|
||||||
|
command: <String>['xcrun', 'xcdevice', 'list', '--timeout', '2'],
|
||||||
|
stdout: devicesOutput,
|
||||||
|
));
|
||||||
|
final List<IOSDevice> devices = await xcdevice.getAvailableIOSDevices();
|
||||||
|
expect(devices, hasLength(1));
|
||||||
|
|
||||||
|
expect(devices[0].id, 'c4ca6f7a53027d1b7e4972e28478e7a28e2faee2');
|
||||||
|
expect(devices[0].name, 'iPhone');
|
||||||
|
expect(await devices[0].sdkNameAndVersion, 'iOS 13.3 17C54');
|
||||||
|
expect(devices[0].cpuArchitecture, DarwinArch.arm64);
|
||||||
|
expect(devices[0].connectionInterface, DeviceConnectionInterface.attached);
|
||||||
|
expect(devices[0].isConnected, true);
|
||||||
|
|
||||||
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
Platform: () => macPlatform,
|
||||||
|
Artifacts: () => Artifacts.test(),
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('use entry with sdk when filtering out duplicates', () async {
|
||||||
|
const String devicesOutput = '''
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"simulator" : false,
|
||||||
|
"interface" : "usb",
|
||||||
|
"available" : false,
|
||||||
|
"platform" : "com.apple.platform.iphoneos",
|
||||||
|
"modelCode" : "iPhone8,1",
|
||||||
|
"identifier" : "c4ca6f7a53027d1b7e4972e28478e7a28e2faee2",
|
||||||
|
"architecture" : "arm64",
|
||||||
|
"modelName" : "iPhone 6s",
|
||||||
|
"name" : "iPhone_1",
|
||||||
|
"error" : {
|
||||||
|
"code" : -13,
|
||||||
|
"failureReason" : "",
|
||||||
|
"description" : "iPhone iPad is not connected",
|
||||||
|
"recoverySuggestion" : "Xcode will continue when iPhone is connected and unlocked.",
|
||||||
|
"domain" : "com.apple.platform.iphoneos"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"simulator" : false,
|
||||||
|
"operatingSystemVersion" : "13.3 (17C54)",
|
||||||
|
"interface" : "usb",
|
||||||
|
"available" : false,
|
||||||
|
"platform" : "com.apple.platform.iphoneos",
|
||||||
|
"modelCode" : "iPhone8,1",
|
||||||
|
"identifier" : "c4ca6f7a53027d1b7e4972e28478e7a28e2faee2",
|
||||||
|
"architecture" : "arm64",
|
||||||
|
"modelName" : "iPhone 6s",
|
||||||
|
"name" : "iPhone_2",
|
||||||
|
"error" : {
|
||||||
|
"code" : -13,
|
||||||
|
"failureReason" : "",
|
||||||
|
"description" : "iPhone iPad is not connected",
|
||||||
|
"recoverySuggestion" : "Xcode will continue when iPhone is connected and unlocked.",
|
||||||
|
"domain" : "com.apple.platform.iphoneos"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
''';
|
||||||
|
|
||||||
|
fakeProcessManager.addCommand(const FakeCommand(
|
||||||
|
command: <String>['xcrun', 'xcdevice', 'list', '--timeout', '2'],
|
||||||
|
stdout: devicesOutput,
|
||||||
|
));
|
||||||
|
final List<IOSDevice> devices = await xcdevice.getAvailableIOSDevices();
|
||||||
|
expect(devices, hasLength(1));
|
||||||
|
|
||||||
|
expect(devices[0].id, 'c4ca6f7a53027d1b7e4972e28478e7a28e2faee2');
|
||||||
|
expect(devices[0].name, 'iPhone_2');
|
||||||
|
expect(await devices[0].sdkNameAndVersion, 'iOS 13.3 17C54');
|
||||||
|
expect(devices[0].cpuArchitecture, DarwinArch.arm64);
|
||||||
|
expect(devices[0].connectionInterface, DeviceConnectionInterface.attached);
|
||||||
|
expect(devices[0].isConnected, false);
|
||||||
|
|
||||||
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
Platform: () => macPlatform,
|
||||||
|
Artifacts: () => Artifacts.test(),
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('use entry with higher sdk when filtering out duplicates', () async {
|
||||||
|
const String devicesOutput = '''
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"simulator" : false,
|
||||||
|
"operatingSystemVersion" : "14.3 (17C54)",
|
||||||
|
"interface" : "usb",
|
||||||
|
"available" : false,
|
||||||
|
"platform" : "com.apple.platform.iphoneos",
|
||||||
|
"modelCode" : "iPhone8,1",
|
||||||
|
"identifier" : "c4ca6f7a53027d1b7e4972e28478e7a28e2faee2",
|
||||||
|
"architecture" : "arm64",
|
||||||
|
"modelName" : "iPhone 6s",
|
||||||
|
"name" : "iPhone_1",
|
||||||
|
"error" : {
|
||||||
|
"code" : -13,
|
||||||
|
"failureReason" : "",
|
||||||
|
"description" : "iPhone iPad is not connected",
|
||||||
|
"recoverySuggestion" : "Xcode will continue when iPhone is connected and unlocked.",
|
||||||
|
"domain" : "com.apple.platform.iphoneos"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"simulator" : false,
|
||||||
|
"operatingSystemVersion" : "13.3 (17C54)",
|
||||||
|
"interface" : "usb",
|
||||||
|
"available" : false,
|
||||||
|
"platform" : "com.apple.platform.iphoneos",
|
||||||
|
"modelCode" : "iPhone8,1",
|
||||||
|
"identifier" : "c4ca6f7a53027d1b7e4972e28478e7a28e2faee2",
|
||||||
|
"architecture" : "arm64",
|
||||||
|
"modelName" : "iPhone 6s",
|
||||||
|
"name" : "iPhone_2",
|
||||||
|
"error" : {
|
||||||
|
"code" : -13,
|
||||||
|
"failureReason" : "",
|
||||||
|
"description" : "iPhone iPad is not connected",
|
||||||
|
"recoverySuggestion" : "Xcode will continue when iPhone is connected and unlocked.",
|
||||||
|
"domain" : "com.apple.platform.iphoneos"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
''';
|
||||||
|
|
||||||
|
fakeProcessManager.addCommand(const FakeCommand(
|
||||||
|
command: <String>['xcrun', 'xcdevice', 'list', '--timeout', '2'],
|
||||||
|
stdout: devicesOutput,
|
||||||
|
));
|
||||||
|
final List<IOSDevice> devices = await xcdevice.getAvailableIOSDevices();
|
||||||
|
expect(devices, hasLength(1));
|
||||||
|
|
||||||
|
expect(devices[0].id, 'c4ca6f7a53027d1b7e4972e28478e7a28e2faee2');
|
||||||
|
expect(devices[0].name, 'iPhone_1');
|
||||||
|
expect(await devices[0].sdkNameAndVersion, 'iOS 14.3 17C54');
|
||||||
|
expect(devices[0].cpuArchitecture, DarwinArch.arm64);
|
||||||
|
expect(devices[0].connectionInterface, DeviceConnectionInterface.attached);
|
||||||
|
expect(devices[0].isConnected, false);
|
||||||
|
|
||||||
|
expect(fakeProcessManager, hasNoRemainingExpectations);
|
||||||
|
}, overrides: <Type, Generator>{
|
||||||
|
Platform: () => macPlatform,
|
||||||
|
Artifacts: () => Artifacts.test(),
|
||||||
|
});
|
||||||
|
|
||||||
testUsingContext('handles bad output',() async {
|
testUsingContext('handles bad output',() async {
|
||||||
fakeProcessManager.addCommand(const FakeCommand(
|
fakeProcessManager.addCommand(const FakeCommand(
|
||||||
command: <String>['xcrun', 'xcdevice', 'list', '--timeout', '2'],
|
command: <String>['xcrun', 'xcdevice', 'list', '--timeout', '2'],
|
||||||
|
Loading…
x
Reference in New Issue
Block a user