Unverified Commit 3aece335 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] refactor devtools handler into its own class (#75444)

parent 4d25d45c
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'package:meta/meta.dart';
import 'package:vm_service/vm_service.dart' as vm_service;
import 'base/logger.dart';
import 'resident_runner.dart';
import 'vmservice.dart';
/// Helper class to manage the life-cycle of devtools and its interaction with
/// the resident runner.
class ResidentDevtoolsHandler {
ResidentDevtoolsHandler(this._devToolsLauncher, this._residentRunner, this._logger);
final DevtoolsLauncher _devToolsLauncher;
final ResidentRunner _residentRunner;
final Logger _logger;
bool _shutdown = false;
bool _served = false;
/// The current devtools server, or null if one is not running.
DevToolsServerAddress get activeDevToolsServer => _devToolsLauncher?.activeDevToolsServer;
// This must be guaranteed not to return a Future that fails.
Future<void> serveAndAnnounceDevTools({
Uri devToolsServerAddress,
@required List<FlutterDevice> flutterDevices,
}) async {
if (!_residentRunner.supportsServiceProtocol || _devToolsLauncher == null) {
return;
}
if (devToolsServerAddress != null) {
_devToolsLauncher.devToolsUrl = devToolsServerAddress;
} else {
_served = true;
await _devToolsLauncher.serve();
}
await _devToolsLauncher.ready;
if (_residentRunner.reportedDebuggers) {
// Since the DevTools only just became available, we haven't had a chance to
// report their URLs yet. Do so now.
_residentRunner.printDebuggerList(includeObservatory: false);
}
await maybeCallDevToolsUriServiceExtension(
flutterDevices,
);
}
Future<void> maybeCallDevToolsUriServiceExtension(
List<FlutterDevice> flutterDevices,
) async {
if (_devToolsLauncher?.activeDevToolsServer == null) {
return;
}
await Future.wait(<Future<void>>[
for (final FlutterDevice device in flutterDevices)
if (device.vmService != null)
_callDevToolsUriExtension(device),
]);
}
Future<void> _callDevToolsUriExtension(
FlutterDevice device,
) async {
await waitForExtension(device.vmService, 'ext.flutter.activeDevToolsServerAddress');
try {
await _invokeRpcOnFirstView(
'ext.flutter.activeDevToolsServerAddress',
device: device,
params: <String, dynamic>{
'value': _devToolsLauncher.activeDevToolsServer.uri.toString(),
},
);
} on Exception catch (e) {
_logger.printError(
'Failed to set DevTools server address: ${e.toString()}. Deep links to'
' DevTools will not show in Flutter errors.',
);
}
}
Future<void> callConnectedVmServiceUriExtension(List<FlutterDevice> flutterDevices) async {
await Future.wait(<Future<void>>[
for (final FlutterDevice device in flutterDevices)
if (device.vmService != null)
_callConnectedVmServiceExtension(device),
]);
}
Future<void> _callConnectedVmServiceExtension(FlutterDevice device) async {
if (device.vmService.httpAddress != null || device.vmService.wsAddress != null) {
final Uri uri = device.vmService.httpAddress ?? device.vmService.wsAddress;
await waitForExtension(device.vmService, 'ext.flutter.connectedVmServiceUri');
try {
await _invokeRpcOnFirstView(
'ext.flutter.connectedVmServiceUri',
device: device,
params: <String, dynamic>{
'value': uri.toString(),
},
);
} on Exception catch (e) {
_logger.printError(e.toString());
_logger.printError(
'Failed to set vm service URI: ${e.toString()}. Deep links to DevTools'
' will not show in Flutter errors.',
);
}
}
}
Future<void> _invokeRpcOnFirstView(String method, {
@required FlutterDevice device,
@required Map<String, dynamic> params,
}) async {
final List<FlutterView> views = await device.vmService.getFlutterViews();
await device.vmService
.invokeFlutterExtensionRpcRaw(
method,
args: params,
isolateId: views
.first.uiIsolate.id
);
}
Future<void> hotRestart(List<FlutterDevice> flutterDevices) async {
await Future.wait(<Future<void>>[
maybeCallDevToolsUriServiceExtension(flutterDevices),
callConnectedVmServiceUriExtension(flutterDevices),
]);
}
Future<void> shutdown() async {
if (_devToolsLauncher == null || _shutdown || !_served) {
return;
}
_shutdown = true;
await _devToolsLauncher.close();
}
}
@visibleForTesting
Future<void> waitForExtension(vm_service.VmService vmService, String extension) async {
final Completer<void> completer = Completer<void>();
try {
await vmService.streamListen(vm_service.EventStreams.kExtension);
} on Exception {
// do nothing
}
StreamSubscription<vm_service.Event> extensionStream;
extensionStream = vmService.onExtensionEvent.listen((vm_service.Event event) {
if (event.json['extensionKind'] == 'Flutter.FrameworkInitialization') {
// The 'Flutter.FrameworkInitialization' event is sent on hot restart
// as well, so make sure we don't try to complete this twice.
if (!completer.isCompleted) {
completer.complete();
extensionStream.cancel();
}
}
});
final vm_service.VM vm = await vmService.getVM();
if (vm.isolates.isNotEmpty) {
final vm_service.IsolateRef isolateRef = vm.isolates.first;
final vm_service.Isolate isolate = await vmService.getIsolate(isolateRef.id);
if (isolate.extensionRPCs.contains(extension)) {
return;
}
}
await completer.future;
}
...@@ -35,6 +35,7 @@ import 'device.dart'; ...@@ -35,6 +35,7 @@ import 'device.dart';
import 'features.dart'; import 'features.dart';
import 'globals.dart' as globals; import 'globals.dart' as globals;
import 'project.dart'; import 'project.dart';
import 'resident_devtools_handler.dart';
import 'run_cold.dart'; import 'run_cold.dart';
import 'run_hot.dart'; import 'run_hot.dart';
import 'vmservice.dart'; import 'vmservice.dart';
...@@ -774,6 +775,7 @@ abstract class ResidentRunner { ...@@ -774,6 +775,7 @@ abstract class ResidentRunner {
if (!artifactDirectory.existsSync()) { if (!artifactDirectory.existsSync()) {
artifactDirectory.createSync(recursive: true); artifactDirectory.createSync(recursive: true);
} }
_residentDevtoolsHandler = ResidentDevtoolsHandler(DevtoolsLauncher.instance, this, globals.logger);
} }
@protected @protected
...@@ -795,9 +797,8 @@ abstract class ResidentRunner { ...@@ -795,9 +797,8 @@ abstract class ResidentRunner {
final CommandHelp commandHelp; final CommandHelp commandHelp;
final bool machine; final bool machine;
@visibleForTesting ResidentDevtoolsHandler get residentDevtoolsHandler => _residentDevtoolsHandler;
DevtoolsLauncher get devToolsLauncher => _devToolsLauncher; ResidentDevtoolsHandler _residentDevtoolsHandler;
DevtoolsLauncher _devToolsLauncher;
bool _exited = false; bool _exited = false;
Completer<int> _finished = Completer<int>(); Completer<int> _finished = Completer<int>();
...@@ -965,7 +966,7 @@ abstract class ResidentRunner { ...@@ -965,7 +966,7 @@ abstract class ResidentRunner {
Future<void> exit() async { Future<void> exit() async {
_exited = true; _exited = true;
await shutdownDevTools(); await residentDevtoolsHandler.shutdown();
await stopEchoingDeviceLog(); await stopEchoingDeviceLog();
await preExit(); await preExit();
await exitApp(); await exitApp();
...@@ -973,7 +974,7 @@ abstract class ResidentRunner { ...@@ -973,7 +974,7 @@ abstract class ResidentRunner {
} }
Future<void> detach() async { Future<void> detach() async {
await shutdownDevTools(); await residentDevtoolsHandler.shutdown();
await stopEchoingDeviceLog(); await stopEchoingDeviceLog();
await preExit(); await preExit();
await shutdownDartDevelopmentService(); await shutdownDartDevelopmentService();
...@@ -1274,101 +1275,6 @@ abstract class ResidentRunner { ...@@ -1274,101 +1275,6 @@ abstract class ResidentRunner {
} }
} }
DevToolsServerAddress activeDevToolsServer() {
_devToolsLauncher ??= DevtoolsLauncher.instance;
return _devToolsLauncher.activeDevToolsServer;
}
// This must be guaranteed not to return a Future that fails.
Future<void> serveAndAnnounceDevTools({
Uri devToolsServerAddress,
}) async {
if (!supportsServiceProtocol) {
return;
}
_devToolsLauncher ??= DevtoolsLauncher.instance;
if (devToolsServerAddress != null) {
_devToolsLauncher.devToolsUrl = devToolsServerAddress;
} else {
unawaited(_devToolsLauncher.serve());
}
await _devToolsLauncher.ready;
if (_reportedDebuggers) {
// Since the DevTools only just became available, we haven't had a chance to
// report their URLs yet. Do so now.
printDebuggerList(includeObservatory: false);
}
await maybeCallDevToolsUriServiceExtension();
}
Future<void> maybeCallDevToolsUriServiceExtension() async {
_devToolsLauncher ??= DevtoolsLauncher.instance;
if (_devToolsLauncher?.activeDevToolsServer != null) {
await Future.wait(<Future<void>>[
for (final FlutterDevice device in flutterDevices)
_callDevToolsUriExtension(device),
]);
}
}
Future<void> _callDevToolsUriExtension(FlutterDevice device) async {
if (_devToolsLauncher == null) {
return;
}
await waitForExtension(device.vmService, 'ext.flutter.activeDevToolsServerAddress');
try {
if (_devToolsLauncher == null) {
return;
}
unawaited(invokeFlutterExtensionRpcRawOnFirstIsolate(
'ext.flutter.activeDevToolsServerAddress',
device: device,
params: <String, dynamic>{
'value': _devToolsLauncher.activeDevToolsServer.uri.toString(),
},
));
} on Exception catch (e) {
globals.printError(
'Failed to set DevTools server address: ${e.toString()}. Deep links to'
' DevTools will not show in Flutter errors.',
);
}
}
Future<void> callConnectedVmServiceUriExtension() async {
await Future.wait(<Future<void>>[
for (final FlutterDevice device in flutterDevices)
_callConnectedVmServiceExtension(device),
]);
}
Future<void> _callConnectedVmServiceExtension(FlutterDevice device) async {
if (device.vmService.httpAddress != null || device.vmService.wsAddress != null) {
final Uri uri = device.vmService.httpAddress ?? device.vmService.wsAddress;
await waitForExtension(device.vmService, 'ext.flutter.connectedVmServiceUri');
try {
unawaited(invokeFlutterExtensionRpcRawOnFirstIsolate(
'ext.flutter.connectedVmServiceUri',
device: device,
params: <String, dynamic>{
'value': uri.toString(),
},
));
} on Exception catch (e) {
globals.printError(e.toString());
globals.printError(
'Failed to set vm service URI: ${e.toString()}. Deep links to DevTools'
' will not show in Flutter errors.',
);
}
}
}
Future<void> shutdownDevTools() async {
await _devToolsLauncher?.close();
_devToolsLauncher = null;
}
Future<void> _serviceProtocolDone(dynamic object) async { Future<void> _serviceProtocolDone(dynamic object) async {
globals.printTrace('Service protocol connection closed.'); globals.printTrace('Service protocol connection closed.');
} }
...@@ -1428,10 +1334,11 @@ abstract class ResidentRunner { ...@@ -1428,10 +1334,11 @@ abstract class ResidentRunner {
appFinished(); appFinished();
} }
bool get reportedDebuggers => _reportedDebuggers;
bool _reportedDebuggers = false; bool _reportedDebuggers = false;
void printDebuggerList({ bool includeObservatory = true, bool includeDevtools = true }) { void printDebuggerList({ bool includeObservatory = true, bool includeDevtools = true }) {
final DevToolsServerAddress devToolsServerAddress = activeDevToolsServer(); final DevToolsServerAddress devToolsServerAddress = residentDevtoolsHandler.activeDevToolsServer;
if (devToolsServerAddress == null) { if (devToolsServerAddress == null) {
includeDevtools = false; includeDevtools = false;
} }
...@@ -1506,36 +1413,6 @@ abstract class ResidentRunner { ...@@ -1506,36 +1413,6 @@ abstract class ResidentRunner {
void clearScreen() => globals.logger.clear(); void clearScreen() => globals.logger.clear();
} }
@visibleForTesting
Future<void> waitForExtension(vm_service.VmService vmService, String extension) async {
final Completer<void> completer = Completer<void>();
try {
await vmService.streamListen(vm_service.EventStreams.kExtension);
} on Exception {
// do nothing
}
StreamSubscription<vm_service.Event> extensionStream;
extensionStream = vmService.onExtensionEvent.listen((vm_service.Event event) {
if (event.json['extensionKind'] == 'Flutter.FrameworkInitialization') {
// The 'Flutter.FrameworkInitialization' event is sent on hot restart
// as well, so make sure we don't try to complete this twice.
if (!completer.isCompleted) {
completer.complete();
extensionStream.cancel();
}
}
});
final vm_service.VM vm = await vmService.getVM();
if (vm.isolates.isNotEmpty) {
final vm_service.IsolateRef isolateRef = vm.isolates.first;
final vm_service.Isolate isolate = await vmService.getIsolate(isolateRef.id);
if (isolate.extensionRPCs.contains(extension)) {
return;
}
}
await completer.future;
}
class OperationResult { class OperationResult {
OperationResult(this.code, this.message, { this.fatal = false }); OperationResult(this.code, this.message, { this.fatal = false });
......
...@@ -75,8 +75,9 @@ class ColdRunner extends ResidentRunner { ...@@ -75,8 +75,9 @@ class ColdRunner extends ResidentRunner {
if (enableDevTools) { if (enableDevTools) {
// The method below is guaranteed never to return a failing future. // The method below is guaranteed never to return a failing future.
unawaited(serveAndAnnounceDevTools( unawaited(residentDevtoolsHandler.serveAndAnnounceDevTools(
devToolsServerAddress: debuggingOptions.devToolsServerAddress, devToolsServerAddress: debuggingOptions.devToolsServerAddress,
flutterDevices: flutterDevices,
)); ));
} }
...@@ -125,7 +126,9 @@ class ColdRunner extends ResidentRunner { ...@@ -125,7 +126,9 @@ class ColdRunner extends ResidentRunner {
} }
if (debuggingEnabled) { if (debuggingEnabled) {
unawaited(callConnectedVmServiceUriExtension()); unawaited(residentDevtoolsHandler.callConnectedVmServiceUriExtension(
flutterDevices,
));
} }
appStartedCompleter?.complete(); appStartedCompleter?.complete();
...@@ -159,8 +162,9 @@ class ColdRunner extends ResidentRunner { ...@@ -159,8 +162,9 @@ class ColdRunner extends ResidentRunner {
if (enableDevTools) { if (enableDevTools) {
// The method below is guaranteed never to return a failing future. // The method below is guaranteed never to return a failing future.
unawaited(serveAndAnnounceDevTools( unawaited(residentDevtoolsHandler.serveAndAnnounceDevTools(
devToolsServerAddress: debuggingOptions.devToolsServerAddress, devToolsServerAddress: debuggingOptions.devToolsServerAddress,
flutterDevices: flutterDevices,
)); ));
} }
...@@ -174,7 +178,9 @@ class ColdRunner extends ResidentRunner { ...@@ -174,7 +178,9 @@ class ColdRunner extends ResidentRunner {
} }
} }
unawaited(callConnectedVmServiceUriExtension()); unawaited(residentDevtoolsHandler.callConnectedVmServiceUriExtension(
flutterDevices,
));
appStartedCompleter?.complete(); appStartedCompleter?.complete();
if (stayResident) { if (stayResident) {
......
...@@ -196,8 +196,9 @@ class HotRunner extends ResidentRunner { ...@@ -196,8 +196,9 @@ class HotRunner extends ResidentRunner {
if (enableDevTools) { if (enableDevTools) {
// The method below is guaranteed never to return a failing future. // The method below is guaranteed never to return a failing future.
unawaited(serveAndAnnounceDevTools( unawaited(residentDevtoolsHandler.serveAndAnnounceDevTools(
devToolsServerAddress: debuggingOptions.devToolsServerAddress, devToolsServerAddress: debuggingOptions.devToolsServerAddress,
flutterDevices: flutterDevices,
)); ));
} }
...@@ -221,7 +222,9 @@ class HotRunner extends ResidentRunner { ...@@ -221,7 +222,9 @@ class HotRunner extends ResidentRunner {
return 3; return 3;
} }
unawaited(callConnectedVmServiceUriExtension()); unawaited(residentDevtoolsHandler.callConnectedVmServiceUriExtension(
flutterDevices,
));
final Stopwatch initialUpdateDevFSsTimer = Stopwatch()..start(); final Stopwatch initialUpdateDevFSsTimer = Stopwatch()..start();
final UpdateFSReport devfsResult = await _updateDevFS(fullRestart: true); final UpdateFSReport devfsResult = await _updateDevFS(fullRestart: true);
...@@ -641,8 +644,7 @@ class HotRunner extends ResidentRunner { ...@@ -641,8 +644,7 @@ class HotRunner extends ResidentRunner {
if (!silent) { if (!silent) {
globals.printStatus('Restarted application in ${getElapsedAsMilliseconds(timer.elapsed)}.'); globals.printStatus('Restarted application in ${getElapsedAsMilliseconds(timer.elapsed)}.');
} }
unawaited(maybeCallDevToolsUriServiceExtension()); unawaited(residentDevtoolsHandler.hotRestart(flutterDevices));
unawaited(callConnectedVmServiceUriExtension());
return result; return result;
} }
final OperationResult result = await _hotReloadHelper( final OperationResult result = await _hotReloadHelper(
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/devtools_launcher.dart';
import 'package:vm_service/vm_service.dart' as vm_service;
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/resident_devtools_handler.dart';
import 'package:flutter_tools/src/resident_runner.dart';
import 'package:test/fake.dart';
import '../src/common.dart';
import '../src/context.dart';
final vm_service.Isolate fakeUnpausedIsolate = vm_service.Isolate(
id: '1',
pauseEvent: vm_service.Event(
kind: vm_service.EventKind.kResume,
timestamp: 0
),
breakpoints: <vm_service.Breakpoint>[],
exceptionPauseMode: null,
extensionRPCs: <String>[],
libraries: <vm_service.LibraryRef>[
vm_service.LibraryRef(
id: '1',
uri: 'file:///hello_world/main.dart',
name: '',
),
],
livePorts: 0,
name: 'test',
number: '1',
pauseOnExit: false,
runnable: true,
startTime: 0,
isSystemIsolate: false,
isolateFlags: <vm_service.IsolateFlag>[],
);
final vm_service.VM fakeVM = vm_service.VM(
isolates: <vm_service.IsolateRef>[fakeUnpausedIsolate],
pid: 1,
hostCPU: '',
isolateGroups: <vm_service.IsolateGroupRef>[],
targetCPU: '',
startTime: 0,
name: 'dart',
architectureBits: 64,
operatingSystem: '',
version: '',
systemIsolateGroups: <vm_service.IsolateGroupRef>[],
systemIsolates: <vm_service.IsolateRef>[],
);
void main() {
testWithoutContext('Does not serve devtools if launcher is null', () async {
final ResidentDevtoolsHandler handler = ResidentDevtoolsHandler(
null,
FakeResidentRunner(),
BufferLogger.test(),
);
await handler.serveAndAnnounceDevTools(flutterDevices: <FlutterDevice>[]);
expect(handler.activeDevToolsServer, null);
});
testWithoutContext('Does not serve devtools if ResidentRunner does not support the service protocol', () async {
final ResidentDevtoolsHandler handler = ResidentDevtoolsHandler(
FakeDevtoolsLauncher(),
FakeResidentRunner()..supportsServiceProtocol = false,
BufferLogger.test(),
);
await handler.serveAndAnnounceDevTools(flutterDevices: <FlutterDevice>[]);
expect(handler.activeDevToolsServer, null);
});
testWithoutContext('Can use devtools with existing devtools URI', () async {
final DevtoolsServerLauncher launcher = DevtoolsServerLauncher(
processManager: FakeProcessManager.list(<FakeCommand>[]),
pubExecutable: 'pub',
logger: BufferLogger.test(),
platform: FakePlatform(),
persistentToolState: null,
);
final ResidentDevtoolsHandler handler = ResidentDevtoolsHandler(
// Uses real devtools instance which should be a no-op if
// URI is already set.
launcher,
FakeResidentRunner(),
BufferLogger.test(),
);
await handler.serveAndAnnounceDevTools(
devToolsServerAddress: Uri.parse('http://localhost:8181'),
flutterDevices: <FlutterDevice>[],
);
expect(handler.activeDevToolsServer.host, 'localhost');
expect(handler.activeDevToolsServer.port, 8181);
});
testWithoutContext('can serveAndAnnounceDevTools with attached device does not fail on null vm service', () async {
final ResidentDevtoolsHandler handler = ResidentDevtoolsHandler(
FakeDevtoolsLauncher()..activeDevToolsServer = DevToolsServerAddress('localhost', 8080),
FakeResidentRunner(),
BufferLogger.test(),
);
// VM Service is intentionally null
final FakeFlutterDevice device = FakeFlutterDevice();
await handler.serveAndAnnounceDevTools(
flutterDevices: <FlutterDevice>[device],
);
});
testWithoutContext('wait for extension handles an immediate extension', () {
final vm_service.Isolate isolate = vm_service.Isolate(
id: '1',
pauseEvent: vm_service.Event(
kind: vm_service.EventKind.kResume,
timestamp: 0
),
breakpoints: <vm_service.Breakpoint>[],
exceptionPauseMode: null,
libraries: <vm_service.LibraryRef>[
vm_service.LibraryRef(
id: '1',
uri: 'file:///hello_world/main.dart',
name: '',
),
],
livePorts: 0,
name: 'test',
number: '1',
pauseOnExit: false,
runnable: true,
startTime: 0,
isSystemIsolate: false,
isolateFlags: <vm_service.IsolateFlag>[],
extensionRPCs: <String>['foo']
);
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
const FakeVmServiceRequest(
method: 'streamListen',
args: <String, Object>{
'streamId': 'Extension',
}
),
FakeVmServiceRequest(method: 'getVM', jsonResponse: fakeVM.toJson()),
FakeVmServiceRequest(
method: 'getIsolate',
jsonResponse: isolate.toJson(),
args: <String, Object>{
'isolateId': '1',
},
),
]);
waitForExtension(fakeVmServiceHost.vmService, 'foo');
});
testWithoutContext('wait for extension handles no isolates', () {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
const FakeVmServiceRequest(
method: 'streamListen',
args: <String, Object>{
'streamId': 'Extension',
}
),
FakeVmServiceRequest(method: 'getVM', jsonResponse: vm_service.VM(
isolates: <vm_service.IsolateRef>[],
pid: 1,
hostCPU: '',
isolateGroups: <vm_service.IsolateGroupRef>[],
targetCPU: '',
startTime: 0,
name: 'dart',
architectureBits: 64,
operatingSystem: '',
version: '',
systemIsolateGroups: <vm_service.IsolateGroupRef>[],
systemIsolates: <vm_service.IsolateRef>[],
).toJson()),
FakeVmServiceStreamResponse(
streamId: 'Extension',
event: vm_service.Event(
timestamp: 0,
extensionKind: 'Flutter.FrameworkInitialization',
kind: 'test',
),
),
]);
waitForExtension(fakeVmServiceHost.vmService, 'foo');
});
}
class FakeDevtoolsLauncher extends Fake implements DevtoolsLauncher {
@override
DevToolsServerAddress activeDevToolsServer;
@override
Future<DevToolsServerAddress> serve() {
return null;
}
@override
Future<void> get ready => Future<void>.value();
}
class FakeResidentRunner extends Fake implements ResidentRunner {
@override
bool supportsServiceProtocol = true;
@override
bool reportedDebuggers = false;
}
class FakeFlutterDevice extends Fake implements FlutterDevice {
@override
vm_service.VmService vmService;
}
...@@ -1600,7 +1600,7 @@ void main() { ...@@ -1600,7 +1600,7 @@ void main() {
verify(mockDevtoolsLauncher.serve()).called(1); verify(mockDevtoolsLauncher.serve()).called(1);
// Shutdown // Shutdown
await residentRunner.shutdownDevTools(); await residentRunner.residentDevtoolsHandler.shutdown();
verify(mockDevtoolsLauncher.close()).called(1); verify(mockDevtoolsLauncher.close()).called(1);
}), overrides: <Type, Generator>{ }), overrides: <Type, Generator>{
DevtoolsLauncher: () => mockDevtoolsLauncher, DevtoolsLauncher: () => mockDevtoolsLauncher,
...@@ -1634,7 +1634,7 @@ void main() { ...@@ -1634,7 +1634,7 @@ void main() {
verify(mockDevtoolsLauncher.serve()).called(1); verify(mockDevtoolsLauncher.serve()).called(1);
// Shutdown // Shutdown
await residentRunner.shutdownDevTools(); await residentRunner.residentDevtoolsHandler.shutdown();
verify(mockDevtoolsLauncher.close()).called(1); verify(mockDevtoolsLauncher.close()).called(1);
}), overrides: <Type, Generator>{ }), overrides: <Type, Generator>{
DevtoolsLauncher: () => mockDevtoolsLauncher, DevtoolsLauncher: () => mockDevtoolsLauncher,
...@@ -1713,7 +1713,7 @@ void main() { ...@@ -1713,7 +1713,7 @@ void main() {
verify(mockDevtoolsLauncher.serve()).called(1); verify(mockDevtoolsLauncher.serve()).called(1);
// Shutdown // Shutdown
await residentRunner.shutdownDevTools(); await residentRunner.residentDevtoolsHandler.shutdown();
verify(mockDevtoolsLauncher.close()).called(1); verify(mockDevtoolsLauncher.close()).called(1);
}), overrides: <Type, Generator>{ }), overrides: <Type, Generator>{
DevtoolsLauncher: () => mockDevtoolsLauncher, DevtoolsLauncher: () => mockDevtoolsLauncher,
...@@ -2941,86 +2941,6 @@ void main() { ...@@ -2941,86 +2941,6 @@ void main() {
expect(nextPlatform('fuchsia', TestFeatureFlags(isMacOSEnabled: true)), 'macOS'); expect(nextPlatform('fuchsia', TestFeatureFlags(isMacOSEnabled: true)), 'macOS');
expect(() => nextPlatform('unknown', TestFeatureFlags()), throwsAssertionError); expect(() => nextPlatform('unknown', TestFeatureFlags()), throwsAssertionError);
}); });
testWithoutContext('wait for extension handles an immediate extension', () {
final vm_service.Isolate isolate = vm_service.Isolate(
id: '1',
pauseEvent: vm_service.Event(
kind: vm_service.EventKind.kResume,
timestamp: 0
),
breakpoints: <vm_service.Breakpoint>[],
exceptionPauseMode: null,
libraries: <vm_service.LibraryRef>[
vm_service.LibraryRef(
id: '1',
uri: 'file:///hello_world/main.dart',
name: '',
),
],
livePorts: 0,
name: 'test',
number: '1',
pauseOnExit: false,
runnable: true,
startTime: 0,
isSystemIsolate: false,
isolateFlags: <vm_service.IsolateFlag>[],
extensionRPCs: <String>['foo']
);
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
const FakeVmServiceRequest(
method: 'streamListen',
args: <String, Object>{
'streamId': 'Extension',
}
),
FakeVmServiceRequest(method: 'getVM', jsonResponse: fakeVM.toJson()),
FakeVmServiceRequest(
method: 'getIsolate',
jsonResponse: isolate.toJson(),
args: <String, Object>{
'isolateId': '1',
},
),
]);
waitForExtension(fakeVmServiceHost.vmService, 'foo');
});
testWithoutContext('wait for extension handles no isolates', () {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
const FakeVmServiceRequest(
method: 'streamListen',
args: <String, Object>{
'streamId': 'Extension',
}
),
FakeVmServiceRequest(method: 'getVM', jsonResponse: vm_service.VM(
isolates: <vm_service.IsolateRef>[],
pid: 1,
hostCPU: '',
isolateGroups: <vm_service.IsolateGroupRef>[],
targetCPU: '',
startTime: 0,
name: 'dart',
architectureBits: 64,
operatingSystem: '',
version: '',
systemIsolateGroups: <vm_service.IsolateGroupRef>[],
systemIsolates: <vm_service.IsolateRef>[],
).toJson()),
FakeVmServiceStreamResponse(
streamId: 'Extension',
event: vm_service.Event(
timestamp: 0,
extensionKind: 'Flutter.FrameworkInitialization',
kind: 'test',
),
),
]);
waitForExtension(fakeVmServiceHost.vmService, 'foo');
});
} }
class MockFlutterDevice extends Mock implements FlutterDevice {} class MockFlutterDevice extends Mock implements FlutterDevice {}
......
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