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