Unverified Commit 6804cef5 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] throw exception instead of string from startApp (#52365)

When attempting to start an emulator in profile mode, ensure the daemon can exit gracefully
parent 4049889d
...@@ -459,7 +459,7 @@ class AppDomain extends Domain { ...@@ -459,7 +459,7 @@ class AppDomain extends Domain {
String isolateFilter, String isolateFilter,
}) async { }) async {
if (await device.isLocalEmulator && !options.buildInfo.supportsEmulator) { if (await device.isLocalEmulator && !options.buildInfo.supportsEmulator) {
throw '${toTitleCase(options.buildInfo.friendlyModeName)} mode is not supported for emulators.'; throw Exception('${toTitleCase(options.buildInfo.friendlyModeName)} mode is not supported for emulators.');
} }
// We change the current working directory for the duration of the `start` command. // We change the current working directory for the duration of the `start` command.
final Directory cwd = globals.fs.currentDirectory; final Directory cwd = globals.fs.currentDirectory;
......
...@@ -12,6 +12,7 @@ import 'package:flutter_tools/src/artifacts.dart'; ...@@ -12,6 +12,7 @@ import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/context.dart'; import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/user_messages.dart'; import 'package:flutter_tools/src/base/user_messages.dart';
import 'package:flutter_tools/src/base/net.dart'; import 'package:flutter_tools/src/base/net.dart';
...@@ -114,6 +115,38 @@ void main() { ...@@ -114,6 +115,38 @@ void main() {
ProcessManager: () => FakeProcessManager.any(), ProcessManager: () => FakeProcessManager.any(),
}); });
testUsingContext('Fails with toolExit run in profile mode on emulator with machine flag', () async {
globals.fs.file('pubspec.yaml').createSync();
globals.fs.file('.packages').writeAsStringSync('\n');
globals.fs.file('lib/main.dart').createSync(recursive: true);
final FakeDevice device = FakeDevice(isLocalEmulator: true);
when(deviceManager.getAllConnectedDevices()).thenAnswer((Invocation invocation) async {
return <Device>[device];
});
when(deviceManager.getDevices()).thenAnswer((Invocation invocation) async {
return <Device>[device];
});
when(deviceManager.findTargetDevices(any)).thenAnswer((Invocation invocation) async {
return <Device>[device];
});
when(deviceManager.hasSpecifiedAllDevices).thenReturn(false);
when(deviceManager.deviceDiscoverers).thenReturn(<DeviceDiscovery>[]);
final RunCommand command = RunCommand();
applyMocksToCommand(command);
await expectLater(createTestCommandRunner(command).run(<String>[
'run',
'--no-pub',
'--machine',
'--profile',
]), throwsToolExit(message: 'not supported for emulators'));
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => MockDeviceManager(),
Stdio: () => MockStdio(),
});
testUsingContext('Walks upward looking for a pubspec.yaml and exits if missing', () async { testUsingContext('Walks upward looking for a pubspec.yaml and exits if missing', () async {
globals.fs.currentDirectory = globals.fs.directory(globals.fs.path.join('a', 'b', 'c')) globals.fs.currentDirectory = globals.fs.directory(globals.fs.path.join('a', 'b', 'c'))
..createSync(recursive: true); ..createSync(recursive: true);
...@@ -572,15 +605,14 @@ class TestRunCommand extends RunCommand { ...@@ -572,15 +605,14 @@ class TestRunCommand extends RunCommand {
} }
} }
class MockStableFlutterVersion extends MockFlutterVersion {
@override
bool get isMaster => false;
}
class FakeDevice extends Fake implements Device { class FakeDevice extends Fake implements Device {
FakeDevice({bool isLocalEmulator = false})
: _isLocalEmulator = isLocalEmulator;
static const int kSuccess = 1; static const int kSuccess = 1;
static const int kFailure = -1; static const int kFailure = -1;
TargetPlatform _targetPlatform = TargetPlatform.ios; TargetPlatform _targetPlatform = TargetPlatform.ios;
final bool _isLocalEmulator;
@override @override
String get id => 'fake_device'; String get id => 'fake_device';
...@@ -588,7 +620,7 @@ class FakeDevice extends Fake implements Device { ...@@ -588,7 +620,7 @@ class FakeDevice extends Fake implements Device {
void _throwToolExit(int code) => throwToolExit(null, exitCode: code); void _throwToolExit(int code) => throwToolExit(null, exitCode: code);
@override @override
Future<bool> get isLocalEmulator => Future<bool>.value(false); Future<bool> get isLocalEmulator => Future<bool>.value(_isLocalEmulator);
@override @override
bool get supportsHotReload => false; bool get supportsHotReload => false;
......
...@@ -101,7 +101,7 @@ Matcher throwsToolExit({ int exitCode, Pattern message }) { ...@@ -101,7 +101,7 @@ Matcher throwsToolExit({ int exitCode, Pattern message }) {
matcher = allOf(matcher, (ToolExit e) => e.exitCode == exitCode); matcher = allOf(matcher, (ToolExit e) => e.exitCode == exitCode);
} }
if (message != null) { if (message != null) {
matcher = allOf(matcher, (ToolExit e) => e.message.contains(message)); matcher = allOf(matcher, (ToolExit e) => e.message?.contains(message) ?? false);
} }
return throwsA(matcher); return throwsA(matcher);
} }
......
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