Unverified Commit 2d9902d9 authored by Christopher Fujino's avatar Christopher Fujino Committed by GitHub

Cleanup ios devices (#52568)

parent dc8ffe04
...@@ -76,7 +76,11 @@ class DeviceManager { ...@@ -76,7 +76,11 @@ class DeviceManager {
androidWorkflow: androidWorkflow, androidWorkflow: androidWorkflow,
processManager: globals.processManager, processManager: globals.processManager,
), ),
IOSDevices(), IOSDevices(
platform: globals.platform,
xcdevice: globals.xcdevice,
iosWorkflow: globals.iosWorkflow,
),
IOSSimulators(iosSimulatorUtils: globals.iosSimulatorUtils), IOSSimulators(iosSimulatorUtils: globals.iosSimulatorUtils),
FuchsiaDevices(), FuchsiaDevices(),
FlutterTesterDevices(), FlutterTesterDevices(),
......
...@@ -27,25 +27,51 @@ import '../protocol_discovery.dart'; ...@@ -27,25 +27,51 @@ import '../protocol_discovery.dart';
import '../vmservice.dart'; import '../vmservice.dart';
import 'fallback_discovery.dart'; import 'fallback_discovery.dart';
import 'ios_deploy.dart'; import 'ios_deploy.dart';
import 'ios_workflow.dart';
import 'mac.dart'; import 'mac.dart';
class IOSDevices extends PollingDeviceDiscovery { class IOSDevices extends PollingDeviceDiscovery {
IOSDevices() : super('iOS devices'); // TODO(fujino): make these required and remove fallbacks once internal invocations migrated
IOSDevices({
Platform platform,
XCDevice xcdevice,
IOSWorkflow iosWorkflow,
}) : _platform = platform ?? globals.platform,
_xcdevice = xcdevice ?? globals.xcdevice,
_iosWorkflow = iosWorkflow ?? globals.iosWorkflow,
super('iOS devices');
final Platform _platform;
final XCDevice _xcdevice;
final IOSWorkflow _iosWorkflow;
@override @override
bool get supportsPlatform => globals.platform.isMacOS; bool get supportsPlatform => _platform.isMacOS;
@override @override
bool get canListAnything => globals.iosWorkflow.canListDevices; bool get canListAnything => _iosWorkflow.canListDevices;
@override @override
Future<List<Device>> pollingGetDevices({ Duration timeout }) { Future<List<Device>> pollingGetDevices({ Duration timeout }) async {
return IOSDevice.getAttachedDevices( if (!_platform.isMacOS) {
globals.platform, globals.xcdevice, timeout: timeout); throw UnsupportedError(
'Control of iOS devices or simulators only supported on macOS.'
);
}
return await _xcdevice.getAvailableTetheredIOSDevices(timeout: timeout);
} }
@override @override
Future<List<String>> getDiagnostics() => IOSDevice.getDiagnostics(globals.platform, globals.xcdevice); Future<List<String>> getDiagnostics() async {
if (!_platform.isMacOS) {
return const <String>[
'Control of iOS devices or simulators only supported on macOS.'
];
}
return await _xcdevice.getDiagnostics();
}
} }
class IOSDevice extends Device { class IOSDevice extends Device {
...@@ -57,10 +83,13 @@ class IOSDevice extends Device { ...@@ -57,10 +83,13 @@ class IOSDevice extends Device {
@required Platform platform, @required Platform platform,
@required Artifacts artifacts, @required Artifacts artifacts,
@required IOSDeploy iosDeploy, @required IOSDeploy iosDeploy,
@required Logger logger,
}) })
: _sdkVersion = sdkVersion, : _sdkVersion = sdkVersion,
_iosDeploy = iosDeploy, _iosDeploy = iosDeploy,
_fileSystem = fileSystem, _fileSystem = fileSystem,
_logger = logger,
_platform = platform,
super( super(
id, id,
category: Category.mobile, category: Category.mobile,
...@@ -82,6 +111,8 @@ class IOSDevice extends Device { ...@@ -82,6 +111,8 @@ 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 Platform _platform;
/// May be 0 if version cannot be parsed. /// May be 0 if version cannot be parsed.
int get majorSdkVersion { int get majorSdkVersion {
...@@ -113,22 +144,6 @@ class IOSDevice extends Device { ...@@ -113,22 +144,6 @@ class IOSDevice extends Device {
@override @override
bool get supportsStartPaused => false; bool get supportsStartPaused => false;
static Future<List<IOSDevice>> getAttachedDevices(Platform platform, XCDevice xcdevice, { Duration timeout }) async {
if (!platform.isMacOS) {
throw UnsupportedError('Control of iOS devices or simulators only supported on macOS.');
}
return await xcdevice.getAvailableTetheredIOSDevices(timeout: timeout);
}
static Future<List<String>> getDiagnostics(Platform platform, XCDevice xcdevice) async {
if (!platform.isMacOS) {
return const <String>['Control of iOS devices or simulators only supported on macOS.'];
}
return await xcdevice.getDiagnostics();
}
@override @override
Future<bool> isAppInstalled(IOSApp app) async { Future<bool> isAppInstalled(IOSApp app) async {
bool result; bool result;
...@@ -138,7 +153,7 @@ class IOSDevice extends Device { ...@@ -138,7 +153,7 @@ class IOSDevice extends Device {
deviceId: id, deviceId: id,
); );
} on ProcessException catch (e) { } on ProcessException catch (e) {
globals.printError(e.message); _logger.printError(e.message);
return false; return false;
} }
return result; return result;
...@@ -151,7 +166,7 @@ class IOSDevice extends Device { ...@@ -151,7 +166,7 @@ class IOSDevice extends Device {
Future<bool> installApp(IOSApp app) async { Future<bool> installApp(IOSApp app) async {
final Directory bundle = _fileSystem.directory(app.deviceBundlePath); final Directory bundle = _fileSystem.directory(app.deviceBundlePath);
if (!bundle.existsSync()) { if (!bundle.existsSync()) {
globals.printError('Could not find application bundle at ${bundle.path}; have you run "flutter build ios"?'); _logger.printError('Could not find application bundle at ${bundle.path}; have you run "flutter build ios"?');
return false; return false;
} }
...@@ -163,14 +178,14 @@ class IOSDevice extends Device { ...@@ -163,14 +178,14 @@ class IOSDevice extends Device {
launchArguments: <String>[], launchArguments: <String>[],
); );
} on ProcessException catch (e) { } on ProcessException catch (e) {
globals.printError(e.message); _logger.printError(e.message);
return false; return false;
} }
if (installationResult != 0) { if (installationResult != 0) {
globals.printError('Could not install ${bundle.path} on $id.'); _logger.printError('Could not install ${bundle.path} on $id.');
globals.printError('Try launching Xcode and selecting "Product > Run" to fix the problem:'); _logger.printError('Try launching Xcode and selecting "Product > Run" to fix the problem:');
globals.printError(' open ios/Runner.xcworkspace'); _logger.printError(' open ios/Runner.xcworkspace');
globals.printError(''); _logger.printError('');
return false; return false;
} }
return true; return true;
...@@ -185,11 +200,11 @@ class IOSDevice extends Device { ...@@ -185,11 +200,11 @@ class IOSDevice extends Device {
bundleId: app.id, bundleId: app.id,
); );
} on ProcessException catch (e) { } on ProcessException catch (e) {
globals.printError(e.message); _logger.printError(e.message);
return false; return false;
} }
if (uninstallationResult != 0) { if (uninstallationResult != 0) {
globals.printError('Could not uninstall ${app.id} on $id.'); _logger.printError('Could not uninstall ${app.id} on $id.');
return false; return false;
} }
return true; return true;
...@@ -212,7 +227,7 @@ class IOSDevice extends Device { ...@@ -212,7 +227,7 @@ class IOSDevice extends Device {
if (!prebuiltApplication) { if (!prebuiltApplication) {
// TODO(chinmaygarde): Use mainPath, route. // TODO(chinmaygarde): Use mainPath, route.
globals.printTrace('Building ${package.name} for $id'); _logger.printTrace('Building ${package.name} for $id');
// Step 1: Build the precompiled/DBC application if necessary. // Step 1: Build the precompiled/DBC application if necessary.
final XcodeBuildResult buildResult = await buildXcodeProject( final XcodeBuildResult buildResult = await buildXcodeProject(
...@@ -223,9 +238,9 @@ class IOSDevice extends Device { ...@@ -223,9 +238,9 @@ class IOSDevice extends Device {
activeArch: cpuArchitecture, activeArch: cpuArchitecture,
); );
if (!buildResult.success) { if (!buildResult.success) {
globals.printError('Could not build the precompiled application for the device.'); _logger.printError('Could not build the precompiled application for the device.');
await diagnoseXcodeBuildFailure(buildResult); await diagnoseXcodeBuildFailure(buildResult);
globals.printError(''); _logger.printError('');
return LaunchResult.failed(); return LaunchResult.failed();
} }
packageId = buildResult.xcodeBuildExecution?.buildSettings['PRODUCT_BUNDLE_IDENTIFIER']; packageId = buildResult.xcodeBuildExecution?.buildSettings['PRODUCT_BUNDLE_IDENTIFIER'];
...@@ -240,7 +255,7 @@ class IOSDevice extends Device { ...@@ -240,7 +255,7 @@ class IOSDevice extends Device {
// Step 2: Check that the application exists at the specified path. // Step 2: Check that the application exists at the specified path.
final Directory bundle = _fileSystem.directory(package.deviceBundlePath); final Directory bundle = _fileSystem.directory(package.deviceBundlePath);
if (!bundle.existsSync()) { if (!bundle.existsSync()) {
globals.printError('Could not find the built application bundle at ${bundle.path}.'); _logger.printError('Could not find the built application bundle at ${bundle.path}.');
return LaunchResult.failed(); return LaunchResult.failed();
} }
...@@ -267,7 +282,7 @@ class IOSDevice extends Device { ...@@ -267,7 +282,7 @@ class IOSDevice extends Device {
// "system_debug_ios" integration test in the CI, which simulates a // "system_debug_ios" integration test in the CI, which simulates a
// home-screen launch. // home-screen launch.
if (debuggingOptions.debuggingEnabled && if (debuggingOptions.debuggingEnabled &&
globals.platform.environment['FLUTTER_TOOLS_DEBUG_WITHOUT_CHECKED_MODE'] != 'true') ...<String>[ _platform.environment['FLUTTER_TOOLS_DEBUG_WITHOUT_CHECKED_MODE'] != 'true') ...<String>[
'--enable-checked-mode', '--enable-checked-mode',
'--verify-entry-points', '--verify-entry-points',
], ],
...@@ -282,13 +297,13 @@ class IOSDevice extends Device { ...@@ -282,13 +297,13 @@ class IOSDevice extends Device {
if (platformArgs['trace-startup'] as bool ?? false) '--trace-startup', if (platformArgs['trace-startup'] as bool ?? false) '--trace-startup',
]; ];
final Status installStatus = globals.logger.startProgress( final Status installStatus = _logger.startProgress(
'Installing and launching...', 'Installing and launching...',
timeout: timeoutConfiguration.slowOperation); timeout: timeoutConfiguration.slowOperation);
try { try {
ProtocolDiscovery observatoryDiscovery; ProtocolDiscovery observatoryDiscovery;
if (debuggingOptions.debuggingEnabled) { if (debuggingOptions.debuggingEnabled) {
globals.printTrace('Debugging is enabled, connecting to observatory'); _logger.printTrace('Debugging is enabled, connecting to observatory');
observatoryDiscovery = ProtocolDiscovery.observatory( observatoryDiscovery = ProtocolDiscovery.observatory(
getLogReader(app: package), getLogReader(app: package),
portForwarder: portForwarder, portForwarder: portForwarder,
...@@ -303,10 +318,10 @@ class IOSDevice extends Device { ...@@ -303,10 +318,10 @@ class IOSDevice extends Device {
launchArguments: launchArguments, launchArguments: launchArguments,
); );
if (installationResult != 0) { if (installationResult != 0) {
globals.printError('Could not run ${bundle.path} on $id.'); _logger.printError('Could not run ${bundle.path} on $id.');
globals.printError('Try launching Xcode and selecting "Product > Run" to fix the problem:'); _logger.printError('Try launching Xcode and selecting "Product > Run" to fix the problem:');
globals.printError(' open ios/Runner.xcworkspace'); _logger.printError(' open ios/Runner.xcworkspace');
globals.printError(''); _logger.printError('');
return LaunchResult.failed(); return LaunchResult.failed();
} }
...@@ -314,9 +329,9 @@ class IOSDevice extends Device { ...@@ -314,9 +329,9 @@ class IOSDevice extends Device {
return LaunchResult.succeeded(); return LaunchResult.succeeded();
} }
globals.printTrace('Application launched on the device. Waiting for observatory port.'); _logger.printTrace('Application launched on the device. Waiting for observatory port.');
final FallbackDiscovery fallbackDiscovery = FallbackDiscovery( final FallbackDiscovery fallbackDiscovery = FallbackDiscovery(
logger: globals.logger, logger: _logger,
mDnsObservatoryDiscovery: MDnsObservatoryDiscovery.instance, mDnsObservatoryDiscovery: MDnsObservatoryDiscovery.instance,
portForwarder: portForwarder, portForwarder: portForwarder,
protocolDiscovery: observatoryDiscovery, protocolDiscovery: observatoryDiscovery,
...@@ -334,7 +349,7 @@ class IOSDevice extends Device { ...@@ -334,7 +349,7 @@ class IOSDevice extends Device {
} }
return LaunchResult.succeeded(observatoryUri: localUri); return LaunchResult.succeeded(observatoryUri: localUri);
} on ProcessException catch (e) { } on ProcessException catch (e) {
globals.printError(e.message); _logger.printError(e.message);
return LaunchResult.failed(); return LaunchResult.failed();
} finally { } finally {
installStatus.stop(); installStatus.stop();
......
...@@ -2,13 +2,9 @@ ...@@ -2,13 +2,9 @@
// 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.
import '../base/context.dart';
import '../doctor.dart'; import '../doctor.dart';
import '../globals.dart' as globals; import '../globals.dart' as globals;
// TODO(fujino): remove once internal references replaced by `globals.iosWorkflow`
IOSWorkflow get iosWorkflow => context.get<IOSWorkflow>();
class IOSWorkflow implements Workflow { class IOSWorkflow implements Workflow {
const IOSWorkflow(); const IOSWorkflow();
......
...@@ -354,6 +354,7 @@ class XCDevice { ...@@ -354,6 +354,7 @@ class XCDevice {
sdkVersion: _sdkVersion(deviceProperties), sdkVersion: _sdkVersion(deviceProperties),
artifacts: globals.artifacts, artifacts: globals.artifacts,
fileSystem: globals.fs, fileSystem: globals.fs,
logger: globals.logger,
iosDeploy: globals.iosDeploy, iosDeploy: globals.iosDeploy,
platform: globals.platform, platform: globals.platform,
)); ));
......
...@@ -21,6 +21,7 @@ import 'package:flutter_tools/src/doctor.dart'; ...@@ -21,6 +21,7 @@ import 'package:flutter_tools/src/doctor.dart';
import 'package:flutter_tools/src/ios/devices.dart'; import 'package:flutter_tools/src/ios/devices.dart';
import 'package:flutter_tools/src/ios/mac.dart'; import 'package:flutter_tools/src/ios/mac.dart';
import 'package:flutter_tools/src/ios/ios_deploy.dart'; import 'package:flutter_tools/src/ios/ios_deploy.dart';
import 'package:flutter_tools/src/ios/ios_workflow.dart';
import 'package:flutter_tools/src/macos/xcode.dart'; import 'package:flutter_tools/src/macos/xcode.dart';
import 'package:flutter_tools/src/mdns_discovery.dart'; import 'package:flutter_tools/src/mdns_discovery.dart';
import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/project.dart';
...@@ -74,6 +75,7 @@ void main() { ...@@ -74,6 +75,7 @@ void main() {
'device-123', 'device-123',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
name: 'iPhone 1', name: 'iPhone 1',
...@@ -87,6 +89,7 @@ void main() { ...@@ -87,6 +89,7 @@ void main() {
'device-123', 'device-123',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
name: 'iPhone 1', name: 'iPhone 1',
...@@ -97,6 +100,7 @@ void main() { ...@@ -97,6 +100,7 @@ void main() {
'device-123', 'device-123',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
name: 'iPhone 1', name: 'iPhone 1',
...@@ -107,6 +111,7 @@ void main() { ...@@ -107,6 +111,7 @@ void main() {
'device-123', 'device-123',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
name: 'iPhone 1', name: 'iPhone 1',
...@@ -117,6 +122,7 @@ void main() { ...@@ -117,6 +122,7 @@ void main() {
'device-123', 'device-123',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
name: 'iPhone 1', name: 'iPhone 1',
...@@ -127,6 +133,7 @@ void main() { ...@@ -127,6 +133,7 @@ void main() {
'device-123', 'device-123',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
name: 'iPhone 1', name: 'iPhone 1',
...@@ -143,6 +150,7 @@ void main() { ...@@ -143,6 +150,7 @@ void main() {
'device-123', 'device-123',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: platform, platform: platform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
name: 'iPhone 1', name: 'iPhone 1',
...@@ -157,46 +165,57 @@ void main() { ...@@ -157,46 +165,57 @@ void main() {
group('ios-deploy wrappers', () { group('ios-deploy wrappers', () {
const String appId = '789'; const String appId = '789';
const String deviceId = 'device-123';
IOSDevice device; IOSDevice device;
IOSDeploy iosDeploy; IOSDeploy iosDeploy;
FullMockProcessManager mockProcessManager; FakeProcessManager fakeProcessManager;
const String iosDeployPath = '/path/to/ios-deploy';
setUp(() { setUp(() {
mockProcessManager = FullMockProcessManager(); when(mockArtifacts.getArtifactPath(Artifact.iosDeploy, platform: TargetPlatform.ios))
.thenReturn(iosDeployPath);
});
testWithoutContext('isAppInstalled() catches ProcessException from ios-deploy', () async {
final MockIOSApp mockApp = MockIOSApp();
when(mockApp.id).thenReturn(appId);
fakeProcessManager = FakeProcessManager.list(<FakeCommand>[
FakeCommand(
command: const <String>[
iosDeployPath,
'--id',
deviceId,
'--exists',
'--bundle_id',
appId,
],
onRun: () => throw const ProcessException('ios-deploy', <String>[]),
)
]);
iosDeploy = IOSDeploy( iosDeploy = IOSDeploy(
artifacts: mockArtifacts, artifacts: mockArtifacts,
cache: mockCache, cache: mockCache,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
processManager: mockProcessManager, processManager: fakeProcessManager,
); );
device = IOSDevice( device = IOSDevice(
'device-123', deviceId,
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
name: 'iPhone 1', name: 'iPhone 1',
sdkVersion: '13.3', sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
); );
});
testUsingContext('isAppInstalled() catches ProcessException from ios-deploy', () async {
final MockIOSApp mockApp = MockIOSApp();
when(mockApp.id).thenReturn(appId);
when(mockProcessManager.run(
any,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).thenThrow(const ProcessException('ios-deploy', <String>[]));
final bool result = await device.isAppInstalled(mockApp); final bool result = await device.isAppInstalled(mockApp);
expect(result, false); expect(result, false);
}); });
testUsingContext('installApp() catches ProcessException from ios-deploy', () async { testWithoutContext('installApp() catches ProcessException from ios-deploy', () async {
const String bundlePath = '/path/to/bundle'; const String bundlePath = '/path/to/bundle';
final MockIOSApp mockApp = MockIOSApp(); final MockIOSApp mockApp = MockIOSApp();
when(mockApp.id).thenReturn(appId); when(mockApp.id).thenReturn(appId);
...@@ -204,24 +223,77 @@ void main() { ...@@ -204,24 +223,77 @@ void main() {
final MockDirectory mockDirectory = MockDirectory(); final MockDirectory mockDirectory = MockDirectory();
when(mockFileSystem.directory(bundlePath)).thenReturn(mockDirectory); when(mockFileSystem.directory(bundlePath)).thenReturn(mockDirectory);
when(mockDirectory.existsSync()).thenReturn(true); when(mockDirectory.existsSync()).thenReturn(true);
when(mockProcessManager.start( when(mockDirectory.path).thenReturn(bundlePath);
any, fakeProcessManager = FakeProcessManager.list(<FakeCommand>[
workingDirectory: anyNamed('workingDirectory'), FakeCommand(
environment: anyNamed('environment'), command: const <String>[
)).thenThrow(const ProcessException('ios-deploy', <String>[])); iosDeployPath,
'--id',
deviceId,
'--bundle',
bundlePath,
'--no-wifi',
],
onRun: () => throw const ProcessException('ios-deploy', <String>[]),
)
]);
iosDeploy = IOSDeploy(
artifacts: mockArtifacts,
cache: mockCache,
logger: logger,
platform: macPlatform,
processManager: fakeProcessManager,
);
device = IOSDevice(
deviceId,
artifacts: mockArtifacts,
fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform,
iosDeploy: iosDeploy,
name: 'iPhone 1',
sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64,
);
final bool result = await device.installApp(mockApp); final bool result = await device.installApp(mockApp);
expect(result, false); expect(result, false);
}); });
testUsingContext('uninstallApp() catches ProcessException from ios-deploy', () async { testWithoutContext('uninstallApp() catches ProcessException from ios-deploy', () async {
final MockIOSApp mockApp = MockIOSApp(); final MockIOSApp mockApp = MockIOSApp();
when(mockApp.id).thenReturn(appId); when(mockApp.id).thenReturn(appId);
when(mockProcessManager.start( fakeProcessManager = FakeProcessManager.list(<FakeCommand>[
any, FakeCommand(
workingDirectory: anyNamed('workingDirectory'), command: const <String>[
environment: anyNamed('environment'), iosDeployPath,
)).thenThrow(const ProcessException('ios-deploy', <String>[])); '--id',
deviceId,
'--uninstall_only',
'--bundle_id',
appId,
],
onRun: () => throw const ProcessException('ios-deploy', <String>[]),
)
]);
iosDeploy = IOSDeploy(
artifacts: mockArtifacts,
cache: mockCache,
logger: logger,
platform: macPlatform,
processManager: fakeProcessManager,
);
device = IOSDevice(
deviceId,
artifacts: mockArtifacts,
fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform,
iosDeploy: iosDeploy,
name: 'iPhone 1',
sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64,
);
final bool result = await device.uninstallApp(mockApp); final bool result = await device.uninstallApp(mockApp);
expect(result, false); expect(result, false);
...@@ -294,6 +366,7 @@ void main() { ...@@ -294,6 +366,7 @@ void main() {
'123', '123',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
name: 'iPhone 1', name: 'iPhone 1',
...@@ -420,13 +493,14 @@ void main() { ...@@ -420,13 +493,14 @@ void main() {
Cache.enableLocking(); Cache.enableLocking();
}); });
testUsingContext('disposing device disposes the portForwarder', () async { testWithoutContext('disposing device disposes the portForwarder', () async {
final IOSDevice device = IOSDevice( final IOSDevice device = IOSDevice(
'123', '123',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
platform: macPlatform, platform: macPlatform,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
logger: logger,
name: 'iPhone 1', name: 'iPhone 1',
sdkVersion: '13.3', sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
...@@ -444,6 +518,7 @@ void main() { ...@@ -444,6 +518,7 @@ void main() {
sdkVersion: '13.3', sdkVersion: '13.3',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: mockIosDeploy, iosDeploy: mockIosDeploy,
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
...@@ -479,12 +554,7 @@ void main() { ...@@ -479,12 +554,7 @@ void main() {
expect(launchResult.hasObservatory, isTrue); expect(launchResult.hasObservatory, isTrue);
expect(await device.stopApp(mockApp), isFalse); expect(await device.stopApp(mockApp), isFalse);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Artifacts: () => mockArtifacts,
Cache: () => mockCache,
FileSystem: () => mockFileSystem,
MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery, MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery,
Platform: () => macPlatform,
ProcessManager: () => mockProcessManager,
Usage: () => mockUsage, Usage: () => mockUsage,
}); });
...@@ -493,6 +563,7 @@ void main() { ...@@ -493,6 +563,7 @@ void main() {
'123', '123',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: mockIosDeploy, iosDeploy: mockIosDeploy,
name: 'iPhone 1', name: 'iPhone 1',
...@@ -528,11 +599,8 @@ void main() { ...@@ -528,11 +599,8 @@ void main() {
verify(mockUsage.sendEvent('ios-handshake', 'fallback-success')).called(1); verify(mockUsage.sendEvent('ios-handshake', 'fallback-success')).called(1);
expect(await device.stopApp(mockApp), isFalse); expect(await device.stopApp(mockApp), isFalse);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Artifacts: () => mockArtifacts,
Cache: () => mockCache,
FileSystem: () => mockFileSystem, FileSystem: () => mockFileSystem,
MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery, MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery,
Platform: () => macPlatform,
ProcessManager: () => mockProcessManager, ProcessManager: () => mockProcessManager,
Usage: () => mockUsage, Usage: () => mockUsage,
}); });
...@@ -542,6 +610,7 @@ void main() { ...@@ -542,6 +610,7 @@ void main() {
'123', '123',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: mockIosDeploy, iosDeploy: mockIosDeploy,
name: 'iPhone 1', name: 'iPhone 1',
...@@ -585,11 +654,8 @@ void main() { ...@@ -585,11 +654,8 @@ void main() {
verify(mockUsage.sendEvent('ios-handshake', 'mdns-failure')).called(1); verify(mockUsage.sendEvent('ios-handshake', 'mdns-failure')).called(1);
verify(mockUsage.sendEvent('ios-handshake', 'fallback-failure')).called(1); verify(mockUsage.sendEvent('ios-handshake', 'fallback-failure')).called(1);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Artifacts: () => mockArtifacts,
Cache: () => mockCache,
FileSystem: () => mockFileSystem, FileSystem: () => mockFileSystem,
MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery, MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery,
Platform: () => macPlatform,
ProcessManager: () => mockProcessManager, ProcessManager: () => mockProcessManager,
Usage: () => mockUsage, Usage: () => mockUsage,
}); });
...@@ -601,6 +667,7 @@ void main() { ...@@ -601,6 +667,7 @@ void main() {
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
sdkVersion: '13.3', sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
logger: logger,
platform: mockPlatform, platform: mockPlatform,
artifacts: mockArtifacts, artifacts: mockArtifacts,
iosDeploy: mockIosDeploy, iosDeploy: mockIosDeploy,
...@@ -642,6 +709,7 @@ void main() { ...@@ -642,6 +709,7 @@ void main() {
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
sdkVersion: '13.3', sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
logger: logger,
platform: mockPlatform, platform: mockPlatform,
artifacts: mockArtifacts, artifacts: mockArtifacts,
iosDeploy: mockIosDeploy, iosDeploy: mockIosDeploy,
...@@ -679,6 +747,7 @@ void main() { ...@@ -679,6 +747,7 @@ void main() {
sdkVersion: '13.3', sdkVersion: '13.3',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: mockIosDeploy, iosDeploy: mockIosDeploy,
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
...@@ -737,6 +806,7 @@ void main() { ...@@ -737,6 +806,7 @@ void main() {
sdkVersion: '13.3', sdkVersion: '13.3',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
logger: logger,
platform: macPlatform, platform: macPlatform,
iosDeploy: mockIosDeploy, iosDeploy: mockIosDeploy,
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
...@@ -778,14 +848,10 @@ void main() { ...@@ -778,14 +848,10 @@ void main() {
expect(args, contains('--observatory-port=8181')); expect(args, contains('--observatory-port=8181'));
expect(await device.stopApp(mockApp), isFalse); expect(await device.stopApp(mockApp), isFalse);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Artifacts: () => mockArtifacts,
Cache: () => mockCache, Cache: () => mockCache,
FileSystem: () => mockFileSystem,
MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery, MDnsObservatoryDiscovery: () => mockMDnsObservatoryDiscovery,
Platform: () => macPlatform,
ProcessManager: () => mockProcessManager, ProcessManager: () => mockProcessManager,
Usage: () => mockUsage, Usage: () => mockUsage,
IOSDeploy: () => mockIosDeploy,
}); });
void testNonPrebuilt( void testNonPrebuilt(
...@@ -865,6 +931,7 @@ void main() { ...@@ -865,6 +931,7 @@ void main() {
sdkVersion: '13.3', sdkVersion: '13.3',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: globals.fs, fileSystem: globals.fs,
logger: testLogger,
platform: macPlatform, platform: macPlatform,
iosDeploy: mockIosDeploy, iosDeploy: mockIosDeploy,
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
...@@ -951,11 +1018,12 @@ void main() { ...@@ -951,11 +1018,12 @@ void main() {
MockArtifacts mockArtifacts; MockArtifacts mockArtifacts;
MockCache mockCache; MockCache mockCache;
MockFileSystem mockFileSystem; MockFileSystem mockFileSystem;
MockProcessManager mockProcessManager;
Logger logger; Logger logger;
MockPlatform mockPlatform; MockPlatform mockPlatform;
FullMockProcessManager mockProcessManager;
const String iosDeployPath = '/path/to/ios-deploy'; const String iosDeployPath = '/path/to/ios-deploy';
const String appId = '789'; const String appId = '789';
const String deviceId = '123';
const MapEntry<String, String> libraryEntry = MapEntry<String, String>( const MapEntry<String, String> libraryEntry = MapEntry<String, String>(
'DYLD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH',
'/path/to/libraries', '/path/to/libraries',
...@@ -979,13 +1047,13 @@ void main() { ...@@ -979,13 +1047,13 @@ void main() {
mockPlatform = MockPlatform(); mockPlatform = MockPlatform();
when(mockPlatform.environment).thenReturn(<String, String>{}); when(mockPlatform.environment).thenReturn(<String, String>{});
when(mockPlatform.isMacOS).thenReturn(true); when(mockPlatform.isMacOS).thenReturn(true);
mockProcessManager = FullMockProcessManager();
when( when(
mockArtifacts.getArtifactPath( mockArtifacts.getArtifactPath(
Artifact.iosDeploy, Artifact.iosDeploy,
platform: anyNamed('platform'), platform: anyNamed('platform'),
), ),
).thenReturn(iosDeployPath); ).thenReturn(iosDeployPath);
mockProcessManager = MockProcessManager();
iosDeploy = IOSDeploy( iosDeploy = IOSDeploy(
artifacts: mockArtifacts, artifacts: mockArtifacts,
cache: mockCache, cache: mockCache,
...@@ -1001,82 +1069,83 @@ void main() { ...@@ -1001,82 +1069,83 @@ void main() {
}); });
testWithoutContext('installApp() calls ios-deploy', () async { testWithoutContext('installApp() calls ios-deploy', () async {
final FakeProcessManager fakeProcessManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(command: <String>[
iosDeployPath,
'--id',
deviceId,
'--bundle',
bundlePath,
'--no-wifi',
]),
]);
iosDeploy = IOSDeploy(
artifacts: mockArtifacts,
cache: mockCache,
logger: logger,
platform: mockPlatform,
processManager: fakeProcessManager,
);
when(mockFileSystem.directory(bundlePath)).thenReturn(directory); when(mockFileSystem.directory(bundlePath)).thenReturn(directory);
final IOSDevice device = IOSDevice( final IOSDevice device = IOSDevice(
'123', deviceId,
name: 'iPhone 1', name: 'iPhone 1',
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
sdkVersion: '13.3', sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
logger: logger,
platform: mockPlatform, platform: mockPlatform,
artifacts: mockArtifacts, artifacts: mockArtifacts,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
); );
final List<String> args = <String>[
iosDeployPath,
'--id',
device.id,
'--bundle',
bundlePath,
'--no-wifi',
];
when(mockProcessManager.start(any, workingDirectory: anyNamed('workingDirectory'), environment: anyNamed('environment'))).
thenAnswer((Invocation invocation) {
return Future<Process>.value(createMockProcess());
});
await device.installApp(mockApp); await device.installApp(mockApp);
final List<String> invocationArguments = verify(mockProcessManager.start(
captureAny,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).captured.first as List<String>;
expect(invocationArguments, args);
}); });
testWithoutContext('uninstallApp() calls ios-deploy', () async { testWithoutContext('uninstallApp() calls ios-deploy', () async {
final FakeProcessManager fakeProcessManager = FakeProcessManager.list(<FakeCommand>[
const FakeCommand(command: <String>[
iosDeployPath,
'--id',
deviceId,
'--uninstall_only',
'--bundle_id',
appId,
]),
]);
iosDeploy = IOSDeploy(
artifacts: mockArtifacts,
cache: mockCache,
logger: logger,
platform: mockPlatform,
processManager: fakeProcessManager,
);
final IOSDevice device = IOSDevice( final IOSDevice device = IOSDevice(
'123', deviceId,
name: 'iPhone 1', name: 'iPhone 1',
fileSystem: fs, fileSystem: fs,
sdkVersion: '13.3', sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
logger: logger,
platform: mockPlatform, platform: mockPlatform,
artifacts: mockArtifacts, artifacts: mockArtifacts,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
); );
final List<String> args = <String>[
iosDeployPath,
'--id',
device.id,
'--uninstall_only',
'--bundle_id',
appId,
];
when(mockProcessManager.start(args, workingDirectory: anyNamed('workingDirectory'), environment: anyNamed('environment'))).
thenAnswer((Invocation invocation) {
return Future<Process>.value(createMockProcess());
});
await device.uninstallApp(mockApp); await device.uninstallApp(mockApp);
final List<String> invocationArguments = verify(mockProcessManager.start(
captureAny,
workingDirectory: anyNamed('workingDirectory'),
environment: anyNamed('environment'),
)).captured.first as List<String>;
expect(invocationArguments, args);
}); });
}); });
}); });
group('getAttachedDevices', () { group('pollingGetDevices', () {
MockXcdevice mockXcdevice; MockXcdevice mockXcdevice;
MockArtifacts mockArtifacts; MockArtifacts mockArtifacts;
MockCache mockCache; MockCache mockCache;
MockFileSystem mockFileSystem; MockFileSystem mockFileSystem;
FakeProcessManager fakeProcessManager;
Logger logger; Logger logger;
FullMockProcessManager mockProcessManager;
IOSDeploy iosDeploy; IOSDeploy iosDeploy;
IOSWorkflow mockIosWorkflow;
setUp(() { setUp(() {
mockXcdevice = MockXcdevice(); mockXcdevice = MockXcdevice();
...@@ -1084,28 +1153,39 @@ void main() { ...@@ -1084,28 +1153,39 @@ void main() {
mockCache = MockCache(); mockCache = MockCache();
logger = BufferLogger.test(); logger = BufferLogger.test();
mockFileSystem = MockFileSystem(); mockFileSystem = MockFileSystem();
mockProcessManager = FullMockProcessManager(); mockIosWorkflow = MockIOSWorkflow();
fakeProcessManager = FakeProcessManager.any();
iosDeploy = IOSDeploy( iosDeploy = IOSDeploy(
artifacts: mockArtifacts, artifacts: mockArtifacts,
cache: mockCache, cache: mockCache,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
processManager: mockProcessManager, processManager: fakeProcessManager,
); );
}); });
final List<Platform> unsupportedPlatforms = <Platform>[linuxPlatform, windowsPlatform]; final List<Platform> unsupportedPlatforms = <Platform>[linuxPlatform, windowsPlatform];
for (final Platform unsupportedPlatform in unsupportedPlatforms) { for (final Platform unsupportedPlatform in unsupportedPlatforms) {
testWithoutContext('throws Unsupported Operation exception on ${unsupportedPlatform.operatingSystem}', () async { testWithoutContext('throws Unsupported Operation exception on ${unsupportedPlatform.operatingSystem}', () async {
final IOSDevices iosDevices = IOSDevices(
platform: unsupportedPlatform,
xcdevice: mockXcdevice,
iosWorkflow: mockIosWorkflow,
);
when(mockXcdevice.isInstalled).thenReturn(false); when(mockXcdevice.isInstalled).thenReturn(false);
expect( expect(
() async { await IOSDevice.getAttachedDevices(unsupportedPlatform, mockXcdevice); }, () async { await iosDevices.pollingGetDevices(); },
throwsA(isA<UnsupportedError>()), throwsA(isA<UnsupportedError>()),
); );
}); });
} }
testWithoutContext('returns attached devices', () async { testWithoutContext('returns attached devices', () async {
final IOSDevices iosDevices = IOSDevices(
platform: macPlatform,
xcdevice: mockXcdevice,
iosWorkflow: mockIosWorkflow,
);
when(mockXcdevice.isInstalled).thenReturn(true); when(mockXcdevice.isInstalled).thenReturn(true);
final IOSDevice device = IOSDevice( final IOSDevice device = IOSDevice(
...@@ -1115,13 +1195,14 @@ void main() { ...@@ -1115,13 +1195,14 @@ void main() {
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
artifacts: mockArtifacts, artifacts: mockArtifacts,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
logger: logger,
platform: macPlatform, platform: macPlatform,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
); );
when(mockXcdevice.getAvailableTetheredIOSDevices()) when(mockXcdevice.getAvailableTetheredIOSDevices())
.thenAnswer((Invocation invocation) => Future<List<IOSDevice>>.value(<IOSDevice>[device])); .thenAnswer((Invocation invocation) => Future<List<IOSDevice>>.value(<IOSDevice>[device]));
final List<IOSDevice> devices = await IOSDevice.getAttachedDevices(macPlatform, mockXcdevice); final List<Device> devices = await iosDevices.pollingGetDevices();
expect(devices, hasLength(1)); expect(devices, hasLength(1));
expect(identical(devices.first, device), isTrue); expect(identical(devices.first, device), isTrue);
}); });
...@@ -1129,39 +1210,49 @@ void main() { ...@@ -1129,39 +1210,49 @@ void main() {
group('getDiagnostics', () { group('getDiagnostics', () {
MockXcdevice mockXcdevice; MockXcdevice mockXcdevice;
IOSWorkflow mockIosWorkflow;
setUp(() { setUp(() {
mockXcdevice = MockXcdevice(); mockXcdevice = MockXcdevice();
mockIosWorkflow = MockIOSWorkflow();
}); });
final List<Platform> unsupportedPlatforms = <Platform>[linuxPlatform, windowsPlatform]; final List<Platform> unsupportedPlatforms = <Platform>[linuxPlatform, windowsPlatform];
for (final Platform unsupportedPlatform in unsupportedPlatforms) { for (final Platform unsupportedPlatform in unsupportedPlatforms) {
testWithoutContext('throws returns platform diagnostic exception on ${unsupportedPlatform.operatingSystem}', () async { testWithoutContext('throws returns platform diagnostic exception on ${unsupportedPlatform.operatingSystem}', () async {
final IOSDevices iosDevices = IOSDevices(
platform: unsupportedPlatform,
xcdevice: mockXcdevice,
iosWorkflow: mockIosWorkflow,
);
when(mockXcdevice.isInstalled).thenReturn(false); when(mockXcdevice.isInstalled).thenReturn(false);
expect((await IOSDevice.getDiagnostics(unsupportedPlatform, mockXcdevice)).first, 'Control of iOS devices or simulators only supported on macOS.'); expect((await iosDevices.getDiagnostics()).first, 'Control of iOS devices or simulators only supported on macOS.');
}); });
} }
testUsingContext('returns diagnostics', () async { testWithoutContext('returns diagnostics', () async {
final IOSDevices iosDevices = IOSDevices(
platform: macPlatform,
xcdevice: mockXcdevice,
iosWorkflow: mockIosWorkflow,
);
when(mockXcdevice.isInstalled).thenReturn(true); when(mockXcdevice.isInstalled).thenReturn(true);
when(mockXcdevice.getDiagnostics()) when(mockXcdevice.getDiagnostics())
.thenAnswer((Invocation invocation) => Future<List<String>>.value(<String>['Generic pairing error'])); .thenAnswer((Invocation invocation) => Future<List<String>>.value(<String>['Generic pairing error']));
final List<String> diagnostics = await IOSDevice.getDiagnostics(macPlatform, mockXcdevice); final List<String> diagnostics = await iosDevices.getDiagnostics();
expect(diagnostics, hasLength(1)); expect(diagnostics, hasLength(1));
expect(diagnostics.first, 'Generic pairing error'); expect(diagnostics.first, 'Generic pairing error');
}, overrides: <Type, Generator>{
Platform: () => macPlatform,
}); });
}); });
group('decodeSyslog', () { group('decodeSyslog', () {
test('decodes a syslog-encoded line', () { testWithoutContext('decodes a syslog-encoded line', () {
final String decoded = decodeSyslog(r'I \M-b\M^]\M-$\M-o\M-8\M^O syslog \M-B\M-/\134_(\M-c\M^C\M^D)_/\M-B\M-/ \M-l\M^F\240!'); final String decoded = decodeSyslog(r'I \M-b\M^]\M-$\M-o\M-8\M^O syslog \M-B\M-/\134_(\M-c\M^C\M^D)_/\M-B\M-/ \M-l\M^F\240!');
expect(decoded, r'I ❤️ syslog ¯\_(ツ)_/¯ 솠!'); expect(decoded, r'I ❤️ syslog ¯\_(ツ)_/¯ 솠!');
}); });
test('passes through un-decodeable lines as-is', () { testWithoutContext('passes through un-decodeable lines as-is', () {
final String decoded = decodeSyslog(r'I \M-b\M^O syslog!'); final String decoded = decodeSyslog(r'I \M-b\M^O syslog!');
expect(decoded, r'I \M-b\M^O syslog!'); expect(decoded, r'I \M-b\M^O syslog!');
}); });
...@@ -1173,8 +1264,8 @@ void main() { ...@@ -1173,8 +1264,8 @@ void main() {
MockArtifacts mockArtifacts; MockArtifacts mockArtifacts;
MockCache mockCache; MockCache mockCache;
MockFileSystem mockFileSystem; MockFileSystem mockFileSystem;
FakeProcessManager fakeProcessManager;
Logger logger; Logger logger;
FullMockProcessManager mockProcessManager;
IOSDeploy iosDeploy; IOSDeploy iosDeploy;
setUp(() { setUp(() {
...@@ -1184,13 +1275,13 @@ void main() { ...@@ -1184,13 +1275,13 @@ void main() {
mockCache = MockCache(); mockCache = MockCache();
logger = BufferLogger.test(); logger = BufferLogger.test();
mockFileSystem = MockFileSystem(); mockFileSystem = MockFileSystem();
mockProcessManager = FullMockProcessManager(); fakeProcessManager = FakeProcessManager.any();
iosDeploy = IOSDeploy( iosDeploy = IOSDeploy(
artifacts: mockArtifacts, artifacts: mockArtifacts,
cache: mockCache, cache: mockCache,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
processManager: mockProcessManager, processManager: fakeProcessManager,
); );
}); });
...@@ -1215,6 +1306,7 @@ Runner(UIKit)[297] <Notice>: E is for enpitsu" ...@@ -1215,6 +1306,7 @@ Runner(UIKit)[297] <Notice>: E is for enpitsu"
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
artifacts: mockArtifacts, artifacts: mockArtifacts,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
logger: logger,
platform: macPlatform, platform: macPlatform,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
); );
...@@ -1226,7 +1318,6 @@ Runner(UIKit)[297] <Notice>: E is for enpitsu" ...@@ -1226,7 +1318,6 @@ Runner(UIKit)[297] <Notice>: E is for enpitsu"
expect(lines, <String>['A is for ari', 'I is for ichigo']); expect(lines, <String>['A is for ari', 'I is for ichigo']);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
IMobileDevice: () => mockIMobileDevice, IMobileDevice: () => mockIMobileDevice,
Platform: () => macPlatform,
}); });
testUsingContext('includes multi-line Flutter logs in the output', () async { testUsingContext('includes multi-line Flutter logs in the output', () async {
...@@ -1250,6 +1341,7 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt ...@@ -1250,6 +1341,7 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
artifacts: mockArtifacts, artifacts: mockArtifacts,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
logger: logger,
platform: macPlatform, platform: macPlatform,
fileSystem: mockFileSystem, fileSystem: mockFileSystem,
); );
...@@ -1267,7 +1359,6 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt ...@@ -1267,7 +1359,6 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
expect(device.category, Category.mobile); expect(device.category, Category.mobile);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
IMobileDevice: () => mockIMobileDevice, IMobileDevice: () => mockIMobileDevice,
Platform: () => macPlatform,
}); });
}); });
...@@ -1276,21 +1367,25 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt ...@@ -1276,21 +1367,25 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
MockCache mockCache; MockCache mockCache;
Logger logger; Logger logger;
IOSDeploy iosDeploy; IOSDeploy iosDeploy;
MemoryFileSystem fileSystem;
FakeProcessManager fakeProcessManager;
setUp(() { setUp(() {
fileSystem = MemoryFileSystem();
mockArtifacts = MockArtifacts(); mockArtifacts = MockArtifacts();
mockCache = MockCache(); mockCache = MockCache();
fakeProcessManager = FakeProcessManager.any();
iosDeploy = IOSDeploy( iosDeploy = IOSDeploy(
artifacts: mockArtifacts, artifacts: mockArtifacts,
cache: mockCache, cache: mockCache,
logger: logger, logger: logger,
platform: macPlatform, platform: macPlatform,
processManager: FakeProcessManager.any(), processManager: fakeProcessManager,
); );
}); });
testUsingContext('is true on module project', () async { testUsingContext('is true on module project', () async {
globals.fs.file('pubspec.yaml') fileSystem.file('pubspec.yaml')
..createSync() ..createSync()
..writeAsStringSync(r''' ..writeAsStringSync(r'''
name: example name: example
...@@ -1298,59 +1393,60 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt ...@@ -1298,59 +1393,60 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
flutter: flutter:
module: {} module: {}
'''); ''');
globals.fs.file('.packages').createSync(); fileSystem.file('.packages').createSync();
final FlutterProject flutterProject = FlutterProject.current(); final FlutterProject flutterProject = FlutterProject.current();
final IOSDevice device = IOSDevice( final IOSDevice device = IOSDevice(
'test', 'test',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: globals.fs, fileSystem: fileSystem,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
platform: globals.platform, logger: logger,
platform: macPlatform,
name: 'iPhone 1', name: 'iPhone 1',
sdkVersion: '13.3', sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64 cpuArchitecture: DarwinArch.arm64
); );
expect(device.isSupportedForProject(flutterProject), true); expect(device.isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(), FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => fakeProcessManager,
Platform: () => macPlatform,
}); });
testUsingContext('is true with editable host app', () async { testUsingContext('is true with editable host app', () async {
globals.fs.file('pubspec.yaml').createSync(); fileSystem.file('pubspec.yaml').createSync();
globals.fs.file('.packages').createSync(); fileSystem.file('.packages').createSync();
globals.fs.directory('ios').createSync(); fileSystem.directory('ios').createSync();
final FlutterProject flutterProject = FlutterProject.current(); final FlutterProject flutterProject = FlutterProject.current();
final IOSDevice device = IOSDevice( final IOSDevice device = IOSDevice(
'test', 'test',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: globals.fs, fileSystem: fileSystem,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
platform: globals.platform, logger: logger,
platform: macPlatform,
name: 'iPhone 1', name: 'iPhone 1',
sdkVersion: '13.3', sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
); );
expect(device.isSupportedForProject(flutterProject), true); expect(device.isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(), FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => fakeProcessManager,
Platform: () => macPlatform,
}); });
testUsingContext('is false with no host app and no module', () async { testUsingContext('is false with no host app and no module', () async {
globals.fs.file('pubspec.yaml').createSync(); fileSystem.file('pubspec.yaml').createSync();
globals.fs.file('.packages').createSync(); fileSystem.file('.packages').createSync();
final FlutterProject flutterProject = FlutterProject.current(); final FlutterProject flutterProject = FlutterProject.current();
final IOSDevice device = IOSDevice( final IOSDevice device = IOSDevice(
'test', 'test',
artifacts: mockArtifacts, artifacts: mockArtifacts,
fileSystem: globals.fs, fileSystem: fileSystem,
iosDeploy: iosDeploy, iosDeploy: iosDeploy,
platform: globals.platform, logger: logger,
platform: macPlatform,
name: 'iPhone 1', name: 'iPhone 1',
sdkVersion: '13.3', sdkVersion: '13.3',
cpuArchitecture: DarwinArch.arm64, cpuArchitecture: DarwinArch.arm64,
...@@ -1358,8 +1454,7 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt ...@@ -1358,8 +1454,7 @@ Runner(libsystem_asl.dylib)[297] <Notice>: libMobileGestalt
expect(device.isSupportedForProject(flutterProject), false); expect(device.isSupportedForProject(flutterProject), false);
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(), FileSystem: () => MemoryFileSystem(),
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => fakeProcessManager,
Platform: () => macPlatform,
}); });
}); });
} }
...@@ -1397,6 +1492,7 @@ class FakeIosDoctorProvider implements DoctorValidatorsProvider { ...@@ -1397,6 +1492,7 @@ class FakeIosDoctorProvider implements DoctorValidatorsProvider {
} }
} }
class MockIOSApp extends Mock implements IOSApp {} class MockIOSApp extends Mock implements IOSApp {}
class MockApplicationPackage extends Mock implements ApplicationPackage {} class MockApplicationPackage extends Mock implements ApplicationPackage {}
class MockArtifacts extends Mock implements Artifacts {} class MockArtifacts extends Mock implements Artifacts {}
...@@ -1408,12 +1504,12 @@ class MockFileSystem extends Mock implements FileSystem {} ...@@ -1408,12 +1504,12 @@ class MockFileSystem extends Mock implements FileSystem {}
class MockForwardedPort extends Mock implements ForwardedPort {} class MockForwardedPort extends Mock implements ForwardedPort {}
class MockIMobileDevice extends Mock implements IMobileDevice {} class MockIMobileDevice extends Mock implements IMobileDevice {}
class MockIOSDeploy extends Mock implements IOSDeploy {} class MockIOSDeploy extends Mock implements IOSDeploy {}
class MockIOSWorkflow extends Mock implements IOSWorkflow {}
class MockMDnsObservatoryDiscovery extends Mock implements MDnsObservatoryDiscovery {} class MockMDnsObservatoryDiscovery extends Mock implements MDnsObservatoryDiscovery {}
class MockMDnsObservatoryDiscoveryResult extends Mock implements MDnsObservatoryDiscoveryResult {} class MockMDnsObservatoryDiscoveryResult extends Mock implements MDnsObservatoryDiscoveryResult {}
class MockPlatform extends Mock implements Platform {} class MockPlatform extends Mock implements Platform {}
class MockPortForwarder extends Mock implements DevicePortForwarder {} class MockPortForwarder extends Mock implements DevicePortForwarder {}
// src/mocks.dart imports `MockProcessManager` which implements some methods, this is a full mock class MockStatus extends Mock implements Status {}
class FullMockProcessManager extends Mock implements ProcessManager {}
class MockUsage extends Mock implements Usage {} class MockUsage extends Mock implements Usage {}
class MockXcdevice extends Mock implements XCDevice {} class MockXcdevice extends Mock implements XCDevice {}
class MockXcode extends Mock implements Xcode {} class MockXcode extends Mock implements Xcode {}
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