Unverified Commit a82c50f1 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Revert "Migrate xcdevice and ios devices to null safety (#91704)" (#91912)

This reverts commit 00658736.
parent 6c9259ae
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import 'base/common.dart'; import 'base/common.dart';
...@@ -281,6 +282,7 @@ abstract class Artifacts { ...@@ -281,6 +282,7 @@ abstract class Artifacts {
/// If a [fileSystem] is not provided, creates a new [MemoryFileSystem] instance. /// If a [fileSystem] is not provided, creates a new [MemoryFileSystem] instance.
/// ///
/// Creates a [LocalEngineArtifacts] if `localEngine` is non-null /// Creates a [LocalEngineArtifacts] if `localEngine` is non-null
@visibleForTesting
factory Artifacts.test({String? localEngine, FileSystem? fileSystem}) { factory Artifacts.test({String? localEngine, FileSystem? fileSystem}) {
fileSystem ??= MemoryFileSystem.test(); fileSystem ??= MemoryFileSystem.test();
if (localEngine != null) { if (localEngine != null) {
......
...@@ -127,6 +127,7 @@ class Cache { ...@@ -127,6 +127,7 @@ class Cache {
/// Defaults to a memory file system, fake platform, /// Defaults to a memory file system, fake platform,
/// buffer logger, and no accessible artifacts. /// buffer logger, and no accessible artifacts.
/// By default, the root cache directory path is "cache". /// By default, the root cache directory path is "cache".
@visibleForTesting
factory Cache.test({ factory Cache.test({
Directory? rootOverride, Directory? rootOverride,
List<ArtifactSet>? artifacts, List<ArtifactSet>? artifacts,
......
...@@ -468,7 +468,7 @@ abstract class Device { ...@@ -468,7 +468,7 @@ abstract class Device {
/// The ID returned matches that in the output of `flutter emulators`. Fetching /// The ID returned matches that in the output of `flutter emulators`. Fetching
/// this name may require connecting to the device and if an error occurs null /// this name may require connecting to the device and if an error occurs null
/// will be returned. /// will be returned.
Future<String?> get emulatorId; Future<String> get emulatorId;
/// Whether this device can run the provided [buildMode]. /// Whether this device can run the provided [buildMode].
/// ///
...@@ -550,7 +550,7 @@ abstract class Device { ...@@ -550,7 +550,7 @@ abstract class Device {
/// reader will also include log messages from before the invocation time. /// reader will also include log messages from before the invocation time.
/// Defaults to false. /// Defaults to false.
FutureOr<DeviceLogReader> getLogReader({ FutureOr<DeviceLogReader> getLogReader({
covariant ApplicationPackage? app, covariant ApplicationPackage app,
bool includePastLogs = false, bool includePastLogs = false,
}); });
...@@ -572,13 +572,13 @@ abstract class Device { ...@@ -572,13 +572,13 @@ abstract class Device {
/// start call. The build mode is not used by all platforms. /// start call. The build mode is not used by all platforms.
Future<LaunchResult> startApp( Future<LaunchResult> startApp(
covariant ApplicationPackage package, { covariant ApplicationPackage package, {
String? mainPath, String mainPath,
String? route, String route,
required DebuggingOptions debuggingOptions, DebuggingOptions debuggingOptions,
Map<String, Object?> platformArgs, Map<String, Object?> platformArgs,
bool prebuiltApplication = false, bool prebuiltApplication = false,
bool ipv6 = false, bool ipv6 = false,
String? userIdentifier, String userIdentifier,
}); });
/// Whether this device implements support for hot reload. /// Whether this device implements support for hot reload.
......
...@@ -7,8 +7,11 @@ ...@@ -7,8 +7,11 @@
import 'base/context.dart'; import 'base/context.dart';
import 'doctor.dart'; import 'doctor.dart';
import 'ios/simulators.dart'; import 'ios/simulators.dart';
import 'macos/xcdevice.dart';
export 'globals_null_migrated.dart'; export 'globals_null_migrated.dart';
Doctor get doctor => context.get<Doctor>(); Doctor get doctor => context.get<Doctor>();
IOSSimulatorUtils get iosSimulatorUtils => context.get<IOSSimulatorUtils>(); IOSSimulatorUtils get iosSimulatorUtils => context.get<IOSSimulatorUtils>();
XCDevice get xcdevice => context.get<XCDevice>();
...@@ -34,7 +34,6 @@ import 'ios/plist_parser.dart'; ...@@ -34,7 +34,6 @@ import 'ios/plist_parser.dart';
import 'ios/xcodeproj.dart'; import 'ios/xcodeproj.dart';
import 'macos/cocoapods.dart'; import 'macos/cocoapods.dart';
import 'macos/cocoapods_validator.dart'; import 'macos/cocoapods_validator.dart';
import 'macos/xcdevice.dart';
import 'macos/xcode.dart'; import 'macos/xcode.dart';
import 'persistent_tool_state.dart'; import 'persistent_tool_state.dart';
import 'project.dart'; import 'project.dart';
...@@ -63,7 +62,6 @@ FlutterVersion get flutterVersion => context.get<FlutterVersion>()!; ...@@ -63,7 +62,6 @@ FlutterVersion get flutterVersion => context.get<FlutterVersion>()!;
FuchsiaArtifacts? get fuchsiaArtifacts => context.get<FuchsiaArtifacts>(); FuchsiaArtifacts? get fuchsiaArtifacts => context.get<FuchsiaArtifacts>();
Usage get flutterUsage => context.get<Usage>()!; Usage get flutterUsage => context.get<Usage>()!;
XcodeProjectInterpreter? get xcodeProjectInterpreter => context.get<XcodeProjectInterpreter>(); XcodeProjectInterpreter? get xcodeProjectInterpreter => context.get<XcodeProjectInterpreter>();
XCDevice? get xcdevice => context.get<XCDevice>();
Xcode? get xcode => context.get<Xcode>(); Xcode? get xcode => context.get<Xcode>();
IOSWorkflow? get iosWorkflow => context.get<IOSWorkflow>(); IOSWorkflow? get iosWorkflow => context.get<IOSWorkflow>();
LocalEngineLocator? get localEngineLocator => context.get<LocalEngineLocator>(); LocalEngineLocator? get localEngineLocator => context.get<LocalEngineLocator>();
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:async'; import 'dart:async';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
...@@ -32,10 +34,10 @@ import 'mac.dart'; ...@@ -32,10 +34,10 @@ import 'mac.dart';
class IOSDevices extends PollingDeviceDiscovery { class IOSDevices extends PollingDeviceDiscovery {
IOSDevices({ IOSDevices({
required Platform platform, @required Platform platform,
required XCDevice xcdevice, @required XCDevice xcdevice,
required IOSWorkflow iosWorkflow, @required IOSWorkflow iosWorkflow,
required Logger logger, @required Logger logger,
}) : _platform = platform, }) : _platform = platform,
_xcdevice = xcdevice, _xcdevice = xcdevice,
_iosWorkflow = iosWorkflow, _iosWorkflow = iosWorkflow,
...@@ -53,7 +55,7 @@ class IOSDevices extends PollingDeviceDiscovery { ...@@ -53,7 +55,7 @@ class IOSDevices extends PollingDeviceDiscovery {
@override @override
bool get canListAnything => _iosWorkflow.canListDevices; bool get canListAnything => _iosWorkflow.canListDevices;
StreamSubscription<Map<XCDeviceEvent, String>>? _observedDeviceEventsSubscription; StreamSubscription<Map<XCDeviceEvent, String>> _observedDeviceEventsSubscription;
@override @override
Future<void> startPolling() async { Future<void> startPolling() async {
...@@ -69,13 +71,13 @@ class IOSDevices extends PollingDeviceDiscovery { ...@@ -69,13 +71,13 @@ class IOSDevices extends PollingDeviceDiscovery {
deviceNotifier ??= ItemListNotifier<Device>(); deviceNotifier ??= ItemListNotifier<Device>();
// Start by populating all currently attached devices. // Start by populating all currently attached devices.
deviceNotifier!.updateWithNewList(await pollingGetDevices()); deviceNotifier.updateWithNewList(await pollingGetDevices());
// cancel any outstanding subscriptions. // cancel any outstanding subscriptions.
await _observedDeviceEventsSubscription?.cancel(); await _observedDeviceEventsSubscription?.cancel();
_observedDeviceEventsSubscription = _xcdevice.observedDeviceEvents()?.listen( _observedDeviceEventsSubscription = _xcdevice.observedDeviceEvents()?.listen(
_onDeviceEvent, _onDeviceEvent,
onError: (Object error, StackTrace stack) { onError: (dynamic error, StackTrace stack) {
_logger.printTrace('Process exception running xcdevice observe:\n$error\n$stack'); _logger.printTrace('Process exception running xcdevice observe:\n$error\n$stack');
}, onDone: () { }, onDone: () {
// If xcdevice is killed or otherwise dies, polling will be stopped. // If xcdevice is killed or otherwise dies, polling will be stopped.
...@@ -90,26 +92,18 @@ class IOSDevices extends PollingDeviceDiscovery { ...@@ -90,26 +92,18 @@ class IOSDevices extends PollingDeviceDiscovery {
Future<void> _onDeviceEvent(Map<XCDeviceEvent, String> event) async { Future<void> _onDeviceEvent(Map<XCDeviceEvent, String> event) async {
final XCDeviceEvent eventType = event.containsKey(XCDeviceEvent.attach) ? XCDeviceEvent.attach : XCDeviceEvent.detach; final XCDeviceEvent eventType = event.containsKey(XCDeviceEvent.attach) ? XCDeviceEvent.attach : XCDeviceEvent.detach;
final String? deviceIdentifier = event[eventType]; final String deviceIdentifier = event[eventType];
final ItemListNotifier<Device>? notifier = deviceNotifier; final Device knownDevice = deviceNotifier.items
if (notifier == null) { .firstWhere((Device device) => device.id == deviceIdentifier, orElse: () => null);
return;
}
Device? knownDevice;
for (final Device device in notifier.items) {
if (device.id == deviceIdentifier) {
knownDevice = device;
}
}
// Ignore already discovered devices (maybe populated at the beginning). // Ignore already discovered devices (maybe populated at the beginning).
if (eventType == XCDeviceEvent.attach && knownDevice == null) { if (eventType == XCDeviceEvent.attach && knownDevice == null) {
// There's no way to get details for an individual attached device, // There's no way to get details for an individual attached device,
// so repopulate them all. // so repopulate them all.
final List<Device> devices = await pollingGetDevices(); final List<Device> devices = await pollingGetDevices();
notifier.updateWithNewList(devices); deviceNotifier.updateWithNewList(devices);
} else if (eventType == XCDeviceEvent.detach && knownDevice != null) { } else if (eventType == XCDeviceEvent.detach && knownDevice != null) {
notifier.removeItem(knownDevice); deviceNotifier.removeItem(knownDevice);
} }
} }
...@@ -119,7 +113,7 @@ class IOSDevices extends PollingDeviceDiscovery { ...@@ -119,7 +113,7 @@ class IOSDevices extends PollingDeviceDiscovery {
} }
@override @override
Future<List<Device>> pollingGetDevices({ Duration? timeout }) async { Future<List<Device>> pollingGetDevices({ Duration timeout }) async {
if (!_platform.isMacOS) { if (!_platform.isMacOS) {
throw UnsupportedError( throw UnsupportedError(
'Control of iOS devices or simulators only supported on macOS.' 'Control of iOS devices or simulators only supported on macOS.'
...@@ -146,16 +140,16 @@ class IOSDevices extends PollingDeviceDiscovery { ...@@ -146,16 +140,16 @@ class IOSDevices extends PollingDeviceDiscovery {
class IOSDevice extends Device { class IOSDevice extends Device {
IOSDevice(String id, { IOSDevice(String id, {
required FileSystem fileSystem, @required FileSystem fileSystem,
required this.name, @required this.name,
required this.cpuArchitecture, @required this.cpuArchitecture,
required this.interfaceType, @required this.interfaceType,
String? sdkVersion, @required String sdkVersion,
required Platform platform, @required Platform platform,
required IOSDeploy iosDeploy, @required IOSDeploy iosDeploy,
required IMobileDevice iMobileDevice, @required IMobileDevice iMobileDevice,
required IProxy iProxy, @required IProxy iProxy,
required Logger logger, @required Logger logger,
}) })
: _sdkVersion = sdkVersion, : _sdkVersion = sdkVersion,
_iosDeploy = iosDeploy, _iosDeploy = iosDeploy,
...@@ -176,7 +170,7 @@ class IOSDevice extends Device { ...@@ -176,7 +170,7 @@ class IOSDevice extends Device {
} }
} }
final String? _sdkVersion; final String _sdkVersion;
final IOSDeploy _iosDeploy; final IOSDeploy _iosDeploy;
final FileSystem _fileSystem; final FileSystem _fileSystem;
final Logger _logger; final Logger _logger;
...@@ -186,7 +180,7 @@ class IOSDevice extends Device { ...@@ -186,7 +180,7 @@ class IOSDevice extends Device {
/// 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(); final String majorVersionString = _sdkVersion?.split('.')?.first?.trim();
return majorVersionString != null ? int.tryParse(majorVersionString) ?? 0 : 0; return majorVersionString != null ? int.tryParse(majorVersionString) ?? 0 : 0;
} }
...@@ -209,18 +203,18 @@ class IOSDevice extends Device { ...@@ -209,18 +203,18 @@ class IOSDevice extends Device {
final IOSDeviceConnectionInterface interfaceType; final IOSDeviceConnectionInterface interfaceType;
final Map<IOSApp?, DeviceLogReader> _logReaders = <IOSApp?, DeviceLogReader>{}; Map<IOSApp, DeviceLogReader> _logReaders;
DevicePortForwarder? _portForwarder; DevicePortForwarder _portForwarder;
@visibleForTesting @visibleForTesting
IOSDeployDebugger? iosDeployDebugger; IOSDeployDebugger iosDeployDebugger;
@override @override
Future<bool> get isLocalEmulator async => false; Future<bool> get isLocalEmulator async => false;
@override @override
Future<String?> get emulatorId async => null; Future<String> get emulatorId async => null;
@override @override
bool get supportsStartPaused => false; bool get supportsStartPaused => false;
...@@ -228,7 +222,7 @@ class IOSDevice extends Device { ...@@ -228,7 +222,7 @@ class IOSDevice extends Device {
@override @override
Future<bool> isAppInstalled( Future<bool> isAppInstalled(
IOSApp app, { IOSApp app, {
String? userIdentifier, String userIdentifier,
}) async { }) async {
bool result; bool result;
try { try {
...@@ -249,7 +243,7 @@ class IOSDevice extends Device { ...@@ -249,7 +243,7 @@ class IOSDevice extends Device {
@override @override
Future<bool> installApp( Future<bool> installApp(
IOSApp app, { IOSApp app, {
String? userIdentifier, String userIdentifier,
}) async { }) async {
final Directory bundle = _fileSystem.directory(app.deviceBundlePath); final Directory bundle = _fileSystem.directory(app.deviceBundlePath);
if (!bundle.existsSync()) { if (!bundle.existsSync()) {
...@@ -283,7 +277,7 @@ class IOSDevice extends Device { ...@@ -283,7 +277,7 @@ class IOSDevice extends Device {
@override @override
Future<bool> uninstallApp( Future<bool> uninstallApp(
IOSApp app, { IOSApp app, {
String? userIdentifier, String userIdentifier,
}) async { }) async {
int uninstallationResult; int uninstallationResult;
try { try {
...@@ -308,16 +302,16 @@ class IOSDevice extends Device { ...@@ -308,16 +302,16 @@ class IOSDevice extends Device {
@override @override
Future<LaunchResult> startApp( Future<LaunchResult> startApp(
IOSApp package, { IOSApp package, {
String? mainPath, String mainPath,
String? route, String route,
required DebuggingOptions debuggingOptions, DebuggingOptions debuggingOptions,
Map<String, Object?> platformArgs = const <String, Object?>{}, Map<String, dynamic> platformArgs,
bool prebuiltApplication = false, bool prebuiltApplication = false,
bool ipv6 = false, bool ipv6 = false,
String? userIdentifier, String userIdentifier,
@visibleForTesting Duration? discoveryTimeout, @visibleForTesting Duration discoveryTimeout,
}) async { }) async {
String? packageId; String packageId;
if (!prebuiltApplication) { if (!prebuiltApplication) {
_logger.printTrace('Building ${package.name} for $id'); _logger.printTrace('Building ${package.name} for $id');
...@@ -327,6 +321,7 @@ class IOSDevice extends Device { ...@@ -327,6 +321,7 @@ class IOSDevice extends Device {
app: package as BuildableIOSApp, app: package as BuildableIOSApp,
buildInfo: debuggingOptions.buildInfo, buildInfo: debuggingOptions.buildInfo,
targetOverride: mainPath, targetOverride: mainPath,
environmentType: EnvironmentType.physical,
activeArch: cpuArchitecture, activeArch: cpuArchitecture,
deviceID: id, deviceID: id,
); );
...@@ -371,14 +366,14 @@ class IOSDevice extends Device { ...@@ -371,14 +366,14 @@ class IOSDevice extends Device {
if (debuggingOptions.verboseSystemLogs) '--verbose-logging', if (debuggingOptions.verboseSystemLogs) '--verbose-logging',
if (debuggingOptions.cacheSkSL) '--cache-sksl', if (debuggingOptions.cacheSkSL) '--cache-sksl',
if (debuggingOptions.purgePersistentCache) '--purge-persistent-cache', if (debuggingOptions.purgePersistentCache) '--purge-persistent-cache',
if (platformArgs['trace-startup'] as bool? ?? false) '--trace-startup', if (platformArgs['trace-startup'] as bool ?? false) '--trace-startup',
]; ];
final Status installStatus = _logger.startProgress( final Status installStatus = _logger.startProgress(
'Installing and launching...', 'Installing and launching...',
); );
try { try {
ProtocolDiscovery? observatoryDiscovery; ProtocolDiscovery observatoryDiscovery;
int installationResult = 1; int installationResult = 1;
if (debuggingOptions.debuggingEnabled) { if (debuggingOptions.debuggingEnabled) {
_logger.printTrace('Debugging is enabled, connecting to observatory'); _logger.printTrace('Debugging is enabled, connecting to observatory');
...@@ -416,7 +411,7 @@ class IOSDevice extends Device { ...@@ -416,7 +411,7 @@ class IOSDevice extends Device {
interfaceType: interfaceType, interfaceType: interfaceType,
); );
} else { } else {
installationResult = await iosDeployDebugger!.launchAndAttach() ? 0 : 1; installationResult = await iosDeployDebugger.launchAndAttach() ? 0 : 1;
} }
if (installationResult != 0) { if (installationResult != 0) {
_logger.printError('Could not run ${bundle.path} on $id.'); _logger.printError('Could not run ${bundle.path} on $id.');
...@@ -434,7 +429,7 @@ class IOSDevice extends Device { ...@@ -434,7 +429,7 @@ class IOSDevice extends Device {
final Timer timer = Timer(discoveryTimeout ?? const Duration(seconds: 30), () { final Timer timer = Timer(discoveryTimeout ?? const Duration(seconds: 30), () {
_logger.printError('iOS Observatory not discovered after 30 seconds. This is taking much longer than expected...'); _logger.printError('iOS Observatory not discovered after 30 seconds. This is taking much longer than expected...');
}); });
final Uri? localUri = await observatoryDiscovery?.uri; final Uri localUri = await observatoryDiscovery.uri;
timer.cancel(); timer.cancel();
if (localUri == null) { if (localUri == null) {
iosDeployDebugger?.detach(); iosDeployDebugger?.detach();
...@@ -453,12 +448,12 @@ class IOSDevice extends Device { ...@@ -453,12 +448,12 @@ class IOSDevice extends Device {
@override @override
Future<bool> stopApp( Future<bool> stopApp(
IOSApp app, { IOSApp app, {
String? userIdentifier, String userIdentifier,
}) async { }) async {
// If the debugger is not attached, killing the ios-deploy process won't stop the app. // If the debugger is not attached, killing the ios-deploy process won't stop the app.
final IOSDeployDebugger? deployDebugger = iosDeployDebugger; if (iosDeployDebugger!= null && iosDeployDebugger.debuggerAttached) {
if (deployDebugger != null && deployDebugger.debuggerAttached) { // Avoid null.
return deployDebugger.exit() == true; return iosDeployDebugger?.exit() == true;
} }
return false; return false;
} }
...@@ -471,10 +466,11 @@ class IOSDevice extends Device { ...@@ -471,10 +466,11 @@ class IOSDevice extends Device {
@override @override
DeviceLogReader getLogReader({ DeviceLogReader getLogReader({
IOSApp? app, IOSApp app,
bool includePastLogs = false, bool includePastLogs = false,
}) { }) {
assert(!includePastLogs, 'Past log reading not supported on iOS devices.'); assert(!includePastLogs, 'Past log reading not supported on iOS devices.');
_logReaders ??= <IOSApp, DeviceLogReader>{};
return _logReaders.putIfAbsent(app, () => IOSDeviceLogReader.create( return _logReaders.putIfAbsent(app, () => IOSDeviceLogReader.create(
device: this, device: this,
app: app, app: app,
...@@ -484,6 +480,7 @@ class IOSDevice extends Device { ...@@ -484,6 +480,7 @@ class IOSDevice extends Device {
@visibleForTesting @visibleForTesting
void setLogReader(IOSApp app, DeviceLogReader logReader) { void setLogReader(IOSApp app, DeviceLogReader logReader) {
_logReaders ??= <IOSApp, DeviceLogReader>{};
_logReaders[app] = logReader; _logReaders[app] = logReader;
} }
...@@ -518,10 +515,9 @@ class IOSDevice extends Device { ...@@ -518,10 +515,9 @@ class IOSDevice extends Device {
@override @override
Future<void> dispose() async { Future<void> dispose() async {
for (final DeviceLogReader logReader in _logReaders.values) { _logReaders?.forEach((IOSApp application, DeviceLogReader logReader) {
logReader.dispose(); logReader.dispose();
} });
_logReaders.clear();
await _portForwarder?.dispose(); await _portForwarder?.dispose();
} }
} }
...@@ -594,19 +590,31 @@ class IOSDeviceLogReader extends DeviceLogReader { ...@@ -594,19 +590,31 @@ class IOSDeviceLogReader extends DeviceLogReader {
this._deviceId, this._deviceId,
this.name, this.name,
String appName, String appName,
) : // Match for lines for the runner in syslog. ) {
// _linesController = StreamController<String>.broadcast(
// iOS 9 format: Runner[297] <Notice>: onListen: _listenToSysLog,
// iOS 10 format: Runner(Flutter)[297] <Notice>: onCancel: dispose,
_runnerLineRegex = RegExp(appName + r'(\(Flutter\))?\[[\d]+\] <[A-Za-z]+>: '); );
// Match for lines for the runner in syslog.
//
// iOS 9 format: Runner[297] <Notice>:
// iOS 10 format: Runner(Flutter)[297] <Notice>:
_runnerLineRegex = RegExp(appName + r'(\(Flutter\))?\[[\d]+\] <[A-Za-z]+>: ');
// Similar to above, but allows ~arbitrary components instead of "Runner"
// and "Flutter". The regex tries to strike a balance between not producing
// false positives and not producing false negatives.
_anyLineRegex = RegExp(r'\w+(\([^)]*\))?\[\d+\] <[A-Za-z]+>: ');
_loggingSubscriptions = <StreamSubscription<void>>[];
}
/// Create a new [IOSDeviceLogReader]. /// Create a new [IOSDeviceLogReader].
factory IOSDeviceLogReader.create({ factory IOSDeviceLogReader.create({
required IOSDevice device, @required IOSDevice device,
IOSApp? app, @required IOSApp app,
required IMobileDevice iMobileDevice, @required IMobileDevice iMobileDevice,
}) { }) {
final String appName = app?.name?.replaceAll('.app', '') ?? ''; final String appName = app == null ? '' : app.name.replaceAll('.app', '');
return IOSDeviceLogReader._( return IOSDeviceLogReader._(
iMobileDevice, iMobileDevice,
device.majorSdkVersion, device.majorSdkVersion,
...@@ -618,7 +626,7 @@ class IOSDeviceLogReader extends DeviceLogReader { ...@@ -618,7 +626,7 @@ class IOSDeviceLogReader extends DeviceLogReader {
/// Create an [IOSDeviceLogReader] for testing. /// Create an [IOSDeviceLogReader] for testing.
factory IOSDeviceLogReader.test({ factory IOSDeviceLogReader.test({
required IMobileDevice iMobileDevice, @required IMobileDevice iMobileDevice,
bool useSyslog = true, bool useSyslog = true,
}) { }) {
return IOSDeviceLogReader._( return IOSDeviceLogReader._(
...@@ -633,11 +641,8 @@ class IOSDeviceLogReader extends DeviceLogReader { ...@@ -633,11 +641,8 @@ class IOSDeviceLogReader extends DeviceLogReader {
// Matches a syslog line from the runner. // Matches a syslog line from the runner.
RegExp _runnerLineRegex; RegExp _runnerLineRegex;
// Matches a syslog line from any app.
// Similar to above, but allows ~arbitrary components instead of "Runner" RegExp _anyLineRegex;
// and "Flutter". The regex tries to strike a balance between not producing
// false positives and not producing false negatives.
final RegExp _anyLineRegex = RegExp(r'\w+(\([^)]*\))?\[\d+\] <[A-Za-z]+>: ');
// Logging from native code/Flutter engine is prefixed by timestamp and process metadata: // Logging from native code/Flutter engine is prefixed by timestamp and process metadata:
// 2020-09-15 19:15:10.931434-0700 Runner[541:226276] Did finish launching. // 2020-09-15 19:15:10.931434-0700 Runner[541:226276] Did finish launching.
...@@ -646,24 +651,19 @@ class IOSDeviceLogReader extends DeviceLogReader { ...@@ -646,24 +651,19 @@ class IOSDeviceLogReader extends DeviceLogReader {
// Logging from the dart code has no prefixing metadata. // Logging from the dart code has no prefixing metadata.
final RegExp _debuggerLoggingRegex = RegExp(r'^\S* \S* \S*\[[0-9:]*] (.*)'); final RegExp _debuggerLoggingRegex = RegExp(r'^\S* \S* \S*\[[0-9:]*] (.*)');
late final StreamController<String> _linesController = StreamController<String>.broadcast( StreamController<String> _linesController;
onListen: _listenToSysLog, List<StreamSubscription<void>> _loggingSubscriptions;
onCancel: dispose,
);
final List<StreamSubscription<void>> _loggingSubscriptions = <StreamSubscription<void>>[];
@override @override
Stream<String> get logLines => _linesController.stream; Stream<String> get logLines => _linesController.stream;
@override @override
FlutterVmService? get connectedVMService => _connectedVMService; FlutterVmService get connectedVMService => _connectedVMService;
FlutterVmService? _connectedVMService; FlutterVmService _connectedVMService;
@override @override
set connectedVMService(FlutterVmService? connectedVmService) { set connectedVMService(FlutterVmService connectedVmService) {
if (connectedVmService != null) { _listenToUnifiedLoggingEvents(connectedVmService);
_listenToUnifiedLoggingEvents(connectedVmService);
}
_connectedVMService = connectedVmService; _connectedVMService = connectedVmService;
} }
...@@ -687,7 +687,7 @@ class IOSDeviceLogReader extends DeviceLogReader { ...@@ -687,7 +687,7 @@ class IOSDeviceLogReader extends DeviceLogReader {
} }
void logMessage(vm_service.Event event) { void logMessage(vm_service.Event event) {
if (_iosDeployDebugger != null && _iosDeployDebugger!.debuggerAttached) { if (_iosDeployDebugger != null && _iosDeployDebugger.debuggerAttached) {
// Prefer the more complete logs from the attached debugger. // Prefer the more complete logs from the attached debugger.
return; return;
} }
...@@ -704,16 +704,13 @@ class IOSDeviceLogReader extends DeviceLogReader { ...@@ -704,16 +704,13 @@ class IOSDeviceLogReader extends DeviceLogReader {
} }
/// Log reader will listen to [debugger.logLines] and will detach debugger on dispose. /// Log reader will listen to [debugger.logLines] and will detach debugger on dispose.
IOSDeployDebugger? get debuggerStream => _iosDeployDebugger; IOSDeployDebugger get debuggerStream => _iosDeployDebugger;
set debuggerStream(IOSDeployDebugger? debugger) { set debuggerStream(IOSDeployDebugger debugger) {
// Logging is gathered from syslog on iOS 13 and earlier. // Logging is gathered from syslog on iOS 13 and earlier.
if (_majorSdkVersion < minimumUniversalLoggingSdkVersion) { if (_majorSdkVersion < minimumUniversalLoggingSdkVersion) {
return; return;
} }
_iosDeployDebugger = debugger; _iosDeployDebugger = debugger;
if (debugger == null) {
return;
}
// Add the debugger logs to the controller created on initialization. // Add the debugger logs to the controller created on initialization.
_loggingSubscriptions.add(debugger.logLines.listen( _loggingSubscriptions.add(debugger.logLines.listen(
(String line) => _linesController.add(_debuggerLineHandler(line)), (String line) => _linesController.add(_debuggerLineHandler(line)),
...@@ -722,10 +719,10 @@ class IOSDeviceLogReader extends DeviceLogReader { ...@@ -722,10 +719,10 @@ class IOSDeviceLogReader extends DeviceLogReader {
cancelOnError: true, cancelOnError: true,
)); ));
} }
IOSDeployDebugger? _iosDeployDebugger; IOSDeployDebugger _iosDeployDebugger;
// Strip off the logging metadata (leave the category), or just echo the line. // Strip off the logging metadata (leave the category), or just echo the line.
String _debuggerLineHandler(String line) => _debuggerLoggingRegex.firstMatch(line)?.group(1) ?? line; String _debuggerLineHandler(String line) => _debuggerLoggingRegex?.firstMatch(line)?.group(1) ?? line;
void _listenToSysLog() { void _listenToSysLog() {
// syslog is not written on iOS 13+. // syslog is not written on iOS 13+.
...@@ -746,7 +743,7 @@ class IOSDeviceLogReader extends DeviceLogReader { ...@@ -746,7 +743,7 @@ class IOSDeviceLogReader extends DeviceLogReader {
} }
@visibleForTesting @visibleForTesting
Process? idevicesyslogProcess; Process idevicesyslogProcess;
// Returns a stateful line handler to properly capture multiline output. // Returns a stateful line handler to properly capture multiline output.
// //
...@@ -767,7 +764,7 @@ class IOSDeviceLogReader extends DeviceLogReader { ...@@ -767,7 +764,7 @@ class IOSDeviceLogReader extends DeviceLogReader {
printing = false; printing = false;
} }
final Match? match = _runnerLineRegex.firstMatch(line); final Match match = _runnerLineRegex.firstMatch(line);
if (match != null) { if (match != null) {
final String logLine = line.substring(match.end); final String logLine = line.substring(match.end);
...@@ -794,10 +791,10 @@ class IOSDevicePortForwarder extends DevicePortForwarder { ...@@ -794,10 +791,10 @@ class IOSDevicePortForwarder extends DevicePortForwarder {
/// Create a new [IOSDevicePortForwarder]. /// Create a new [IOSDevicePortForwarder].
IOSDevicePortForwarder({ IOSDevicePortForwarder({
required Logger logger, @required Logger logger,
required String id, @required String id,
required IProxy iproxy, @required IProxy iproxy,
required OperatingSystemUtils operatingSystemUtils, @required OperatingSystemUtils operatingSystemUtils,
}) : _logger = logger, }) : _logger = logger,
_id = id, _id = id,
_iproxy = iproxy, _iproxy = iproxy,
...@@ -810,10 +807,10 @@ class IOSDevicePortForwarder extends DevicePortForwarder { ...@@ -810,10 +807,10 @@ class IOSDevicePortForwarder extends DevicePortForwarder {
/// ///
/// The device id may be provided, but otherwise defaults to '1234'. /// The device id may be provided, but otherwise defaults to '1234'.
factory IOSDevicePortForwarder.test({ factory IOSDevicePortForwarder.test({
required ProcessManager processManager, @required ProcessManager processManager,
required Logger logger, @required Logger logger,
String? id, String id,
required OperatingSystemUtils operatingSystemUtils, OperatingSystemUtils operatingSystemUtils,
}) { }) {
return IOSDevicePortForwarder( return IOSDevicePortForwarder(
logger: logger, logger: logger,
...@@ -842,20 +839,20 @@ class IOSDevicePortForwarder extends DevicePortForwarder { ...@@ -842,20 +839,20 @@ class IOSDevicePortForwarder extends DevicePortForwarder {
static const Duration _kiProxyPortForwardTimeout = Duration(seconds: 1); static const Duration _kiProxyPortForwardTimeout = Duration(seconds: 1);
@override @override
Future<int> forward(int devicePort, { int? hostPort }) async { Future<int> forward(int devicePort, { int hostPort }) async {
final bool autoselect = hostPort == null || hostPort == 0; final bool autoselect = hostPort == null || hostPort == 0;
if (autoselect) { if (autoselect) {
final int freePort = await _operatingSystemUtils.findFreePort(); final int freePort = await _operatingSystemUtils?.findFreePort();
// Dynamic port range 49152 - 65535. // Dynamic port range 49152 - 65535.
hostPort = freePort == 0 ? 49152 : freePort; hostPort = freePort == null || freePort == 0 ? 49152 : freePort;
} }
Process? process; Process process;
bool connected = false; bool connected = false;
while (!connected) { while (!connected) {
_logger.printTrace('Attempting to forward device port $devicePort to host port $hostPort'); _logger.printTrace('Attempting to forward device port $devicePort to host port $hostPort');
process = await _iproxy.forward(devicePort, hostPort!, _id); process = await _iproxy.forward(devicePort, hostPort, _id);
// TODO(ianh): This is a flaky race condition, https://github.com/libimobiledevice/libimobiledevice/issues/674 // TODO(ianh): This is a flaky race condition, https://github.com/libimobiledevice/libimobiledevice/issues/674
connected = !await process.stdout.isEmpty.timeout(_kiProxyPortForwardTimeout, onTimeout: () => false); connected = !await process.stdout.isEmpty.timeout(_kiProxyPortForwardTimeout, onTimeout: () => false);
if (!connected) { if (!connected) {
...@@ -874,7 +871,7 @@ class IOSDevicePortForwarder extends DevicePortForwarder { ...@@ -874,7 +871,7 @@ class IOSDevicePortForwarder extends DevicePortForwarder {
assert(process != null); assert(process != null);
final ForwardedPort forwardedPort = ForwardedPort.withContext( final ForwardedPort forwardedPort = ForwardedPort.withContext(
hostPort!, devicePort, process, hostPort, devicePort, process,
); );
_logger.printTrace('Forwarded port $forwardedPort'); _logger.printTrace('Forwarded port $forwardedPort');
forwardedPorts.add(forwardedPort); forwardedPorts.add(forwardedPort);
......
...@@ -45,16 +45,6 @@ class IMobileDevice { ...@@ -45,16 +45,6 @@ class IMobileDevice {
_processUtils = ProcessUtils(logger: logger, processManager: processManager), _processUtils = ProcessUtils(logger: logger, processManager: processManager),
_processManager = processManager; _processManager = processManager;
/// Create an [IMobileDevice] for testing.
factory IMobileDevice.test({ required ProcessManager processManager }) {
return IMobileDevice(
artifacts: Artifacts.test(),
cache: Cache.test(processManager: processManager),
processManager: processManager,
logger: BufferLogger.test(),
);
}
final String _idevicesyslogPath; final String _idevicesyslogPath;
final String _idevicescreenshotPath; final String _idevicescreenshotPath;
final MapEntry<String, String> _dyLdLibEntry; final MapEntry<String, String> _dyLdLibEntry;
...@@ -103,7 +93,7 @@ class IMobileDevice { ...@@ -103,7 +93,7 @@ class IMobileDevice {
Future<XcodeBuildResult> buildXcodeProject({ Future<XcodeBuildResult> buildXcodeProject({
required BuildableIOSApp app, required BuildableIOSApp app,
required BuildInfo buildInfo, required BuildInfo buildInfo,
String? targetOverride, required String targetOverride,
EnvironmentType environmentType = EnvironmentType.physical, EnvironmentType environmentType = EnvironmentType.physical,
DarwinArch? activeArch, DarwinArch? activeArch,
bool codesign = true, bool codesign = true,
......
...@@ -2,8 +2,11 @@ ...@@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:async'; import 'dart:async';
import 'package:meta/meta.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import '../artifacts.dart'; import '../artifacts.dart';
...@@ -31,13 +34,13 @@ enum XCDeviceEvent { ...@@ -31,13 +34,13 @@ enum XCDeviceEvent {
/// A utility class for interacting with Xcode xcdevice command line tools. /// A utility class for interacting with Xcode xcdevice command line tools.
class XCDevice { class XCDevice {
XCDevice({ XCDevice({
required Artifacts artifacts, @required Artifacts artifacts,
required Cache cache, @required Cache cache,
required ProcessManager processManager, @required ProcessManager processManager,
required Logger logger, @required Logger logger,
required Xcode xcode, @required Xcode xcode,
required Platform platform, @required Platform platform,
required IProxy iproxy, @required IProxy iproxy,
}) : _processUtils = ProcessUtils(logger: logger, processManager: processManager), }) : _processUtils = ProcessUtils(logger: logger, processManager: processManager),
_logger = logger, _logger = logger,
_iMobileDevice = IMobileDevice( _iMobileDevice = IMobileDevice(
...@@ -70,9 +73,9 @@ class XCDevice { ...@@ -70,9 +73,9 @@ class XCDevice {
final Xcode _xcode; final Xcode _xcode;
final IProxy _iProxy; final IProxy _iProxy;
List<Object>? _cachedListResults; List<dynamic> _cachedListResults;
Process? _deviceObservationProcess; Process _deviceObservationProcess;
StreamController<Map<XCDeviceEvent, String>>? _deviceIdentifierByEvent; StreamController<Map<XCDeviceEvent, String>> _deviceIdentifierByEvent;
void _setupDeviceIdentifierByEventStream() { void _setupDeviceIdentifierByEventStream() {
// _deviceIdentifierByEvent Should always be available for listeners // _deviceIdentifierByEvent Should always be available for listeners
...@@ -85,9 +88,9 @@ class XCDevice { ...@@ -85,9 +88,9 @@ class XCDevice {
bool get isInstalled => _xcode.isInstalledAndMeetsVersionCheck; bool get isInstalled => _xcode.isInstalledAndMeetsVersionCheck;
Future<List<Object>?> _getAllDevices({ Future<List<dynamic>> _getAllDevices({
bool useCache = false, bool useCache = false,
required Duration timeout @required Duration timeout
}) async { }) async {
if (!isInstalled) { if (!isInstalled) {
_logger.printTrace("Xcode not found. Run 'flutter doctor' for more information."); _logger.printTrace("Xcode not found. Run 'flutter doctor' for more information.");
...@@ -111,7 +114,7 @@ class XCDevice { ...@@ -111,7 +114,7 @@ class XCDevice {
if (result.exitCode == 0) { if (result.exitCode == 0) {
final String listOutput = result.stdout; final String listOutput = result.stdout;
try { try {
final List<Object> listResults = (json.decode(result.stdout) as List<Object?>).whereType<Object>().toList(); final List<dynamic> listResults = json.decode(listOutput) as List<dynamic>;
_cachedListResults = listResults; _cachedListResults = listResults;
return listResults; return listResults;
} on FormatException { } on FormatException {
...@@ -134,12 +137,12 @@ class XCDevice { ...@@ -134,12 +137,12 @@ class XCDevice {
/// ///
/// Each attach and detach event is a tuple of one event type /// Each attach and detach event is a tuple of one event type
/// and identifier. /// and identifier.
Stream<Map<XCDeviceEvent, String>>? observedDeviceEvents() { Stream<Map<XCDeviceEvent, String>> observedDeviceEvents() {
if (!isInstalled) { if (!isInstalled) {
_logger.printTrace("Xcode not found. Run 'flutter doctor' for more information."); _logger.printTrace("Xcode not found. Run 'flutter doctor' for more information.");
return null; return null;
} }
return _deviceIdentifierByEvent?.stream; return _deviceIdentifierByEvent.stream;
} }
// Attach: d83d5bc53967baa0ee18626ba87b6254b2ab5418 // Attach: d83d5bc53967baa0ee18626ba87b6254b2ab5418
...@@ -168,7 +171,7 @@ class XCDevice { ...@@ -168,7 +171,7 @@ class XCDevice {
], ],
); );
final StreamSubscription<String> stdoutSubscription = _deviceObservationProcess!.stdout final StreamSubscription<String> stdoutSubscription = _deviceObservationProcess.stdout
.transform<String>(utf8.decoder) .transform<String>(utf8.decoder)
.transform<String>(const LineSplitter()) .transform<String>(const LineSplitter())
.listen((String line) { .listen((String line) {
...@@ -180,35 +183,35 @@ class XCDevice { ...@@ -180,35 +183,35 @@ class XCDevice {
// Attach: 00008027-00192736010F802E // Attach: 00008027-00192736010F802E
// Detach: d83d5bc53967baa0ee18626ba87b6254b2ab5418 // Detach: d83d5bc53967baa0ee18626ba87b6254b2ab5418
// Attach: d83d5bc53967baa0ee18626ba87b6254b2ab5418 // Attach: d83d5bc53967baa0ee18626ba87b6254b2ab5418
final RegExpMatch? match = _observationIdentifierPattern.firstMatch(line); final RegExpMatch match = _observationIdentifierPattern.firstMatch(line);
if (match != null && match.groupCount == 2) { if (match != null && match.groupCount == 2) {
final String verb = match.group(1)!.toLowerCase(); final String verb = match.group(1).toLowerCase();
final String identifier = match.group(2)!; final String identifier = match.group(2);
if (verb.startsWith('attach')) { if (verb.startsWith('attach')) {
_deviceIdentifierByEvent?.add(<XCDeviceEvent, String>{ _deviceIdentifierByEvent.add(<XCDeviceEvent, String>{
XCDeviceEvent.attach: identifier XCDeviceEvent.attach: identifier
}); });
} else if (verb.startsWith('detach')) { } else if (verb.startsWith('detach')) {
_deviceIdentifierByEvent?.add(<XCDeviceEvent, String>{ _deviceIdentifierByEvent.add(<XCDeviceEvent, String>{
XCDeviceEvent.detach: identifier XCDeviceEvent.detach: identifier
}); });
} }
} }
}); });
final StreamSubscription<String> stderrSubscription = _deviceObservationProcess!.stderr final StreamSubscription<String> stderrSubscription = _deviceObservationProcess.stderr
.transform<String>(utf8.decoder) .transform<String>(utf8.decoder)
.transform<String>(const LineSplitter()) .transform<String>(const LineSplitter())
.listen((String line) { .listen((String line) {
_logger.printTrace('xcdevice observe error: $line'); _logger.printTrace('xcdevice observe error: $line');
}); });
unawaited(_deviceObservationProcess?.exitCode.then((int status) { unawaited(_deviceObservationProcess.exitCode.then((int status) {
_logger.printTrace('xcdevice exited with code $exitCode'); _logger.printTrace('xcdevice exited with code $exitCode');
unawaited(stdoutSubscription.cancel()); unawaited(stdoutSubscription.cancel());
unawaited(stderrSubscription.cancel()); unawaited(stderrSubscription.cancel());
}).whenComplete(() async { }).whenComplete(() async {
if (_deviceIdentifierByEvent?.hasListener == true) { if (_deviceIdentifierByEvent.hasListener) {
// Tell listeners the process died. // Tell listeners the process died.
await _deviceIdentifierByEvent?.close(); await _deviceIdentifierByEvent.close();
} }
_deviceObservationProcess = null; _deviceObservationProcess = null;
...@@ -216,9 +219,9 @@ class XCDevice { ...@@ -216,9 +219,9 @@ class XCDevice {
_setupDeviceIdentifierByEventStream(); _setupDeviceIdentifierByEventStream();
})); }));
} on ProcessException catch (exception, stackTrace) { } on ProcessException catch (exception, stackTrace) {
_deviceIdentifierByEvent?.addError(exception, stackTrace); _deviceIdentifierByEvent.addError(exception, stackTrace);
} on ArgumentError catch (exception, stackTrace) { } on ArgumentError catch (exception, stackTrace) {
_deviceIdentifierByEvent?.addError(exception, stackTrace); _deviceIdentifierByEvent.addError(exception, stackTrace);
} }
} }
...@@ -227,8 +230,8 @@ class XCDevice { ...@@ -227,8 +230,8 @@ class XCDevice {
} }
/// [timeout] defaults to 2 seconds. /// [timeout] defaults to 2 seconds.
Future<List<IOSDevice>> getAvailableIOSDevices({ Duration? timeout }) async { Future<List<IOSDevice>> getAvailableIOSDevices({ Duration timeout }) async {
final List<Object>? allAvailableDevices = await _getAllDevices(timeout: timeout ?? const Duration(seconds: 2)); final List<dynamic> allAvailableDevices = await _getAllDevices(timeout: timeout ?? const Duration(seconds: 2));
if (allAvailableDevices == null) { if (allAvailableDevices == null) {
return const <IOSDevice>[]; return const <IOSDevice>[];
...@@ -272,29 +275,22 @@ class XCDevice { ...@@ -272,29 +275,22 @@ class XCDevice {
// ... // ...
final List<IOSDevice> devices = <IOSDevice>[]; final List<IOSDevice> devices = <IOSDevice>[];
for (final Object device in allAvailableDevices) { for (final dynamic device in allAvailableDevices) {
if (device is Map<String, Object?>) { if (device is Map<String, dynamic>) {
// Only include iPhone, iPad, iPod, or other iOS devices. // Only include iPhone, iPad, iPod, or other iOS devices.
if (!_isIPhoneOSDevice(device)) { if (!_isIPhoneOSDevice(device)) {
continue; continue;
} }
final String? identifier = device['identifier'] as String?;
final String? name = device['name'] as String?;
if (identifier == null || name == null) {
continue;
}
final Map<String, Object?>? errorProperties = _errorProperties(device); final Map<String, dynamic> errorProperties = _errorProperties(device);
if (errorProperties != null) { if (errorProperties != null) {
final String? errorMessage = _parseErrorMessage(errorProperties); final String errorMessage = _parseErrorMessage(errorProperties);
if (errorMessage != null) { if (errorMessage.contains('not paired')) {
if (errorMessage.contains('not paired')) { UsageEvent('device', 'ios-trust-failure', flutterUsage: globals.flutterUsage).send();
UsageEvent('device', 'ios-trust-failure', flutterUsage: globals.flutterUsage).send();
}
_logger.printTrace(errorMessage);
} }
_logger.printTrace(errorMessage);
final int? code = _errorCode(errorProperties); final int code = _errorCode(errorProperties);
// Temporary error -10: iPhone is busy: Preparing debugger support for iPhone. // Temporary error -10: iPhone is busy: Preparing debugger support for iPhone.
// Sometimes the app launch will fail on these devices until Xcode is done setting up the device. // Sometimes the app launch will fail on these devices until Xcode is done setting up the device.
...@@ -312,18 +308,18 @@ class XCDevice { ...@@ -312,18 +308,18 @@ class XCDevice {
continue; continue;
} }
String? sdkVersion = _sdkVersion(device); String sdkVersion = _sdkVersion(device);
if (sdkVersion != null) { if (sdkVersion != null) {
final String? buildVersion = _buildVersion(device); final String buildVersion = _buildVersion(device);
if (buildVersion != null) { if (buildVersion != null) {
sdkVersion = '$sdkVersion $buildVersion'; sdkVersion = '$sdkVersion $buildVersion';
} }
} }
devices.add(IOSDevice( devices.add(IOSDevice(
identifier, device['identifier'] as String,
name: name, name: device['name'] as String,
cpuArchitecture: _cpuArchitecture(device), cpuArchitecture: _cpuArchitecture(device),
interfaceType: interface, interfaceType: interface,
sdkVersion: sdkVersion, sdkVersion: sdkVersion,
...@@ -342,30 +338,33 @@ class XCDevice { ...@@ -342,30 +338,33 @@ class XCDevice {
/// 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.
/// Excludes simulators. /// Excludes simulators.
static bool _isIPhoneOSDevice(Map<String, Object?> deviceProperties) { static bool _isIPhoneOSDevice(Map<String, dynamic> deviceProperties) {
final Object? platform = deviceProperties['platform']; if (deviceProperties.containsKey('platform')) {
if (platform is String) { final String platform = deviceProperties['platform'] as String;
return platform == 'com.apple.platform.iphoneos'; return platform == 'com.apple.platform.iphoneos';
} }
return false; return false;
} }
static Map<String, Object?>? _errorProperties(Map<String, Object?> deviceProperties) { static Map<String, dynamic> _errorProperties(Map<String, dynamic> deviceProperties) {
final Object? error = deviceProperties['error']; if (deviceProperties.containsKey('error')) {
return error is Map<String, Object?> ? error : null; return deviceProperties['error'] as Map<String, dynamic>;
}
return null;
} }
static int? _errorCode(Map<String, Object?> errorProperties) { static int _errorCode(Map<String, dynamic> errorProperties) {
final Object? code = errorProperties['code']; if (errorProperties.containsKey('code') && errorProperties['code'] is int) {
return code is int ? code : null; return errorProperties['code'] as int;
}
return null;
} }
static IOSDeviceConnectionInterface _interfaceType(Map<String, Object?> deviceProperties) { static IOSDeviceConnectionInterface _interfaceType(Map<String, dynamic> deviceProperties) {
// Interface can be "usb", "network", or "none" for simulators // Interface can be "usb", "network", or "none" for simulators
// and unknown future interfaces. // and unknown future interfaces.
final Object? interface = deviceProperties['interface']; if (deviceProperties.containsKey('interface')) {
if (interface is String) { if ((deviceProperties['interface'] as String).toLowerCase() == 'network') {
if (interface.toLowerCase() == 'network') {
return IOSDeviceConnectionInterface.network; return IOSDeviceConnectionInterface.network;
} else { } else {
return IOSDeviceConnectionInterface.usb; return IOSDeviceConnectionInterface.usb;
...@@ -375,13 +374,13 @@ class XCDevice { ...@@ -375,13 +374,13 @@ class XCDevice {
return IOSDeviceConnectionInterface.none; return IOSDeviceConnectionInterface.none;
} }
static String? _sdkVersion(Map<String, Object?> deviceProperties) { static String _sdkVersion(Map<String, dynamic> deviceProperties) {
final Object? operatingSystemVersion = deviceProperties['operatingSystemVersion']; if (deviceProperties.containsKey('operatingSystemVersion')) {
if (operatingSystemVersion is String) {
// Parse out the OS version, ignore the build number in parentheses. // Parse out the OS version, ignore the build number in parentheses.
// "13.3 (17C54)" // "13.3 (17C54)"
final RegExp operatingSystemRegex = RegExp(r'(.*) \(.*\)$'); final RegExp operatingSystemRegex = RegExp(r'(.*) \(.*\)$');
if (operatingSystemRegex.hasMatch(operatingSystemVersion.trim())) { final String operatingSystemVersion = deviceProperties['operatingSystemVersion'] as String;
if(operatingSystemRegex.hasMatch(operatingSystemVersion.trim())) {
return operatingSystemRegex.firstMatch(operatingSystemVersion.trim())?.group(1); return operatingSystemRegex.firstMatch(operatingSystemVersion.trim())?.group(1);
} }
return operatingSystemVersion; return operatingSystemVersion;
...@@ -389,20 +388,20 @@ class XCDevice { ...@@ -389,20 +388,20 @@ class XCDevice {
return null; return null;
} }
static String? _buildVersion(Map<String, Object?> deviceProperties) { static String _buildVersion(Map<String, dynamic> deviceProperties) {
final Object? operatingSystemVersion = deviceProperties['operatingSystemVersion']; if (deviceProperties.containsKey('operatingSystemVersion')) {
if (operatingSystemVersion is String) {
// Parse out the build version, for example 17C54 from "13.3 (17C54)". // Parse out the build version, for example 17C54 from "13.3 (17C54)".
final RegExp buildVersionRegex = RegExp(r'\(.*\)$'); final RegExp buildVersionRegex = RegExp(r'\(.*\)$');
final String operatingSystemVersion = deviceProperties['operatingSystemVersion'] as String;
return buildVersionRegex.firstMatch(operatingSystemVersion)?.group(0)?.replaceAll(RegExp('[()]'), ''); return buildVersionRegex.firstMatch(operatingSystemVersion)?.group(0)?.replaceAll(RegExp('[()]'), '');
} }
return null; return null;
} }
DarwinArch _cpuArchitecture(Map<String, Object?> deviceProperties) { DarwinArch _cpuArchitecture(Map<String, dynamic> deviceProperties) {
DarwinArch? cpuArchitecture; DarwinArch cpuArchitecture;
final Object? architecture = deviceProperties['architecture']; if (deviceProperties.containsKey('architecture')) {
if (architecture is String) { final String architecture = deviceProperties['architecture'] as String;
try { try {
cpuArchitecture = getIOSArchForName(architecture); cpuArchitecture = getIOSArchForName(architecture);
} on Exception { } on Exception {
...@@ -421,11 +420,11 @@ class XCDevice { ...@@ -421,11 +420,11 @@ class XCDevice {
); );
} }
} }
return cpuArchitecture ?? DarwinArch.arm64; return cpuArchitecture;
} }
/// Error message parsed from xcdevice. null if no error. /// Error message parsed from xcdevice. null if no error.
static String? _parseErrorMessage(Map<String, Object?>? errorProperties) { static String _parseErrorMessage(Map<String, dynamic> errorProperties) {
// { // {
// "simulator" : false, // "simulator" : false,
// "operatingSystemVersion" : "13.3 (17C54)", // "operatingSystemVersion" : "13.3 (17C54)",
...@@ -480,8 +479,8 @@ class XCDevice { ...@@ -480,8 +479,8 @@ class XCDevice {
final StringBuffer errorMessage = StringBuffer('Error: '); final StringBuffer errorMessage = StringBuffer('Error: ');
final Object? description = errorProperties['description']; if (errorProperties.containsKey('description')) {
if (description is String) { final String description = errorProperties['description'] as String;
errorMessage.write(description); errorMessage.write(description);
if (!description.endsWith('.')) { if (!description.endsWith('.')) {
errorMessage.write('.'); errorMessage.write('.');
...@@ -490,12 +489,12 @@ class XCDevice { ...@@ -490,12 +489,12 @@ class XCDevice {
errorMessage.write('Xcode pairing error.'); errorMessage.write('Xcode pairing error.');
} }
final Object? recoverySuggestion = errorProperties['recoverySuggestion']; if (errorProperties.containsKey('recoverySuggestion')) {
if (recoverySuggestion is String) { final String recoverySuggestion = errorProperties['recoverySuggestion'] as String;
errorMessage.write(' $recoverySuggestion'); errorMessage.write(' $recoverySuggestion');
} }
final int? code = _errorCode(errorProperties); final int code = _errorCode(errorProperties);
if (code != null) { if (code != null) {
errorMessage.write(' (code $code)'); errorMessage.write(' (code $code)');
} }
...@@ -505,7 +504,7 @@ class XCDevice { ...@@ -505,7 +504,7 @@ class XCDevice {
/// List of all devices reporting errors. /// List of all devices reporting errors.
Future<List<String>> getDiagnostics() async { Future<List<String>> getDiagnostics() async {
final List<Object>? allAvailableDevices = await _getAllDevices( final List<dynamic> allAvailableDevices = await _getAllDevices(
useCache: true, useCache: true,
timeout: const Duration(seconds: 2) timeout: const Duration(seconds: 2)
); );
...@@ -515,12 +514,13 @@ class XCDevice { ...@@ -515,12 +514,13 @@ class XCDevice {
} }
final List<String> diagnostics = <String>[]; final List<String> diagnostics = <String>[];
for (final Object deviceProperties in allAvailableDevices) { for (final dynamic device in allAvailableDevices) {
if (deviceProperties is! Map<String, Object?>) { if (device is! Map) {
continue; continue;
} }
final Map<String, Object?>? errorProperties = _errorProperties(deviceProperties); final Map<String, dynamic> deviceProperties = device as Map<String, dynamic>;
final String? errorMessage = _parseErrorMessage(errorProperties); final Map<String, dynamic> errorProperties = _errorProperties(deviceProperties);
final String errorMessage = _parseErrorMessage(errorProperties);
if (errorMessage != null) { if (errorMessage != null) {
diagnostics.add(errorMessage); diagnostics.add(errorMessage);
} }
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:async'; import 'dart:async';
import 'dart:io' as io; import 'dart:io' as io;
...@@ -37,17 +39,16 @@ void main() { ...@@ -37,17 +39,16 @@ void main() {
group('IOSDevice', () { group('IOSDevice', () {
final List<Platform> unsupportedPlatforms = <Platform>[linuxPlatform, windowsPlatform]; final List<Platform> unsupportedPlatforms = <Platform>[linuxPlatform, windowsPlatform];
late Cache cache; Cache cache;
late Logger logger; Logger logger;
late IOSDeploy iosDeploy; IOSDeploy iosDeploy;
late IMobileDevice iMobileDevice; IMobileDevice iMobileDevice;
late FileSystem fileSystem; FileSystem nullFileSystem;
setUp(() { setUp(() {
final Artifacts artifacts = Artifacts.test(); final Artifacts artifacts = Artifacts.test();
cache = Cache.test(processManager: FakeProcessManager.any()); cache = Cache.test(processManager: FakeProcessManager.any());
logger = BufferLogger.test(); logger = BufferLogger.test();
fileSystem = MemoryFileSystem.test();
iosDeploy = IOSDeploy( iosDeploy = IOSDeploy(
artifacts: artifacts, artifacts: artifacts,
cache: cache, cache: cache,
...@@ -67,7 +68,7 @@ void main() { ...@@ -67,7 +68,7 @@ void main() {
IOSDevice( IOSDevice(
'device-123', 'device-123',
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()), iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
fileSystem: fileSystem, fileSystem: nullFileSystem,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
...@@ -83,7 +84,7 @@ void main() { ...@@ -83,7 +84,7 @@ void main() {
expect(IOSDevice( expect(IOSDevice(
'device-123', 'device-123',
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()), iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
fileSystem: fileSystem, fileSystem: nullFileSystem,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
...@@ -96,7 +97,7 @@ void main() { ...@@ -96,7 +97,7 @@ void main() {
expect(IOSDevice( expect(IOSDevice(
'device-123', 'device-123',
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()), iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
fileSystem: fileSystem, fileSystem: nullFileSystem,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
...@@ -109,7 +110,7 @@ void main() { ...@@ -109,7 +110,7 @@ void main() {
expect(IOSDevice( expect(IOSDevice(
'device-123', 'device-123',
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()), iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
fileSystem: fileSystem, fileSystem: nullFileSystem,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
...@@ -122,7 +123,7 @@ void main() { ...@@ -122,7 +123,7 @@ void main() {
expect(IOSDevice( expect(IOSDevice(
'device-123', 'device-123',
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()), iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
fileSystem: fileSystem, fileSystem: nullFileSystem,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
...@@ -135,7 +136,7 @@ void main() { ...@@ -135,7 +136,7 @@ void main() {
expect(IOSDevice( expect(IOSDevice(
'device-123', 'device-123',
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()), iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
fileSystem: fileSystem, fileSystem: nullFileSystem,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
...@@ -151,7 +152,7 @@ void main() { ...@@ -151,7 +152,7 @@ void main() {
final IOSDevice device = IOSDevice( final IOSDevice device = IOSDevice(
'device-123', 'device-123',
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()), iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
fileSystem: fileSystem, fileSystem: nullFileSystem,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
...@@ -169,7 +170,7 @@ void main() { ...@@ -169,7 +170,7 @@ void main() {
final IOSDevice device = IOSDevice( final IOSDevice device = IOSDevice(
'device-123', 'device-123',
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()), iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
fileSystem: fileSystem, fileSystem: nullFileSystem,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
...@@ -193,7 +194,7 @@ void main() { ...@@ -193,7 +194,7 @@ void main() {
IOSDevice( IOSDevice(
'device-123', 'device-123',
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()), iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
fileSystem: fileSystem, fileSystem: nullFileSystem,
logger: logger, logger: logger,
platform: platform, platform: platform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
...@@ -210,21 +211,21 @@ void main() { ...@@ -210,21 +211,21 @@ void main() {
} }
group('.dispose()', () { group('.dispose()', () {
late IOSDevice device; IOSDevice device;
late FakeIOSApp appPackage1; FakeIOSApp appPackage1;
late FakeIOSApp appPackage2; FakeIOSApp appPackage2;
late IOSDeviceLogReader logReader1; IOSDeviceLogReader logReader1;
late IOSDeviceLogReader logReader2; IOSDeviceLogReader logReader2;
late FakeProcess process1; FakeProcess process1;
late FakeProcess process2; FakeProcess process2;
late FakeProcess process3; FakeProcess process3;
late IOSDevicePortForwarder portForwarder; IOSDevicePortForwarder portForwarder;
late ForwardedPort forwardedPort; ForwardedPort forwardedPort;
late Cache cache; Cache cache;
late Logger logger; Logger logger;
late IOSDeploy iosDeploy; IOSDeploy iosDeploy;
late FileSystem fileSystem; FileSystem nullFileSystem;
late IProxy iproxy; IProxy iproxy;
IOSDevicePortForwarder createPortForwarder( IOSDevicePortForwarder createPortForwarder(
ForwardedPort forwardedPort, ForwardedPort forwardedPort,
...@@ -234,7 +235,7 @@ void main() { ...@@ -234,7 +235,7 @@ void main() {
id: device.id, id: device.id,
logger: logger, logger: logger,
operatingSystemUtils: OperatingSystemUtils( operatingSystemUtils: OperatingSystemUtils(
fileSystem: fileSystem, fileSystem: nullFileSystem,
logger: logger, logger: logger,
platform: FakePlatform(operatingSystem: 'macos'), platform: FakePlatform(operatingSystem: 'macos'),
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
...@@ -252,7 +253,7 @@ void main() { ...@@ -252,7 +253,7 @@ void main() {
final IOSDeviceLogReader logReader = IOSDeviceLogReader.create( final IOSDeviceLogReader logReader = IOSDeviceLogReader.create(
device: device, device: device,
app: appPackage, app: appPackage,
iMobileDevice: IMobileDevice.test(processManager: FakeProcessManager.any()), iMobileDevice: null, // not used by this test.
); );
logReader.idevicesyslogProcess = process; logReader.idevicesyslogProcess = process;
return logReader; return logReader;
...@@ -268,8 +269,6 @@ void main() { ...@@ -268,8 +269,6 @@ void main() {
cache = Cache.test( cache = Cache.test(
processManager: FakeProcessManager.any(), processManager: FakeProcessManager.any(),
); );
fileSystem = MemoryFileSystem.test();
logger = BufferLogger.test();
iosDeploy = IOSDeploy( iosDeploy = IOSDeploy(
artifacts: Artifacts.test(), artifacts: Artifacts.test(),
cache: cache, cache: cache,
...@@ -283,7 +282,7 @@ void main() { ...@@ -283,7 +282,7 @@ void main() {
device = IOSDevice( device = IOSDevice(
'123', '123',
iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()), iProxy: IProxy.test(logger: logger, processManager: FakeProcessManager.any()),
fileSystem: fileSystem, fileSystem: nullFileSystem,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
...@@ -310,15 +309,15 @@ void main() { ...@@ -310,15 +309,15 @@ void main() {
}); });
group('polling', () { group('polling', () {
late FakeXcdevice xcdevice; FakeXcdevice xcdevice;
late Cache cache; Cache cache;
late FakeProcessManager fakeProcessManager; FakeProcessManager fakeProcessManager;
late BufferLogger logger; BufferLogger logger;
late IOSDeploy iosDeploy; IOSDeploy iosDeploy;
late IMobileDevice iMobileDevice; IMobileDevice iMobileDevice;
late IOSWorkflow iosWorkflow; IOSWorkflow iosWorkflow;
late IOSDevice device1; IOSDevice device1;
late IOSDevice device2; IOSDevice device2;
setUp(() { setUp(() {
xcdevice = FakeXcdevice(); xcdevice = FakeXcdevice();
...@@ -415,22 +414,22 @@ void main() { ...@@ -415,22 +414,22 @@ void main() {
await iosDevices.startPolling(); await iosDevices.startPolling();
expect(xcdevice.getAvailableIOSDevicesCount, 1); expect(xcdevice.getAvailableIOSDevicesCount, 1);
expect(iosDevices.deviceNotifier!.items, isEmpty); expect(iosDevices.deviceNotifier.items, isEmpty);
expect(xcdevice.deviceEventController.hasListener, isTrue); expect(xcdevice.deviceEventController.hasListener, isTrue);
xcdevice.deviceEventController.add(<XCDeviceEvent, String>{ xcdevice.deviceEventController.add(<XCDeviceEvent, String>{
XCDeviceEvent.attach: 'd83d5bc53967baa0ee18626ba87b6254b2ab5418' XCDeviceEvent.attach: 'd83d5bc53967baa0ee18626ba87b6254b2ab5418'
}); });
await added.future; await added.future;
expect(iosDevices.deviceNotifier!.items.length, 2); expect(iosDevices.deviceNotifier.items.length, 2);
expect(iosDevices.deviceNotifier!.items, contains(device1)); expect(iosDevices.deviceNotifier.items, contains(device1));
expect(iosDevices.deviceNotifier!.items, contains(device2)); expect(iosDevices.deviceNotifier.items, contains(device2));
xcdevice.deviceEventController.add(<XCDeviceEvent, String>{ xcdevice.deviceEventController.add(<XCDeviceEvent, String>{
XCDeviceEvent.detach: 'd83d5bc53967baa0ee18626ba87b6254b2ab5418' XCDeviceEvent.detach: 'd83d5bc53967baa0ee18626ba87b6254b2ab5418'
}); });
await removed.future; await removed.future;
expect(iosDevices.deviceNotifier!.items, <Device>[device2]); expect(iosDevices.deviceNotifier.items, <Device>[device2]);
// Remove stream will throw over-completion if called more than once // Remove stream will throw over-completion if called more than once
// which proves this is ignored. // which proves this is ignored.
...@@ -490,7 +489,7 @@ void main() { ...@@ -490,7 +489,7 @@ void main() {
xcdevice.devices.add(<IOSDevice>[]); xcdevice.devices.add(<IOSDevice>[]);
await iosDevices.startPolling(); await iosDevices.startPolling();
expect(iosDevices.deviceNotifier!.items, isEmpty); expect(iosDevices.deviceNotifier.items, isEmpty);
expect(xcdevice.deviceEventController.hasListener, isTrue); expect(xcdevice.deviceEventController.hasListener, isTrue);
iosDevices.dispose(); iosDevices.dispose();
...@@ -532,9 +531,9 @@ void main() { ...@@ -532,9 +531,9 @@ void main() {
}); });
group('getDiagnostics', () { group('getDiagnostics', () {
late FakeXcdevice xcdevice; FakeXcdevice xcdevice;
late IOSWorkflow iosWorkflow; IOSWorkflow iosWorkflow;
late Logger logger; Logger logger;
setUp(() { setUp(() {
xcdevice = FakeXcdevice(); xcdevice = FakeXcdevice();
...@@ -602,7 +601,7 @@ class FakeXcdevice extends Fake implements XCDevice { ...@@ -602,7 +601,7 @@ class FakeXcdevice extends Fake implements XCDevice {
} }
@override @override
Future<List<IOSDevice>> getAvailableIOSDevices({Duration? timeout}) async { Future<List<IOSDevice>> getAvailableIOSDevices({Duration timeout}) async {
return devices[getAvailableIOSDevicesCount++]; return devices[getAvailableIOSDevicesCount++];
} }
} }
......
...@@ -5,16 +5,12 @@ ...@@ -5,16 +5,12 @@
// @dart = 2.8 // @dart = 2.8
import 'package:file/memory.dart'; import 'package:file/memory.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.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/ios/devices.dart'; import 'package:flutter_tools/src/ios/devices.dart';
import 'package:flutter_tools/src/ios/ios_deploy.dart';
import 'package:flutter_tools/src/ios/iproxy.dart'; import 'package:flutter_tools/src/ios/iproxy.dart';
import 'package:flutter_tools/src/ios/mac.dart';
import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/project.dart';
import '../../src/common.dart'; import '../../src/common.dart';
...@@ -80,26 +76,17 @@ flutter: ...@@ -80,26 +76,17 @@ flutter:
} }
IOSDevice setUpIOSDevice(FileSystem fileSystem) { IOSDevice setUpIOSDevice(FileSystem fileSystem) {
final Platform platform = FakePlatform(operatingSystem: 'macos');
final Logger logger = BufferLogger.test();
final ProcessManager processManager = FakeProcessManager.any();
return IOSDevice( return IOSDevice(
'test', 'test',
fileSystem: fileSystem, fileSystem: fileSystem,
logger: logger, logger: BufferLogger.test(),
iosDeploy: IOSDeploy( iosDeploy: null, // not used in this test
platform: platform, iMobileDevice: null, // not used in this test
logger: logger, platform: FakePlatform(operatingSystem: 'macos'),
processManager: processManager,
artifacts: Artifacts.test(),
cache: Cache.test(processManager: processManager),
),
iMobileDevice: IMobileDevice.test(processManager: processManager),
platform: platform,
name: 'iPhone 1', name: 'iPhone 1',
sdkVersion: '13.3', sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
iProxy: IProxy.test(logger: logger, processManager: processManager), iProxy: IProxy.test(logger: BufferLogger.test(), processManager: FakeProcessManager.any()),
interfaceType: IOSDeviceConnectionInterface.usb, interfaceType: IOSDeviceConnectionInterface.usb,
); );
} }
...@@ -326,7 +326,7 @@ void main() { ...@@ -326,7 +326,7 @@ void main() {
processManager: fakeProcessManager, processManager: fakeProcessManager,
logger: logger, logger: logger,
xcode: xcode, xcode: xcode,
platform: FakePlatform(operatingSystem: 'macos'), platform: null,
artifacts: Artifacts.test(), artifacts: Artifacts.test(),
cache: Cache.test(processManager: FakeProcessManager.any()), cache: Cache.test(processManager: FakeProcessManager.any()),
iproxy: IProxy.test(logger: logger, processManager: fakeProcessManager), iproxy: IProxy.test(logger: logger, processManager: fakeProcessManager),
...@@ -354,7 +354,7 @@ void main() { ...@@ -354,7 +354,7 @@ void main() {
processManager: fakeProcessManager, processManager: fakeProcessManager,
logger: logger, logger: logger,
xcode: xcode, xcode: xcode,
platform: FakePlatform(operatingSystem: 'macos'), platform: null,
artifacts: Artifacts.test(), artifacts: Artifacts.test(),
cache: Cache.test(processManager: FakeProcessManager.any()), cache: Cache.test(processManager: FakeProcessManager.any()),
iproxy: IProxy.test(logger: logger, processManager: fakeProcessManager), iproxy: IProxy.test(logger: logger, processManager: fakeProcessManager),
......
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