decouple `flutter drive` from `flutter start`
flutter start's method of finding devices to run the app on is not suitable for flutter drive.
This commit also refactors several tool services to allow mocking in unit tests.
diff --git a/packages/flutter_tools/lib/src/ios/devices.dart b/packages/flutter_tools/lib/src/ios/devices.dart
index cf1a55a..e03169b 100644
--- a/packages/flutter_tools/lib/src/ios/devices.dart
+++ b/packages/flutter_tools/lib/src/ios/devices.dart
@@ -62,6 +62,8 @@
final String name;
+ bool get isLocalEmulator => false;
+
bool get supportsStartPaused => false;
static List<IOSDevice> getAttachedDevices([IOSDevice mockIOS]) {
diff --git a/packages/flutter_tools/lib/src/ios/simulators.dart b/packages/flutter_tools/lib/src/ios/simulators.dart
index b157a25..1209942 100644
--- a/packages/flutter_tools/lib/src/ios/simulators.dart
+++ b/packages/flutter_tools/lib/src/ios/simulators.dart
@@ -10,6 +10,7 @@
import '../application_package.dart';
import '../base/common.dart';
+import '../base/context.dart';
import '../base/process.dart';
import '../build_configuration.dart';
import '../device.dart';
@@ -26,12 +27,29 @@
IOSSimulators() : super('IOSSimulators');
bool get supportsPlatform => Platform.isMacOS;
- List<Device> pollingGetDevices() => IOSSimulator.getAttachedDevices();
+ List<Device> pollingGetDevices() => IOSSimulatorUtils.instance.getAttachedDevices();
+}
+
+class IOSSimulatorUtils {
+ /// Returns [IOSSimulatorUtils] active in the current app context (i.e. zone).
+ static IOSSimulatorUtils get instance => context[IOSSimulatorUtils] ?? (context[IOSSimulatorUtils] = new IOSSimulatorUtils());
+
+ List<IOSSimulator> getAttachedDevices() {
+ if (!xcode.isInstalledAndMeetsVersionCheck)
+ return <IOSSimulator>[];
+
+ return SimControl.instance.getConnectedDevices().map((SimDevice device) {
+ return new IOSSimulator(device.udid, name: device.name);
+ }).toList();
+ }
}
/// A wrapper around the `simctl` command line tool.
class SimControl {
- static Future<bool> boot({String deviceId}) async {
+ /// Returns [SimControl] active in the current app context (i.e. zone).
+ static SimControl get instance => context[SimControl] ?? (context[SimControl] = new SimControl());
+
+ Future<bool> boot({String deviceId}) async {
if (_isAnyConnected())
return true;
@@ -65,7 +83,7 @@
}
/// Returns a list of all available devices, both potential and connected.
- static List<SimDevice> getDevices() {
+ List<SimDevice> getDevices() {
// {
// "devices" : {
// "com.apple.CoreSimulator.SimRuntime.iOS-8-2" : [
@@ -102,18 +120,18 @@
}
/// Returns all the connected simulator devices.
- static List<SimDevice> getConnectedDevices() {
+ List<SimDevice> getConnectedDevices() {
return getDevices().where((SimDevice device) => device.isBooted).toList();
}
- static StreamController<List<SimDevice>> _trackDevicesControler;
+ StreamController<List<SimDevice>> _trackDevicesControler;
/// Listens to changes in the set of connected devices. The implementation
/// currently uses polling. Callers should be careful to call cancel() on any
/// stream subscription when finished.
///
/// TODO(devoncarew): We could investigate using the usbmuxd protocol directly.
- static Stream<List<SimDevice>> trackDevices() {
+ Stream<List<SimDevice>> trackDevices() {
if (_trackDevicesControler == null) {
Timer timer;
Set<String> deviceIds = new Set<String>();
@@ -138,7 +156,7 @@
}
/// Update the cached set of device IDs and return whether there were any changes.
- static bool _updateDeviceIds(List<SimDevice> devices, Set<String> deviceIds) {
+ bool _updateDeviceIds(List<SimDevice> devices, Set<String> deviceIds) {
Set<String> newIds = new Set<String>.from(devices.map((SimDevice device) => device.udid));
bool changed = false;
@@ -159,13 +177,13 @@
return changed;
}
- static bool _isAnyConnected() => getConnectedDevices().isNotEmpty;
+ bool _isAnyConnected() => getConnectedDevices().isNotEmpty;
- static void install(String deviceId, String appPath) {
+ void install(String deviceId, String appPath) {
runCheckedSync([_xcrunPath, 'simctl', 'install', deviceId, appPath]);
}
- static void launch(String deviceId, String appIdentifier, [List<String> launchArgs]) {
+ void launch(String deviceId, String appIdentifier, [List<String> launchArgs]) {
List<String> args = [_xcrunPath, 'simctl', 'launch', deviceId, appIdentifier];
if (launchArgs != null)
args.addAll(launchArgs);
@@ -190,17 +208,10 @@
class IOSSimulator extends Device {
IOSSimulator(String id, { this.name }) : super(id);
- static List<IOSSimulator> getAttachedDevices() {
- if (!xcode.isInstalledAndMeetsVersionCheck)
- return <IOSSimulator>[];
-
- return SimControl.getConnectedDevices().map((SimDevice device) {
- return new IOSSimulator(device.udid, name: device.name);
- }).toList();
- }
-
final String name;
+ bool get isLocalEmulator => true;
+
String get xcrunPath => path.join('/usr', 'bin', 'xcrun');
String _getSimulatorPath() {
@@ -220,7 +231,7 @@
return false;
try {
- SimControl.install(id, app.localPath);
+ SimControl.instance.install(id, app.localPath);
return true;
} catch (e) {
return false;
@@ -231,7 +242,7 @@
bool isConnected() {
if (!Platform.isMacOS)
return false;
- return SimControl.getConnectedDevices().any((SimDevice device) => device.udid == id);
+ return SimControl.instance.getConnectedDevices().any((SimDevice device) => device.udid == id);
}
@override
@@ -333,7 +344,7 @@
}
// Step 3: Install the updated bundle to the simulator.
- SimControl.install(id, path.absolute(bundle.path));
+ SimControl.instance.install(id, path.absolute(bundle.path));
// Step 4: Prepare launch arguments.
List<String> args = <String>[];
@@ -349,7 +360,7 @@
// Step 5: Launch the updated application in the simulator.
try {
- SimControl.launch(id, app.id, args);
+ SimControl.instance.launch(id, app.id, args);
} catch (error) {
printError('$error');
return false;