[flutter_tools] always use device.stopApp (#83803)

This commit is contained in:
Jonah Williams 2021-06-02 17:34:02 -07:00 committed by GitHub
parent 4d289ca634
commit f666f93dbb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 7 additions and 172 deletions

View file

@ -344,49 +344,10 @@ class FlutterDevice {
Future<void> exitApps({
@visibleForTesting Duration timeoutDelay = const Duration(seconds: 10),
}) async {
if (!device.supportsFlutterExit || vmService == null) {
return device.stopApp(package, userIdentifier: userIdentifier);
}
final List<FlutterView> views = await vmService.getFlutterViews();
if (views == null || views.isEmpty) {
return device.stopApp(package, userIdentifier: userIdentifier);
}
// If any of the flutter views are paused, we might not be able to
// cleanly exit since the service extension may not have been registered.
for (final FlutterView flutterView in views) {
final vm_service.Isolate isolate = await vmService
.getIsolateOrNull(flutterView.uiIsolate.id);
if (isolate == null) {
continue;
}
if (isPauseEvent(isolate.pauseEvent.kind)) {
return device.stopApp(package, userIdentifier: userIdentifier);
}
}
for (final FlutterView view in views) {
if (view != null && view.uiIsolate != null) {
// If successful, there will be no response from flutterExit. If the exit
// method is not registered, this will complete with `false`.
unawaited(vmService.flutterExit(
isolateId: view.uiIsolate.id,
).then((bool exited) async {
// If exiting the app failed, fall back to stopApp
if (!exited) {
await device.stopApp(package, userIdentifier: userIdentifier);
}
}));
}
}
return vmService.service.onDone
.catchError((dynamic error, StackTrace stackTrace) {
globals.logger.printError(
'unhandled error waiting for vm service exit:\n $error',
stackTrace: stackTrace,
);
})
.timeout(timeoutDelay, onTimeout: () {
return device.stopApp(package, userIdentifier: userIdentifier);
});
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/83127
// When updating `flutter attach` to support running without a device,
// this will need to be changed to fall back to io exit.
return device.stopApp(package, userIdentifier: userIdentifier);
}
Future<Uri> setupDevFS(

View file

@ -1655,71 +1655,6 @@ void main() {
expect(await result, 0);
}));
testUsingContext('FlutterDevice will not exit a paused isolate', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
FakeVmServiceRequest(
method: '_flutter.listViews',
jsonResponse: <String, Object>{
'views': <Object>[
fakeFlutterView.toJson(),
],
},
),
FakeVmServiceRequest(
method: 'getIsolate',
args: <String, Object>{
'isolateId': fakeUnpausedIsolate.id,
},
jsonResponse: fakePausedIsolate.toJson(),
),
]);
final TestFlutterDevice flutterDevice = TestFlutterDevice(
mockDevice,
);
flutterDevice.vmService = fakeVmServiceHost.vmService;
await flutterDevice.exitApps();
expect(mockDevice.appStopped, true);
expect(fakeVmServiceHost.hasRemainingExpectations, false);
}));
testUsingContext('FlutterDevice will exit an isolate that did not register the exit extension method', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
FakeVmServiceRequest(
method: '_flutter.listViews',
jsonResponse: <String, Object>{
'views': <Object>[
fakeFlutterView.toJson(),
],
},
),
FakeVmServiceRequest(
method: 'getIsolate',
args: <String, Object>{
'isolateId': fakeUnpausedIsolate.id,
},
jsonResponse: fakeUnpausedIsolate.toJson(),
),
FakeVmServiceRequest(
method: 'ext.flutter.exit',
args: <String, Object>{
'isolateId': fakeUnpausedIsolate.id,
},
errorCode: RPCErrorCodes.kMethodNotFound,
),
]);
final TestFlutterDevice flutterDevice = TestFlutterDevice(
mockDevice,
);
flutterDevice.vmService = fakeVmServiceHost.vmService;
await flutterDevice.exitApps(timeoutDelay: Duration.zero);
expect(mockDevice.appStopped, true);
expect(fakeVmServiceHost.hasRemainingExpectations, false);
}));
testUsingContext('FlutterDevice can exit from a release mode isolate with no VmService', () => testbed.run(() async {
final TestFlutterDevice flutterDevice = TestFlutterDevice(
mockDevice,
@ -1730,70 +1665,8 @@ void main() {
expect(mockDevice.appStopped, true);
}));
testUsingContext('FlutterDevice will call stopApp if the exit request times out', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
FakeVmServiceRequest(
method: '_flutter.listViews',
jsonResponse: <String, Object>{
'views': <Object>[
fakeFlutterView.toJson(),
],
},
),
FakeVmServiceRequest(
method: 'getIsolate',
args: <String, Object>{
'isolateId': fakeUnpausedIsolate.id,
},
jsonResponse: fakeUnpausedIsolate.toJson(),
),
FakeVmServiceRequest(
method: 'ext.flutter.exit',
args: <String, Object>{
'isolateId': fakeUnpausedIsolate.id,
},
// Intentionally do not close isolate.
close: false,
)
]);
final TestFlutterDevice flutterDevice = TestFlutterDevice(
mockDevice,
);
flutterDevice.vmService = fakeVmServiceHost.vmService;
await flutterDevice.exitApps(
timeoutDelay: Duration.zero,
);
expect(mockDevice.appStopped, true);
expect(fakeVmServiceHost.hasRemainingExpectations, false);
}));
testUsingContext('FlutterDevice will exit an un-paused isolate', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
FakeVmServiceRequest(
method: kListViewsMethod,
jsonResponse: <String, Object>{
'views': <Object>[
fakeFlutterView.toJson(),
],
},
),
FakeVmServiceRequest(
method: 'getIsolate',
args: <String, Object>{
'isolateId': fakeUnpausedIsolate.id
},
jsonResponse: fakeUnpausedIsolate.toJson(),
),
FakeVmServiceRequest(
method: 'ext.flutter.exit',
args: <String, Object>{
'isolateId': fakeUnpausedIsolate.id,
},
close: true,
)
]);
testUsingContext('FlutterDevice will exit an un-paused isolate using stopApp', () => testbed.run(() async {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
final TestFlutterDevice flutterDevice = TestFlutterDevice(
mockDevice,
);
@ -1802,6 +1675,7 @@ void main() {
final Future<void> exitFuture = flutterDevice.exitApps();
await expectLater(exitFuture, completes);
expect(mockDevice.appStopped, true);
expect(fakeVmServiceHost.hasRemainingExpectations, false);
}));