Unverified Commit 209bdcb6 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] remove flutter view cache (#56223)

Remove caching of FlutterView. Perhaps the FlutterView RPC might return an empty list if the VM is not quite up yet? We had some old logic to poll the flutter views RPC for up to 200ms. That doesn't seem like a great approach, so instead we could forgo it entirely and trust that either the views come up before the developer tries to interact, or we crash.
parent a48a51b0
...@@ -190,6 +190,11 @@ abstract class ResidentWebRunner extends ResidentRunner { ...@@ -190,6 +190,11 @@ abstract class ResidentWebRunner extends ResidentRunner {
globals.printStatus('For a more detailed help message, press "h". $quitMessage'); globals.printStatus('For a more detailed help message, press "h". $quitMessage');
} }
@override
Future<List<FlutterView>> listFlutterViews() async {
return <FlutterView>[];
}
@override @override
Future<void> debugDumpApp() async { Future<void> debugDumpApp() async {
try { try {
......
...@@ -95,7 +95,6 @@ class ColdRunner extends ResidentRunner { ...@@ -95,7 +95,6 @@ class ColdRunner extends ResidentRunner {
continue; continue;
} }
await device.initLogReader(); await device.initLogReader();
await device.refreshViews();
globals.printTrace('Connected to ${device.device.name}'); globals.printTrace('Connected to ${device.device.name}');
} }
...@@ -145,9 +144,9 @@ class ColdRunner extends ResidentRunner { ...@@ -145,9 +144,9 @@ class ColdRunner extends ResidentRunner {
for (final FlutterDevice device in flutterDevices) { for (final FlutterDevice device in flutterDevices) {
await device.initLogReader(); await device.initLogReader();
} }
await refreshViews();
for (final FlutterDevice device in flutterDevices) { for (final FlutterDevice device in flutterDevices) {
for (final FlutterView view in device.views) { final List<FlutterView> views = await device.vmService.getFlutterViews();
for (final FlutterView view in views) {
globals.printTrace('Connected to $view.'); globals.printTrace('Connected to $view.');
} }
} }
......
...@@ -198,7 +198,8 @@ class HotRunner extends ResidentRunner { ...@@ -198,7 +198,8 @@ class HotRunner extends ResidentRunner {
} }
for (final FlutterDevice device in flutterDevices) { for (final FlutterDevice device in flutterDevices) {
for (final FlutterView view in device.views) { final List<FlutterView> views = await device.vmService.getFlutterViews();
for (final FlutterView view in views) {
await device.vmService.flutterFastReassemble( await device.vmService.flutterFastReassemble(
classId, classId,
isolateId: view.uiIsolate.id, isolateId: view.uiIsolate.id,
...@@ -277,14 +278,14 @@ class HotRunner extends ResidentRunner { ...@@ -277,14 +278,14 @@ class HotRunner extends ResidentRunner {
return 3; return 3;
} }
await refreshViews();
for (final FlutterDevice device in flutterDevices) { for (final FlutterDevice device in flutterDevices) {
// VM must have accepted the kernel binary, there will be no reload // VM must have accepted the kernel binary, there will be no reload
// report, so we let incremental compiler know that source code was accepted. // report, so we let incremental compiler know that source code was accepted.
if (device.generator != null) { if (device.generator != null) {
device.generator.accept(); device.generator.accept();
} }
for (final FlutterView view in device.views) { final List<FlutterView> views = await device.vmService.getFlutterViews();
for (final FlutterView view in views) {
globals.printTrace('Connected to $view.'); globals.printTrace('Connected to $view.');
} }
} }
...@@ -474,15 +475,15 @@ class HotRunner extends ResidentRunner { ...@@ -474,15 +475,15 @@ class HotRunner extends ResidentRunner {
Uri main, Uri main,
Uri assetsDirectory, Uri assetsDirectory,
) async { ) async {
final List<FlutterView> views = await device.vmService.getFlutterViews();
await Future.wait(<Future<void>>[ await Future.wait(<Future<void>>[
for (final FlutterView view in device.views) for (final FlutterView view in views)
device.vmService.runInView( device.vmService.runInView(
viewId: view.id, viewId: view.id,
main: main, main: main,
assetsDirectory: assetsDirectory, assetsDirectory: assetsDirectory,
), ),
]); ]);
await device.refreshViews();
} }
Future<void> _launchFromDevFS(String mainScript) async { Future<void> _launchFromDevFS(String mainScript) async {
...@@ -501,7 +502,8 @@ class HotRunner extends ResidentRunner { ...@@ -501,7 +502,8 @@ class HotRunner extends ResidentRunner {
if (benchmarkMode) { if (benchmarkMode) {
futures.clear(); futures.clear();
for (final FlutterDevice device in flutterDevices) { for (final FlutterDevice device in flutterDevices) {
for (final FlutterView view in device.views) { final List<FlutterView> views = await device.vmService.getFlutterViews();
for (final FlutterView view in views) {
futures.add(device.vmService futures.add(device.vmService
.flushUIThreadTasks(uiIsolateId: view.uiIsolate.id)); .flushUIThreadTasks(uiIsolateId: view.uiIsolate.id));
} }
...@@ -514,9 +516,6 @@ class HotRunner extends ResidentRunner { ...@@ -514,9 +516,6 @@ class HotRunner extends ResidentRunner {
String reason, String reason,
bool benchmarkMode = false, bool benchmarkMode = false,
}) async { }) async {
globals.printTrace('Refreshing active FlutterViews before restarting.');
await refreshViews();
final Stopwatch restartTimer = Stopwatch()..start(); final Stopwatch restartTimer = Stopwatch()..start();
// TODO(aam): Add generator reset logic once we switch to using incremental // TODO(aam): Add generator reset logic once we switch to using incremental
// compiler for full application recompilation on restart. // compiler for full application recompilation on restart.
...@@ -541,7 +540,8 @@ class HotRunner extends ResidentRunner { ...@@ -541,7 +540,8 @@ class HotRunner extends ResidentRunner {
final List<Future<void>> operations = <Future<void>>[]; final List<Future<void>> operations = <Future<void>>[];
for (final FlutterDevice device in flutterDevices) { for (final FlutterDevice device in flutterDevices) {
final Set<String> uiIsolatesIds = <String>{}; final Set<String> uiIsolatesIds = <String>{};
for (final FlutterView view in device.views) { final List<FlutterView> views = await device.vmService.getFlutterViews();
for (final FlutterView view in views) {
if (view.uiIsolate == null) { if (view.uiIsolate == null) {
continue; continue;
} }
...@@ -810,7 +810,8 @@ class HotRunner extends ResidentRunner { ...@@ -810,7 +810,8 @@ class HotRunner extends ResidentRunner {
void Function(String message) onSlow, void Function(String message) onSlow,
}) async { }) async {
for (final FlutterDevice device in flutterDevices) { for (final FlutterDevice device in flutterDevices) {
for (final FlutterView view in device.views) { final List<FlutterView> views = await device.vmService.getFlutterViews();
for (final FlutterView view in views) {
if (view.uiIsolate == null) { if (view.uiIsolate == null) {
return OperationResult(2, 'Application isolate not found', fatal: true); return OperationResult(2, 'Application isolate not found', fatal: true);
} }
...@@ -818,10 +819,6 @@ class HotRunner extends ResidentRunner { ...@@ -818,10 +819,6 @@ class HotRunner extends ResidentRunner {
} }
final Stopwatch reloadTimer = Stopwatch()..start(); final Stopwatch reloadTimer = Stopwatch()..start();
globals.printTrace('Refreshing active FlutterViews before reloading.');
await refreshViews();
final Stopwatch devFSTimer = Stopwatch()..start(); final Stopwatch devFSTimer = Stopwatch()..start();
final UpdateFSReport updatedDevFS = await _updateDevFS(); final UpdateFSReport updatedDevFS = await _updateDevFS();
// Record time it took to synchronize to DevFS. // Record time it took to synchronize to DevFS.
...@@ -912,14 +909,6 @@ class HotRunner extends ResidentRunner { ...@@ -912,14 +909,6 @@ class HotRunner extends ResidentRunner {
// Record time it took for the VM to reload the sources. // Record time it took for the VM to reload the sources.
_addBenchmarkData('hotReloadVMReloadMilliseconds', vmReloadTimer.elapsed.inMilliseconds); _addBenchmarkData('hotReloadVMReloadMilliseconds', vmReloadTimer.elapsed.inMilliseconds);
final Stopwatch reassembleTimer = Stopwatch()..start(); final Stopwatch reassembleTimer = Stopwatch()..start();
// Reload the isolate data.
await Future.wait(<Future<void>>[
for (final FlutterDevice device in flutterDevices)
device.refreshViews()
]);
globals.printTrace('Evicting dirty assets');
await _evictDirtyAssets(); await _evictDirtyAssets();
// Check if any isolates are paused and reassemble those // Check if any isolates are paused and reassemble those
...@@ -930,7 +919,8 @@ class HotRunner extends ResidentRunner { ...@@ -930,7 +919,8 @@ class HotRunner extends ResidentRunner {
int pausedIsolatesFound = 0; int pausedIsolatesFound = 0;
bool failedReassemble = false; bool failedReassemble = false;
for (final FlutterDevice device in flutterDevices) { for (final FlutterDevice device in flutterDevices) {
for (final FlutterView view in device.views) { final List<FlutterView> views = await device.vmService.getFlutterViews();
for (final FlutterView view in views) {
// Check if the isolate is paused, and if so, don't reassemble. Ignore the // Check if the isolate is paused, and if so, don't reassemble. Ignore the
// PostPauseEvent event - the client requesting the pause will resume the app. // PostPauseEvent event - the client requesting the pause will resume the app.
final vm_service.Isolate isolate = await device.vmService final vm_service.Isolate isolate = await device.vmService
...@@ -1055,11 +1045,7 @@ class HotRunner extends ResidentRunner { ...@@ -1055,11 +1045,7 @@ class HotRunner extends ResidentRunner {
final StringBuffer message = StringBuffer(); final StringBuffer message = StringBuffer();
bool plural; bool plural;
if (pausedIsolatesFound == 1) { if (pausedIsolatesFound == 1) {
if (flutterDevices.length == 1 && flutterDevices.single.views.length == 1) { message.write('The application is ');
message.write('The application is ');
} else {
message.write('An isolate is ');
}
plural = false; plural = false;
} else { } else {
message.write('$pausedIsolatesFound isolates are '); message.write('$pausedIsolatesFound isolates are ');
...@@ -1121,13 +1107,14 @@ class HotRunner extends ResidentRunner { ...@@ -1121,13 +1107,14 @@ class HotRunner extends ResidentRunner {
} }
} }
Future<void> _evictDirtyAssets() { Future<void> _evictDirtyAssets() async {
final List<Future<Map<String, dynamic>>> futures = <Future<Map<String, dynamic>>>[]; final List<Future<Map<String, dynamic>>> futures = <Future<Map<String, dynamic>>>[];
for (final FlutterDevice device in flutterDevices) { for (final FlutterDevice device in flutterDevices) {
if (device.devFS.assetPathsToEvict.isEmpty) { if (device.devFS.assetPathsToEvict.isEmpty) {
continue; continue;
} }
if (device.views.first.uiIsolate == null) { final List<FlutterView> views = await device.vmService.getFlutterViews();
if (views.first.uiIsolate == null) {
globals.printError('Application isolate not found for $device'); globals.printError('Application isolate not found for $device');
continue; continue;
} }
...@@ -1136,7 +1123,7 @@ class HotRunner extends ResidentRunner { ...@@ -1136,7 +1123,7 @@ class HotRunner extends ResidentRunner {
device.vmService device.vmService
.flutterEvictAsset( .flutterEvictAsset(
assetPath, assetPath,
isolateId: device.views.first.uiIsolate.id, isolateId: views.first.uiIsolate.id,
) )
); );
} }
......
...@@ -684,15 +684,29 @@ extension FlutterVmService on vm_service.VmService { ...@@ -684,15 +684,29 @@ extension FlutterVmService on vm_service.VmService {
} }
/// List all [FlutterView]s attached to the current VM. /// List all [FlutterView]s attached to the current VM.
Future<List<FlutterView>> getFlutterViews() async { ///
final vm_service.Response response = await callMethod( /// If this returns an empty list, it will poll forever unless [returnEarly]
kListViewsMethod, /// is set to true.
); ///
final List<Object> rawViews = response.json['views'] as List<Object>; /// By default, the poll duration is 50 milliseconds.
return <FlutterView>[ Future<List<FlutterView>> getFlutterViews({
for (final Object rawView in rawViews) bool returnEarly = false,
FlutterView.parse(rawView as Map<String, Object>) Duration delay = const Duration(milliseconds: 50),
]; }) async {
while (true) {
final vm_service.Response response = await callMethod(
kListViewsMethod,
);
final List<Object> rawViews = response.json['views'] as List<Object>;
final List<FlutterView> views = <FlutterView>[
for (final Object rawView in rawViews)
FlutterView.parse(rawView as Map<String, Object>)
];
if (views.isNotEmpty || returnEarly) {
return views;
}
await Future<void>.delayed(delay);
}
} }
/// Attempt to retrieve the isolate with id [isolateId], or `null` if it has /// Attempt to retrieve the isolate with id [isolateId], or `null` if it has
......
...@@ -66,7 +66,7 @@ abstract class ChromiumDevice extends Device { ...@@ -66,7 +66,7 @@ abstract class ChromiumDevice extends Device {
bool get supportsStartPaused => true; bool get supportsStartPaused => true;
@override @override
bool get supportsFlutterExit => true; bool get supportsFlutterExit => false;
@override @override
bool get supportsScreenshot => false; bool get supportsScreenshot => false;
...@@ -343,6 +343,9 @@ class WebServerDevice extends Device { ...@@ -343,6 +343,9 @@ class WebServerDevice extends Device {
@override @override
Future<bool> isLatestBuildInstalled(ApplicationPackage app) async => true; Future<bool> isLatestBuildInstalled(ApplicationPackage app) async => true;
@override
bool get supportsFlutterExit => false;
@override @override
Future<bool> get isLocalEmulator async => false; Future<bool> get isLocalEmulator async => false;
......
...@@ -685,7 +685,6 @@ VMServiceConnector getFakeVmServiceFactory({ ...@@ -685,7 +685,6 @@ VMServiceConnector getFakeVmServiceFactory({
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost( final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[ requests: <VmServiceExpectation>[
FakeVmServiceRequest( FakeVmServiceRequest(
id: '1',
method: kListViewsMethod, method: kListViewsMethod,
args: null, args: null,
jsonResponse: <String, Object>{ jsonResponse: <String, Object>{
...@@ -698,14 +697,12 @@ VMServiceConnector getFakeVmServiceFactory({ ...@@ -698,14 +697,12 @@ VMServiceConnector getFakeVmServiceFactory({
}, },
), ),
FakeVmServiceRequest( FakeVmServiceRequest(
id: '2',
method: 'getVM', method: 'getVM',
args: null, args: null,
jsonResponse: vm_service.VM.parse(<String, Object>{}) jsonResponse: vm_service.VM.parse(<String, Object>{})
.toJson(), .toJson(),
), ),
FakeVmServiceRequest( FakeVmServiceRequest(
id: '3',
method: '_createDevFS', method: '_createDevFS',
args: <String, Object>{ args: <String, Object>{
'fsName': globals.fs.currentDirectory.absolute.path, 'fsName': globals.fs.currentDirectory.absolute.path,
...@@ -715,7 +712,6 @@ VMServiceConnector getFakeVmServiceFactory({ ...@@ -715,7 +712,6 @@ VMServiceConnector getFakeVmServiceFactory({
}, },
), ),
FakeVmServiceRequest( FakeVmServiceRequest(
id: '4',
method: kListViewsMethod, method: kListViewsMethod,
args: null, args: null,
jsonResponse: <String, Object>{ jsonResponse: <String, Object>{
......
...@@ -65,7 +65,7 @@ void main() { ...@@ -65,7 +65,7 @@ void main() {
'hotRestart': true, 'hotRestart': true,
'screenshot': false, 'screenshot': false,
'fastStart': false, 'fastStart': false,
'flutterExit': true, 'flutterExit': false,
'hardwareRendering': false, 'hardwareRendering': false,
'startPaused': true 'startPaused': true
} }
......
...@@ -12,7 +12,6 @@ void main() { ...@@ -12,7 +12,6 @@ void main() {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost( final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[ requests: <VmServiceExpectation>[
FakeVmServiceRequest( FakeVmServiceRequest(
id: '1',
method: 'getVM', method: 'getVM',
jsonResponse: (vm_service.VM.parse(<String, Object>{}) jsonResponse: (vm_service.VM.parse(<String, Object>{})
..isolates = <vm_service.IsolateRef>[ ..isolates = <vm_service.IsolateRef>[
...@@ -23,7 +22,6 @@ void main() { ...@@ -23,7 +22,6 @@ void main() {
).toJson(), ).toJson(),
), ),
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '2',
method: 'getScripts', method: 'getScripts',
args: <String, Object>{ args: <String, Object>{
'isolateId': '1', 'isolateId': '1',
......
...@@ -129,7 +129,6 @@ void main() { ...@@ -129,7 +129,6 @@ void main() {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost( final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[ requests: <VmServiceExpectation>[
FakeVmServiceRequest( FakeVmServiceRequest(
id: '1',
method: '_createDevFS', method: '_createDevFS',
args: <String, Object>{ args: <String, Object>{
'fsName': 'test', 'fsName': 'test',
...@@ -202,7 +201,6 @@ void main() { ...@@ -202,7 +201,6 @@ void main() {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost( final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[ requests: <VmServiceExpectation>[
FakeVmServiceRequest( FakeVmServiceRequest(
id: '1',
method: '_createDevFS', method: '_createDevFS',
args: <String, Object>{ args: <String, Object>{
'fsName': 'test', 'fsName': 'test',
......
...@@ -637,7 +637,6 @@ void main() { ...@@ -637,7 +637,6 @@ void main() {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost( final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[ requests: <VmServiceExpectation>[
FakeVmServiceRequest( FakeVmServiceRequest(
id: '1',
method: kListViewsMethod, method: kListViewsMethod,
jsonResponse: <String, Object>{ jsonResponse: <String, Object>{
'views': <Object>[ 'views': <Object>[
......
...@@ -21,6 +21,36 @@ import '../src/common.dart'; ...@@ -21,6 +21,36 @@ import '../src/common.dart';
import '../src/context.dart'; import '../src/context.dart';
import '../src/mocks.dart'; import '../src/mocks.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,
libraries: <vm_service.LibraryRef>[],
livePorts: 0,
name: 'test',
number: '1',
pauseOnExit: false,
runnable: true,
startTime: 0,
);
final FlutterView fakeFlutterView = FlutterView(
id: 'a',
uiIsolate: fakeUnpausedIsolate,
);
final FakeVmServiceRequest listViews = FakeVmServiceRequest(
method: kListViewsMethod,
jsonResponse: <String, Object>{
'views': <Object>[
fakeFlutterView.toJson(),
],
},
);
void main() { void main() {
group('validateReloadReport', () { group('validateReloadReport', () {
testUsingContext('invalid', () async { testUsingContext('invalid', () async {
...@@ -172,42 +202,72 @@ void main() { ...@@ -172,42 +202,72 @@ void main() {
testUsingContext('Does hot restarts when all devices support it', () async { testUsingContext('Does hot restarts when all devices support it', () async {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
const FakeVmServiceRequest( listViews,
id: '1', FakeVmServiceRequest(
method: kListViewsMethod, method: 'getIsolate',
jsonResponse: <String, Object>{ args: <String, Object>{
'views': <Object>[], 'isolateId': fakeUnpausedIsolate.id,
} },
), jsonResponse: fakeUnpausedIsolate.toJson(),
const FakeVmServiceRequest(
id: '2',
method: kListViewsMethod,
jsonResponse: <String, Object>{
'views': <Object>[],
}
), ),
FakeVmServiceRequest( FakeVmServiceRequest(
id: '3',
method: 'getVM', method: 'getVM',
jsonResponse: vm_service.VM.parse(<String, Object>{}).toJson() jsonResponse: vm_service.VM.parse(<String, Object>{}).toJson()
), ),
listViews,
FakeVmServiceRequest(
method: 'getIsolate',
args: <String, Object>{
'isolateId': fakeUnpausedIsolate.id,
},
jsonResponse: fakeUnpausedIsolate.toJson(),
),
FakeVmServiceRequest( FakeVmServiceRequest(
id: '4',
method: 'getVM', method: 'getVM',
jsonResponse: vm_service.VM.parse(<String, Object>{}).toJson() jsonResponse: vm_service.VM.parse(<String, Object>{}).toJson()
), ),
listViews,
listViews,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5', method: 'streamListen',
method: kListViewsMethod, args: <String, Object>{
jsonResponse: <String, Object>{ 'streamId': 'Isolate',
'views': <Object>[],
} }
), ),
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '6', method: 'streamListen',
method: kListViewsMethod, args: <String, Object>{
jsonResponse: <String, Object>{ 'streamId': 'Isolate',
'views': <Object>[], }
),
FakeVmServiceStreamResponse(
streamId: 'Isolate',
event: vm_service.Event(
timestamp: 0,
kind: vm_service.EventKind.kIsolateRunnable,
)
),
FakeVmServiceStreamResponse(
streamId: 'Isolate',
event: vm_service.Event(
timestamp: 0,
kind: vm_service.EventKind.kIsolateRunnable,
)
),
FakeVmServiceRequest(
method: kRunInViewMethod,
args: <String, Object>{
'viewId': fakeFlutterView.id,
'mainScript': 'lib/main.dart.dill',
'assetDirectory': 'build/flutter_assets',
}
),
FakeVmServiceRequest(
method: kRunInViewMethod,
args: <String, Object>{
'viewId': fakeFlutterView.id,
'mainScript': 'lib/main.dart.dill',
'assetDirectory': 'build/flutter_assets',
} }
), ),
]); ]);
...@@ -257,25 +317,40 @@ void main() { ...@@ -257,25 +317,40 @@ void main() {
testUsingContext('hot restart supported', () async { testUsingContext('hot restart supported', () async {
// Setup mocks // Setup mocks
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
const FakeVmServiceRequest( listViews,
id: '1', FakeVmServiceRequest(
method: kListViewsMethod, method: 'getIsolate',
jsonResponse: <String, Object>{ args: <String, Object>{
'views': <Object>[], 'isolateId': fakeUnpausedIsolate.id,
} },
jsonResponse: fakeUnpausedIsolate.toJson(),
), ),
FakeVmServiceRequest( FakeVmServiceRequest(
id: '2',
method: 'getVM', method: 'getVM',
jsonResponse: vm_service.VM.parse(<String, Object>{}).toJson() jsonResponse: vm_service.VM.parse(<String, Object>{}).toJson(),
), ),
listViews,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '3', method: 'streamListen',
method: kListViewsMethod, args: <String, Object>{
jsonResponse: <String, Object>{ 'streamId': 'Isolate',
'views': <Object>[], }
),
FakeVmServiceRequest(
method: kRunInViewMethod,
args: <String, Object>{
'viewId': fakeFlutterView.id,
'mainScript': 'lib/main.dart.dill',
'assetDirectory': 'build/flutter_assets',
} }
), ),
FakeVmServiceStreamResponse(
streamId: 'Isolate',
event: vm_service.Event(
timestamp: 0,
kind: vm_service.EventKind.kIsolateRunnable,
)
),
]); ]);
final MockDevice mockDevice = MockDevice(); final MockDevice mockDevice = MockDevice();
when(mockDevice.supportsHotReload).thenReturn(true); when(mockDevice.supportsHotReload).thenReturn(true);
......
...@@ -36,14 +36,12 @@ import '../src/testbed.dart'; ...@@ -36,14 +36,12 @@ import '../src/testbed.dart';
const List<VmServiceExpectation> kAttachLogExpectations = <VmServiceExpectation>[ const List<VmServiceExpectation> kAttachLogExpectations = <VmServiceExpectation>[
FakeVmServiceRequest( FakeVmServiceRequest(
id: '1',
method: 'streamListen', method: 'streamListen',
args: <String, Object>{ args: <String, Object>{
'streamId': 'Stdout', 'streamId': 'Stdout',
}, },
), ),
FakeVmServiceRequest( FakeVmServiceRequest(
id: '2',
method: 'streamListen', method: 'streamListen',
args: <String, Object>{ args: <String, Object>{
'streamId': 'Stderr', 'streamId': 'Stderr',
...@@ -53,14 +51,12 @@ const List<VmServiceExpectation> kAttachLogExpectations = <VmServiceExpectation> ...@@ -53,14 +51,12 @@ const List<VmServiceExpectation> kAttachLogExpectations = <VmServiceExpectation>
const List<VmServiceExpectation> kAttachIsolateExpectations = <VmServiceExpectation>[ const List<VmServiceExpectation> kAttachIsolateExpectations = <VmServiceExpectation>[
FakeVmServiceRequest( FakeVmServiceRequest(
id: '3',
method: 'streamListen', method: 'streamListen',
args: <String, Object>{ args: <String, Object>{
'streamId': 'Isolate' 'streamId': 'Isolate'
} }
), ),
FakeVmServiceRequest( FakeVmServiceRequest(
id: '4',
method: 'registerService', method: 'registerService',
args: <String, Object>{ args: <String, Object>{
'service': 'reloadSources', 'service': 'reloadSources',
...@@ -362,7 +358,6 @@ void main() { ...@@ -362,7 +358,6 @@ void main() {
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
method: 'hotRestart', method: 'hotRestart',
id: '5',
jsonResponse: <String, Object>{ jsonResponse: <String, Object>{
'type': 'Success', 'type': 'Success',
} }
...@@ -439,7 +434,6 @@ void main() { ...@@ -439,7 +434,6 @@ void main() {
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
method: 'hotRestart', method: 'hotRestart',
id: '5',
jsonResponse: <String, Object>{ jsonResponse: <String, Object>{
'type': 'Success', 'type': 'Success',
} }
...@@ -670,7 +664,6 @@ void main() { ...@@ -670,7 +664,6 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5',
method: 'hotRestart', method: 'hotRestart',
jsonResponse: <String, Object>{ jsonResponse: <String, Object>{
'type': 'Failed', 'type': 'Failed',
...@@ -693,7 +686,6 @@ void main() { ...@@ -693,7 +686,6 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5',
method: 'hotRestart', method: 'hotRestart',
// Failed response, // Failed response,
errorCode: RPCErrorCodes.kInternalError, errorCode: RPCErrorCodes.kInternalError,
...@@ -725,7 +717,6 @@ void main() { ...@@ -725,7 +717,6 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5',
method: 'ext.flutter.debugDumpApp', method: 'ext.flutter.debugDumpApp',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -747,7 +738,6 @@ void main() { ...@@ -747,7 +738,6 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5',
method: 'ext.flutter.debugDumpLayerTree', method: 'ext.flutter.debugDumpLayerTree',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -769,7 +759,6 @@ void main() { ...@@ -769,7 +759,6 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5',
method: 'ext.flutter.debugDumpRenderTree', method: 'ext.flutter.debugDumpRenderTree',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -791,7 +780,6 @@ void main() { ...@@ -791,7 +780,6 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5',
method: 'ext.flutter.debugDumpSemanticsTreeInTraversalOrder', method: 'ext.flutter.debugDumpSemanticsTreeInTraversalOrder',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -813,7 +801,6 @@ void main() { ...@@ -813,7 +801,6 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5',
method: 'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder', method: 'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -836,7 +823,6 @@ void main() { ...@@ -836,7 +823,6 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5',
method: 'ext.flutter.debugPaint', method: 'ext.flutter.debugPaint',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -846,7 +832,6 @@ void main() { ...@@ -846,7 +832,6 @@ void main() {
}, },
), ),
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '6',
method: 'ext.flutter.debugPaint', method: 'ext.flutter.debugPaint',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -874,7 +859,6 @@ void main() { ...@@ -874,7 +859,6 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5',
method: 'ext.flutter.showPerformanceOverlay', method: 'ext.flutter.showPerformanceOverlay',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -884,7 +868,6 @@ void main() { ...@@ -884,7 +868,6 @@ void main() {
}, },
), ),
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '6',
method: 'ext.flutter.showPerformanceOverlay', method: 'ext.flutter.showPerformanceOverlay',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -911,7 +894,6 @@ void main() { ...@@ -911,7 +894,6 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5',
method: 'ext.flutter.inspector.show', method: 'ext.flutter.inspector.show',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -921,7 +903,6 @@ void main() { ...@@ -921,7 +903,6 @@ void main() {
}, },
), ),
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '6',
method: 'ext.flutter.inspector.show', method: 'ext.flutter.inspector.show',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -948,7 +929,6 @@ void main() { ...@@ -948,7 +929,6 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5',
method: 'ext.flutter.profileWidgetBuilds', method: 'ext.flutter.profileWidgetBuilds',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -958,7 +938,6 @@ void main() { ...@@ -958,7 +938,6 @@ void main() {
}, },
), ),
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '6',
method: 'ext.flutter.profileWidgetBuilds', method: 'ext.flutter.profileWidgetBuilds',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -985,7 +964,6 @@ void main() { ...@@ -985,7 +964,6 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachExpectations, ...kAttachExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '5',
method: 'ext.flutter.platformOverride', method: 'ext.flutter.platformOverride',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -995,7 +973,6 @@ void main() { ...@@ -995,7 +973,6 @@ void main() {
}, },
), ),
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '6',
method: 'ext.flutter.platformOverride', method: 'ext.flutter.platformOverride',
args: <String, Object>{ args: <String, Object>{
'isolateId': null, 'isolateId': null,
...@@ -1089,14 +1066,12 @@ void main() { ...@@ -1089,14 +1066,12 @@ void main() {
fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[ fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
...kAttachLogExpectations, ...kAttachLogExpectations,
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '3',
method: 'streamListen', method: 'streamListen',
args: <String, Object>{ args: <String, Object>{
'streamId': 'Isolate' 'streamId': 'Isolate'
} }
), ),
const FakeVmServiceRequest( const FakeVmServiceRequest(
id: '4',
method: 'registerService', method: 'registerService',
args: <String, Object>{ args: <String, Object>{
'service': 'reloadSources', 'service': 'reloadSources',
......
...@@ -139,7 +139,9 @@ void main() { ...@@ -139,7 +139,9 @@ void main() {
final MockFlutterDevice mockFlutterDevice = MockFlutterDevice(); final MockFlutterDevice mockFlutterDevice = MockFlutterDevice();
when(mockResidentRunner.isRunningDebug).thenReturn(true); when(mockResidentRunner.isRunningDebug).thenReturn(true);
when(mockResidentRunner.flutterDevices).thenReturn(<FlutterDevice>[mockFlutterDevice]); when(mockResidentRunner.flutterDevices).thenReturn(<FlutterDevice>[mockFlutterDevice]);
when(mockFlutterDevice.views).thenReturn(<FlutterView>[]); when(mockResidentRunner.listFlutterViews()).thenAnswer((Invocation invocation) async {
return <FlutterView>[];
});
await terminalHandler.processTerminalInput('l'); await terminalHandler.processTerminalInput('l');
......
...@@ -231,10 +231,10 @@ void main() { ...@@ -231,10 +231,10 @@ void main() {
testWithoutContext('runInView forwards arguments correctly', () async { testWithoutContext('runInView forwards arguments correctly', () async {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost( final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[ requests: <VmServiceExpectation>[
const FakeVmServiceRequest(method: 'streamListen', id: '1', args: <String, Object>{ const FakeVmServiceRequest(method: 'streamListen', args: <String, Object>{
'streamId': 'Isolate' 'streamId': 'Isolate'
}), }),
const FakeVmServiceRequest(method: kRunInViewMethod, id: '2', args: <String, Object>{ const FakeVmServiceRequest(method: kRunInViewMethod, args: <String, Object>{
'viewId': '1234', 'viewId': '1234',
'mainScript': 'main.dart', 'mainScript': 'main.dart',
'assetDirectory': 'flutter_assets/', 'assetDirectory': 'flutter_assets/',
...@@ -256,6 +256,65 @@ void main() { ...@@ -256,6 +256,65 @@ void main() {
); );
expect(fakeVmServiceHost.hasRemainingExpectations, false); expect(fakeVmServiceHost.hasRemainingExpectations, false);
}); });
testWithoutContext('getFlutterViews polls until a view is returned', () async {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[
const FakeVmServiceRequest(
method: kListViewsMethod,
jsonResponse: <String, Object>{
'views': <Object>[],
},
),
const FakeVmServiceRequest(
method: kListViewsMethod,
jsonResponse: <String, Object>{
'views': <Object>[],
},
),
const FakeVmServiceRequest(
method: kListViewsMethod,
jsonResponse: <String, Object>{
'views': <Object>[
<String, Object>{
'id': 'a',
'isolate': <String, Object>{},
},
],
},
),
]
);
expect(
await fakeVmServiceHost.vmService.getFlutterViews(
delay: Duration.zero,
),
isNotEmpty,
);
expect(fakeVmServiceHost.hasRemainingExpectations, false);
});
testWithoutContext('getFlutterViews does not poll if returnEarly is true', () async {
final FakeVmServiceHost fakeVmServiceHost = FakeVmServiceHost(
requests: <VmServiceExpectation>[
const FakeVmServiceRequest(
method: kListViewsMethod,
jsonResponse: <String, Object>{
'views': <Object>[],
},
),
]
);
expect(
await fakeVmServiceHost.vmService.getFlutterViews(
returnEarly: true,
),
isEmpty,
);
expect(fakeVmServiceHost.hasRemainingExpectations, false);
});
} }
class MockDevice extends Mock implements Device {} class MockDevice extends Mock implements Device {}
......
...@@ -76,7 +76,7 @@ void main() { ...@@ -76,7 +76,7 @@ void main() {
expect(chromeDevice.supportsHotReload, true); expect(chromeDevice.supportsHotReload, true);
expect(chromeDevice.supportsHotRestart, true); expect(chromeDevice.supportsHotRestart, true);
expect(chromeDevice.supportsStartPaused, true); expect(chromeDevice.supportsStartPaused, true);
expect(chromeDevice.supportsFlutterExit, true); expect(chromeDevice.supportsFlutterExit, false);
expect(chromeDevice.supportsScreenshot, false); expect(chromeDevice.supportsScreenshot, false);
expect(await chromeDevice.isLocalEmulator, false); expect(await chromeDevice.isLocalEmulator, false);
expect(chromeDevice.getLogReader(), isA<NoOpDeviceLogReader>()); expect(chromeDevice.getLogReader(), isA<NoOpDeviceLogReader>());
...@@ -96,7 +96,7 @@ void main() { ...@@ -96,7 +96,7 @@ void main() {
expect(chromeDevice.supportsHotReload, true); expect(chromeDevice.supportsHotReload, true);
expect(chromeDevice.supportsHotRestart, true); expect(chromeDevice.supportsHotRestart, true);
expect(chromeDevice.supportsStartPaused, true); expect(chromeDevice.supportsStartPaused, true);
expect(chromeDevice.supportsFlutterExit, true); expect(chromeDevice.supportsFlutterExit, false);
expect(chromeDevice.supportsScreenshot, false); expect(chromeDevice.supportsScreenshot, false);
expect(await chromeDevice.isLocalEmulator, false); expect(await chromeDevice.isLocalEmulator, false);
expect(chromeDevice.getLogReader(), isA<NoOpDeviceLogReader>()); expect(chromeDevice.getLogReader(), isA<NoOpDeviceLogReader>());
...@@ -114,7 +114,7 @@ void main() { ...@@ -114,7 +114,7 @@ void main() {
expect(device.supportsHotReload, true); expect(device.supportsHotReload, true);
expect(device.supportsHotRestart, true); expect(device.supportsHotRestart, true);
expect(device.supportsStartPaused, true); expect(device.supportsStartPaused, true);
expect(device.supportsFlutterExit, true); expect(device.supportsFlutterExit, false);
expect(device.supportsScreenshot, false); expect(device.supportsScreenshot, false);
expect(await device.isLocalEmulator, false); expect(await device.isLocalEmulator, false);
expect(device.getLogReader(), isA<NoOpDeviceLogReader>()); expect(device.getLogReader(), isA<NoOpDeviceLogReader>());
......
...@@ -239,7 +239,6 @@ class FakeVmServiceHost { ...@@ -239,7 +239,6 @@ class FakeVmServiceHost {
final FakeVmServiceRequest fakeRequest = _requests.removeAt(0) as FakeVmServiceRequest; final FakeVmServiceRequest fakeRequest = _requests.removeAt(0) as FakeVmServiceRequest;
expect(request, isA<Map<String, Object>>() expect(request, isA<Map<String, Object>>()
.having((Map<String, Object> request) => request['method'], 'method', fakeRequest.method) .having((Map<String, Object> request) => request['method'], 'method', fakeRequest.method)
.having((Map<String, Object> request) => request['id'], 'id', fakeRequest.id)
.having((Map<String, Object> request) => request['params'], 'args', fakeRequest.args) .having((Map<String, Object> request) => request['params'], 'args', fakeRequest.args)
); );
if (fakeRequest.close) { if (fakeRequest.close) {
...@@ -250,13 +249,13 @@ class FakeVmServiceHost { ...@@ -250,13 +249,13 @@ class FakeVmServiceHost {
if (fakeRequest.errorCode == null) { if (fakeRequest.errorCode == null) {
_input.add(json.encode(<String, Object>{ _input.add(json.encode(<String, Object>{
'jsonrpc': '2.0', 'jsonrpc': '2.0',
'id': fakeRequest.id, 'id': request['id'],
'result': fakeRequest.jsonResponse ?? <String, Object>{'type': 'Success'}, 'result': fakeRequest.jsonResponse ?? <String, Object>{'type': 'Success'},
})); }));
} else { } else {
_input.add(json.encode(<String, Object>{ _input.add(json.encode(<String, Object>{
'jsonrpc': '2.0', 'jsonrpc': '2.0',
'id': fakeRequest.id, 'id': request['id'],
'error': <String, Object>{ 'error': <String, Object>{
'code': fakeRequest.errorCode, 'code': fakeRequest.errorCode,
} }
...@@ -299,7 +298,6 @@ abstract class VmServiceExpectation { ...@@ -299,7 +298,6 @@ abstract class VmServiceExpectation {
class FakeVmServiceRequest implements VmServiceExpectation { class FakeVmServiceRequest implements VmServiceExpectation {
const FakeVmServiceRequest({ const FakeVmServiceRequest({
@required this.method, @required this.method,
@required this.id,
this.args = const <String, Object>{}, this.args = const <String, Object>{},
this.jsonResponse, this.jsonResponse,
this.errorCode, this.errorCode,
...@@ -307,7 +305,6 @@ class FakeVmServiceRequest implements VmServiceExpectation { ...@@ -307,7 +305,6 @@ class FakeVmServiceRequest implements VmServiceExpectation {
}); });
final String method; final String method;
final String id;
/// When true, the vm service is automatically closed. /// When true, the vm service is automatically closed.
final bool close; final bool close;
......
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