Flutter `emulator launch` crash running in dart-2-mode (#19454) * Only printError on our simple messages Any other type is a real error that should be a normal crash (to get a proper error log). See #19453. * Add toList() to convert Iterable<String> -> List<String> This code previously throw in Dart-2 mode. Fixes #19453. * Move getSimulatorPath into Xcode * Add a test that we tried to launch the simulator * Remove unused import
diff --git a/packages/flutter_tools/lib/src/commands/emulators.dart b/packages/flutter_tools/lib/src/commands/emulators.dart index 0904bc4..e1ab0dd 100644 --- a/packages/flutter_tools/lib/src/commands/emulators.dart +++ b/packages/flutter_tools/lib/src/commands/emulators.dart
@@ -72,7 +72,11 @@ await emulators.first.launch(); } catch (e) { - printError(e); + if (e is String) { + printError(e); + } else { + rethrow; + } } } }
diff --git a/packages/flutter_tools/lib/src/ios/ios_emulators.dart b/packages/flutter_tools/lib/src/ios/ios_emulators.dart index 0916a3c..f9c3a57 100644 --- a/packages/flutter_tools/lib/src/ios/ios_emulators.dart +++ b/packages/flutter_tools/lib/src/ios/ios_emulators.dart
@@ -4,7 +4,6 @@ import 'dart:async'; -import '../base/file_system.dart'; import '../base/platform.dart'; import '../base/process.dart'; import '../emulator.dart'; @@ -40,7 +39,8 @@ Future<bool> launchSimulator(List<String> additionalArgs) async { final List<String> args = <String>['open'] .followedBy(additionalArgs) - .followedBy(<String>['-a', getSimulatorPath()]); + .followedBy(<String>['-a', xcode.getSimulatorPath()]) + .toList(); final RunResult launchResult = await runAsync(args); if (launchResult.exitCode != 0) { @@ -62,22 +62,10 @@ /// Return the list of iOS Simulators (there can only be zero or one). List<IOSEmulator> getEmulators() { - final String simulatorPath = getSimulatorPath(); + final String simulatorPath = xcode.getSimulatorPath(); if (simulatorPath == null) { return <IOSEmulator>[]; } return <IOSEmulator>[new IOSEmulator('apple_ios_simulator')]; } - -String getSimulatorPath() { - if (xcode.xcodeSelectPath == null) - return null; - final List<String> searchPaths = <String>[ - fs.path.join(xcode.xcodeSelectPath, 'Applications', 'Simulator.app'), - ]; - return searchPaths.where((String p) => p != null).firstWhere( - (String p) => fs.directory(p).existsSync(), - orElse: () => null, - ); -}
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart index d5a2c6b..85d4d87 100644 --- a/packages/flutter_tools/lib/src/ios/mac.dart +++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -167,6 +167,18 @@ Future<RunResult> clang(List<String> args) { return runCheckedAsync(<String>['xcrun', 'clang']..addAll(args)); } + + String getSimulatorPath() { + if (xcodeSelectPath == null) + return null; + final List<String> searchPaths = <String>[ + fs.path.join(xcodeSelectPath, 'Applications', 'Simulator.app'), + ]; + return searchPaths.where((String p) => p != null).firstWhere( + (String p) => fs.directory(p).existsSync(), + orElse: () => null, + ); + } } Future<XcodeBuildResult> buildXcodeProject({
diff --git a/packages/flutter_tools/test/emulator_test.dart b/packages/flutter_tools/test/emulator_test.dart index 9aad551..4286019 100644 --- a/packages/flutter_tools/test/emulator_test.dart +++ b/packages/flutter_tools/test/emulator_test.dart
@@ -10,6 +10,8 @@ import 'package:flutter_tools/src/base/config.dart'; import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/emulator.dart'; +import 'package:flutter_tools/src/ios/ios_emulators.dart'; +import 'package:flutter_tools/src/ios/mac.dart'; import 'package:mockito/mockito.dart'; import 'package:process/process.dart'; import 'package:test/test.dart'; @@ -21,11 +23,13 @@ MockProcessManager mockProcessManager; MockConfig mockConfig; MockAndroidSdk mockSdk; + MockXcode mockXcode; setUp(() { mockProcessManager = new MockProcessManager(); mockConfig = new MockConfig(); mockSdk = new MockAndroidSdk(); + mockXcode = new MockXcode(); when(mockSdk.avdManagerPath).thenReturn('avdmanager'); when(mockSdk.emulatorPath).thenReturn('emulator'); @@ -121,6 +125,30 @@ AndroidSdk: () => mockSdk, }); }); + + group('ios_emulators', () { + bool didAttemptToRunSimulator = false; + setUp(() { + when(mockXcode.xcodeSelectPath).thenReturn('/fake/Xcode.app/Contents/Developer'); + when(mockXcode.getSimulatorPath()).thenAnswer((_) => '/fake/simulator.app'); + when(mockProcessManager.run(any)).thenAnswer((Invocation invocation) async { + final List<String> args = invocation.positionalArguments[0]; + if (args.length >= 3 && args[0] == 'open' && args[1] == '-a' && args[2] == '/fake/simulator.app') { + didAttemptToRunSimulator = true; + } + return new ProcessResult(101, 0, '', ''); + }); + }); + testUsingContext('runs correct launch commands', () async { + final Emulator emulator = new IOSEmulator('ios'); + await emulator.launch(); + expect(didAttemptToRunSimulator, equals(true)); + }, overrides: <Type, Generator>{ + ProcessManager: () => mockProcessManager, + Config: () => mockConfig, + Xcode: () => mockXcode, + }); + }); } class TestEmulatorManager extends EmulatorManager { @@ -230,3 +258,5 @@ throw new ProcessException('emulator', args); } } + +class MockXcode extends Mock implements Xcode {}