Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
9202e547
Unverified
Commit
9202e547
authored
Apr 20, 2020
by
Jonah Williams
Committed by
GitHub
Apr 20, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tools] move service extensions off of deprecated vm service (#55012)
parent
96a3b2ae
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1154 additions
and
654 deletions
+1154
-654
resident_web_runner.dart
...utter_tools/lib/src/build_runner/resident_web_runner.dart
+58
-72
device.dart
packages/flutter_tools/lib/src/device.dart
+3
-3
devices.dart
packages/flutter_tools/lib/src/ios/devices.dart
+4
-5
resident_runner.dart
packages/flutter_tools/lib/src/resident_runner.dart
+79
-29
run_cold.dart
packages/flutter_tools/lib/src/run_cold.dart
+4
-4
run_hot.dart
packages/flutter_tools/lib/src/run_hot.dart
+30
-23
tracing.dart
packages/flutter_tools/lib/src/tracing.dart
+4
-1
vmservice.dart
packages/flutter_tools/lib/src/vmservice.dart
+221
-156
attach_test.dart
...utter_tools/test/commands.shard/hermetic/attach_test.dart
+24
-6
resident_runner_test.dart
...lutter_tools/test/general.shard/resident_runner_test.dart
+223
-67
resident_web_runner_test.dart
...er_tools/test/general.shard/resident_web_runner_test.dart
+393
-195
vmservice_test.dart
...ages/flutter_tools/test/general.shard/vmservice_test.dart
+2
-92
common.dart
packages/flutter_tools/test/src/common.dart
+109
-1
No files found.
packages/flutter_tools/lib/src/build_runner/resident_web_runner.dart
View file @
9202e547
...
...
@@ -34,6 +34,7 @@ import '../project.dart';
import
'../reporting/reporting.dart'
;
import
'../resident_runner.dart'
;
import
'../run_hot.dart'
;
import
'../vmservice.dart'
;
import
'../web/chrome.dart'
;
import
'../web/compile.dart'
;
import
'../web/web_device.dart'
;
...
...
@@ -195,9 +196,10 @@ abstract class ResidentWebRunner extends ResidentRunner {
@override
Future
<
void
>
debugDumpApp
()
async
{
try
{
await
_vmService
?.
callServiceExtension
(
'ext.flutter.debugDumpApp'
,
);
await
_vmService
?.
flutterDebugDumpApp
(
isolateId:
null
,
);
}
on
vmservice
.
RPCError
{
return
;
}
...
...
@@ -206,9 +208,10 @@ abstract class ResidentWebRunner extends ResidentRunner {
@override
Future
<
void
>
debugDumpRenderTree
()
async
{
try
{
await
_vmService
?.
callServiceExtension
(
'ext.flutter.debugDumpRenderTree'
,
);
await
_vmService
?.
flutterDebugDumpRenderTree
(
isolateId:
null
,
);
}
on
vmservice
.
RPCError
{
return
;
}
...
...
@@ -217,9 +220,10 @@ abstract class ResidentWebRunner extends ResidentRunner {
@override
Future
<
void
>
debugDumpLayerTree
()
async
{
try
{
await
_vmService
?.
callServiceExtension
(
'ext.flutter.debugDumpLayerTree'
,
);
await
_vmService
?.
flutterDebugDumpLayerTree
(
isolateId:
null
,
);
}
on
vmservice
.
RPCError
{
return
;
}
...
...
@@ -228,8 +232,10 @@ abstract class ResidentWebRunner extends ResidentRunner {
@override
Future
<
void
>
debugDumpSemanticsTreeInTraversalOrder
()
async
{
try
{
await
_vmService
?.
callServiceExtension
(
'ext.flutter.debugDumpSemanticsTreeInTraversalOrder'
);
await
_vmService
?.
flutterDebugDumpSemanticsTreeInTraversalOrder
(
isolateId:
null
,
);
}
on
vmservice
.
RPCError
{
return
;
}
...
...
@@ -238,14 +244,16 @@ abstract class ResidentWebRunner extends ResidentRunner {
@override
Future
<
void
>
debugTogglePlatform
()
async
{
try
{
final
vmservice
.
Response
response
=
await
_vmService
?.
callServiceExtension
(
'ext.flutter.platformOverride'
);
final
String
currentPlatform
=
response
.
json
[
'value'
]
as
String
;
final
String
currentPlatform
=
await
_vmService
?.
flutterPlatformOverride
(
isolateId:
null
,
);
final
String
platform
=
nextPlatform
(
currentPlatform
,
featureFlags
);
await
_vmService
?.
callServiceExtension
(
'ext.flutter.platformOverride'
,
args:
<
String
,
Object
>{
'value'
:
platform
,
});
await
_vmService
?.
flutterPlatformOverride
(
platform:
platform
,
isolateId:
null
,
);
globals
.
printStatus
(
'Switched operating system to
$platform
'
);
}
on
vmservice
.
RPCError
{
return
;
...
...
@@ -261,8 +269,10 @@ abstract class ResidentWebRunner extends ResidentRunner {
@override
Future
<
void
>
debugDumpSemanticsTreeInInverseHitTestOrder
()
async
{
try
{
await
_vmService
?.
callServiceExtension
(
'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder'
);
await
_vmService
?.
flutterDebugDumpSemanticsTreeInInverseHitTestOrder
(
isolateId:
null
,
);
}
on
vmservice
.
RPCError
{
return
;
}
...
...
@@ -271,16 +281,10 @@ abstract class ResidentWebRunner extends ResidentRunner {
@override
Future
<
void
>
debugToggleDebugPaintSizeEnabled
()
async
{
try
{
final
vmservice
.
Response
response
=
await
_vmService
?.
callServiceExtension
(
'ext.flutter.debugPaint'
,
);
await
_vmService
?.
callServiceExtension
(
'ext.flutter.debugPaint'
,
args:
<
dynamic
,
dynamic
>{
'enabled'
:
!(
response
.
json
[
'enabled'
]
==
'true'
)
},
);
await
_vmService
?.
flutterToggleDebugPaintSizeEnabled
(
isolateId:
null
,
);
}
on
vmservice
.
RPCError
{
return
;
}
...
...
@@ -289,16 +293,10 @@ abstract class ResidentWebRunner extends ResidentRunner {
@override
Future
<
void
>
debugToggleDebugCheckElevationsEnabled
()
async
{
try
{
final
vmservice
.
Response
response
=
await
_vmService
?.
callServiceExtension
(
'ext.flutter.debugCheckElevationsEnabled'
,
);
await
_vmService
?.
callServiceExtension
(
'ext.flutter.debugCheckElevationsEnabled'
,
args:
<
dynamic
,
dynamic
>{
'enabled'
:
!(
response
.
json
[
'enabled'
]
==
'true'
)
},
);
await
_vmService
?.
flutterToggleDebugCheckElevationsEnabled
(
isolateId:
null
,
);
}
on
vmservice
.
RPCError
{
return
;
}
...
...
@@ -307,14 +305,10 @@ abstract class ResidentWebRunner extends ResidentRunner {
@override
Future
<
void
>
debugTogglePerformanceOverlayOverride
()
async
{
try
{
final
vmservice
.
Response
response
=
await
_vmService
?.
callServiceExtension
(
'ext.flutter.showPerformanceOverlay'
);
await
_vmService
?.
callServiceExtension
(
'ext.flutter.showPerformanceOverlay'
,
args:
<
dynamic
,
dynamic
>{
'enabled'
:
!(
response
.
json
[
'enabled'
]
==
'true'
)
},
);
await
_vmService
?.
flutterTogglePerformanceOverlayOverride
(
isolateId:
null
,
);
}
on
vmservice
.
RPCError
{
return
;
}
...
...
@@ -323,14 +317,10 @@ abstract class ResidentWebRunner extends ResidentRunner {
@override
Future
<
void
>
debugToggleWidgetInspector
()
async
{
try
{
final
vmservice
.
Response
response
=
await
_vmService
?.
callServiceExtension
(
'ext.flutter.debugToggleWidgetInspector'
);
await
_vmService
?.
callServiceExtension
(
'ext.flutter.debugToggleWidgetInspector'
,
args:
<
dynamic
,
dynamic
>{
'enabled'
:
!(
response
.
json
[
'enabled'
]
==
'true'
)
},
);
await
_vmService
?.
flutterToggleWidgetInspector
(
isolateId:
null
,
);
}
on
vmservice
.
RPCError
{
return
;
}
...
...
@@ -339,14 +329,10 @@ abstract class ResidentWebRunner extends ResidentRunner {
@override
Future
<
void
>
debugToggleProfileWidgetBuilds
()
async
{
try
{
final
vmservice
.
Response
response
=
await
_vmService
?.
callServiceExtension
(
'ext.flutter.profileWidgetBuilds'
);
await
_vmService
?.
callServiceExtension
(
'ext.flutter.profileWidgetBuilds'
,
args:
<
dynamic
,
dynamic
>{
'enabled'
:
!(
response
.
json
[
'enabled'
]
==
'true'
)
},
);
await
_vmService
?.
flutterToggleProfileWidgetBuilds
(
isolateId:
null
,
);
}
on
vmservice
.
RPCError
{
return
;
}
...
...
@@ -674,6 +660,14 @@ class _ResidentWebRunner extends ResidentWebRunner {
_connectionResult
=
await
webDevFS
.
connect
(
useDebugExtension
);
unawaited
(
_connectionResult
.
debugConnection
.
onDone
.
whenComplete
(
_cleanupAndExit
));
_stdOutSub
=
_vmService
.
onStdoutEvent
.
listen
((
vmservice
.
Event
log
)
{
final
String
message
=
utf8
.
decode
(
base64
.
decode
(
log
.
bytes
));
globals
.
printStatus
(
message
,
newline:
false
);
});
_stdErrSub
=
_vmService
.
onStderrEvent
.
listen
((
vmservice
.
Event
log
)
{
final
String
message
=
utf8
.
decode
(
base64
.
decode
(
log
.
bytes
));
globals
.
printStatus
(
message
,
newline:
false
);
});
try
{
await
_vmService
.
streamListen
(
vmservice
.
EventStreams
.
kStdout
);
}
on
vmservice
.
RPCError
{
...
...
@@ -692,14 +686,6 @@ class _ResidentWebRunner extends ResidentWebRunner {
// It is safe to ignore this error because we expect an error to be
// thrown if we're not already subscribed.
}
_stdOutSub
=
_vmService
.
onStdoutEvent
.
listen
((
vmservice
.
Event
log
)
{
final
String
message
=
utf8
.
decode
(
base64
.
decode
(
log
.
bytes
));
globals
.
printStatus
(
message
,
newline:
false
);
});
_stdErrSub
=
_vmService
.
onStderrEvent
.
listen
((
vmservice
.
Event
log
)
{
final
String
message
=
utf8
.
decode
(
base64
.
decode
(
log
.
bytes
));
globals
.
printStatus
(
message
,
newline:
false
);
});
unawaited
(
_vmService
.
registerService
(
'reloadSources'
,
'FlutterTools'
));
_vmService
.
registerServiceCallback
(
'reloadSources'
,
(
Map
<
String
,
Object
>
params
)
async
{
final
bool
pause
=
params
[
'pause'
]
as
bool
??
false
;
...
...
packages/flutter_tools/lib/src/device.dart
View file @
9202e547
...
...
@@ -6,6 +6,7 @@ import 'dart:async';
import
'dart:math'
as
math
;
import
'package:meta/meta.dart'
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
import
'android/android_device_discovery.dart'
;
import
'android/android_workflow.dart'
;
...
...
@@ -25,7 +26,6 @@ import 'linux/linux_device.dart';
import
'macos/macos_device.dart'
;
import
'project.dart'
;
import
'tester/flutter_tester.dart'
;
import
'vmservice.dart'
;
import
'web/web_device.dart'
;
import
'windows/windows_device.dart'
;
...
...
@@ -755,7 +755,7 @@ abstract class DeviceLogReader {
/// Some logs can be obtained from a VM service stream.
/// Set this after the VM services are connected.
VM
Service
connectedVMService
;
vm_service
.
Vm
Service
connectedVMService
;
@override
String
toString
()
=>
name
;
...
...
@@ -785,7 +785,7 @@ class NoOpDeviceLogReader implements DeviceLogReader {
int
appPid
;
@override
VM
Service
connectedVMService
;
vm_service
.
Vm
Service
connectedVMService
;
@override
Stream
<
String
>
get
logLines
=>
const
Stream
<
String
>.
empty
();
...
...
packages/flutter_tools/lib/src/ios/devices.dart
View file @
9202e547
...
...
@@ -24,7 +24,6 @@ import '../macos/xcode.dart';
import
'../mdns_discovery.dart'
;
import
'../project.dart'
;
import
'../protocol_discovery.dart'
;
import
'../vmservice.dart'
;
import
'fallback_discovery.dart'
;
import
'ios_deploy.dart'
;
import
'ios_workflow.dart'
;
...
...
@@ -561,18 +560,18 @@ class IOSDeviceLogReader extends DeviceLogReader {
Stream
<
String
>
get
logLines
=>
_linesController
.
stream
;
@override
VM
Service
get
connectedVMService
=>
_connectedVMService
;
VM
Service
_connectedVMService
;
vm_service
.
Vm
Service
get
connectedVMService
=>
_connectedVMService
;
vm_service
.
Vm
Service
_connectedVMService
;
@override
set
connectedVMService
(
VM
Service
connectedVmService
)
{
set
connectedVMService
(
vm_service
.
Vm
Service
connectedVmService
)
{
_listenToUnifiedLoggingEvents
(
connectedVmService
);
_connectedVMService
=
connectedVmService
;
}
static
const
int
_minimumUniversalLoggingSdkVersion
=
13
;
Future
<
void
>
_listenToUnifiedLoggingEvents
(
VM
Service
connectedVmService
)
async
{
Future
<
void
>
_listenToUnifiedLoggingEvents
(
vm_service
.
Vm
Service
connectedVmService
)
async
{
if
(
_majorSdkVersion
<
_minimumUniversalLoggingSdkVersion
)
{
return
;
}
...
...
packages/flutter_tools/lib/src/resident_runner.dart
View file @
9202e547
...
...
@@ -152,7 +152,7 @@ class FlutterDevice {
final
ResidentCompiler
generator
;
final
BuildInfo
buildInfo
;
Stream
<
Uri
>
observatoryUris
;
VM
Service
vmService
;
vm_service
.
Vm
Service
vmService
;
DevFS
devFS
;
ApplicationPackage
package
;
List
<
String
>
fileSystemRoots
;
...
...
@@ -226,24 +226,28 @@ class FlutterDevice {
return
completer
.
future
;
}
// TODO(jonahwilliams): remove once all callsites are updated.
VMService
get
flutterDeprecatedVmService
=>
vmService
as
VMService
;
Future
<
void
>
refreshViews
()
async
{
if
(
vmService
==
null
)
{
return
;
}
await
v
mService
.
vm
.
refreshViews
(
waitForViews:
true
);
await
flutterDeprecatedV
mService
.
vm
.
refreshViews
(
waitForViews:
true
);
}
List
<
FlutterView
>
get
views
{
if
(
vmService
==
null
||
v
mService
.
isClosed
)
{
if
(
vmService
==
null
||
flutterDeprecatedV
mService
.
isClosed
)
{
return
<
FlutterView
>[];
}
return
(
viewFilter
!=
null
?
v
mService
.
vm
.
allViewsWithName
(
viewFilter
)
:
v
mService
.
vm
.
views
).
toList
();
?
flutterDeprecatedV
mService
.
vm
.
allViewsWithName
(
viewFilter
)
:
flutterDeprecatedV
mService
.
vm
.
views
).
toList
();
}
Future
<
void
>
getVMs
()
=>
v
mService
.
getVMOld
();
Future
<
void
>
getVMs
()
=>
flutterDeprecatedV
mService
.
getVMOld
();
Future
<
void
>
exitApps
()
async
{
if
(!
device
.
supportsFlutterExit
)
{
...
...
@@ -270,7 +274,9 @@ class FlutterDevice {
for
(
final
FlutterView
view
in
flutterViews
)
{
if
(
view
!=
null
&&
view
.
uiIsolate
!=
null
)
{
assert
(!
view
.
uiIsolate
.
pauseEvent
.
isPauseEvent
);
futures
.
add
(
view
.
uiIsolate
.
flutterExit
());
futures
.
add
(
vmService
.
flutterExit
(
isolateId:
view
.
uiIsolate
.
id
,
));
}
}
// The flutterExit message only returns if it fails, so just wait a few
...
...
@@ -286,7 +292,7 @@ class FlutterDevice {
})
{
// One devFS per device. Shared by all running instances.
devFS
=
DevFS
(
v
mService
,
flutterDeprecatedV
mService
,
fsName
,
rootDirectory
,
osUtils:
globals
.
os
,
...
...
@@ -301,7 +307,7 @@ class FlutterDevice {
final
String
deviceEntryUri
=
devFS
.
baseUri
.
resolveUri
(
globals
.
fs
.
path
.
toUri
(
entryPath
)).
toString
();
return
<
Future
<
vm_service
.
ReloadReport
>>[
for
(
final
Isolate
isolate
in
v
mService
.
vm
.
isolates
)
for
(
final
Isolate
isolate
in
flutterDeprecatedV
mService
.
vm
.
isolates
)
vmService
.
reloadSources
(
isolate
.
id
,
pause:
pause
,
...
...
@@ -325,68 +331,91 @@ class FlutterDevice {
Future
<
void
>
debugDumpApp
()
async
{
for
(
final
FlutterView
view
in
views
)
{
await
view
.
uiIsolate
.
flutterDebugDumpApp
();
await
vmService
.
flutterDebugDumpApp
(
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
Future
<
void
>
debugDumpRenderTree
()
async
{
for
(
final
FlutterView
view
in
views
)
{
await
view
.
uiIsolate
.
flutterDebugDumpRenderTree
();
await
vmService
.
flutterDebugDumpRenderTree
(
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
Future
<
void
>
debugDumpLayerTree
()
async
{
for
(
final
FlutterView
view
in
views
)
{
await
view
.
uiIsolate
.
flutterDebugDumpLayerTree
();
await
vmService
.
flutterDebugDumpLayerTree
(
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
Future
<
void
>
debugDumpSemanticsTreeInTraversalOrder
()
async
{
for
(
final
FlutterView
view
in
views
)
{
await
view
.
uiIsolate
.
flutterDebugDumpSemanticsTreeInTraversalOrder
();
await
vmService
.
flutterDebugDumpSemanticsTreeInTraversalOrder
(
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
Future
<
void
>
debugDumpSemanticsTreeInInverseHitTestOrder
()
async
{
for
(
final
FlutterView
view
in
views
)
{
await
view
.
uiIsolate
.
flutterDebugDumpSemanticsTreeInInverseHitTestOrder
();
await
vmService
.
flutterDebugDumpSemanticsTreeInInverseHitTestOrder
(
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
Future
<
void
>
toggleDebugPaintSizeEnabled
()
async
{
for
(
final
FlutterView
view
in
views
)
{
await
view
.
uiIsolate
.
flutterToggleDebugPaintSizeEnabled
();
await
vmService
.
flutterToggleDebugPaintSizeEnabled
(
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
Future
<
void
>
toggleDebugCheckElevationsEnabled
()
async
{
for
(
final
FlutterView
view
in
views
)
{
await
view
.
uiIsolate
.
flutterToggleDebugCheckElevationsEnabled
();
await
vmService
.
flutterToggleDebugCheckElevationsEnabled
(
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
Future
<
void
>
debugTogglePerformanceOverlayOverride
()
async
{
for
(
final
FlutterView
view
in
views
)
{
await
view
.
uiIsolate
.
flutterTogglePerformanceOverlayOverride
();
await
vmService
.
flutterTogglePerformanceOverlayOverride
(
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
Future
<
void
>
toggleWidgetInspector
()
async
{
for
(
final
FlutterView
view
in
views
)
{
await
view
.
uiIsolate
.
flutterToggleWidgetInspector
();
await
vmService
.
flutterToggleWidgetInspector
(
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
Future
<
void
>
toggleProfileWidgetBuilds
()
async
{
for
(
final
FlutterView
view
in
views
)
{
await
view
.
uiIsolate
.
flutterToggleProfileWidgetBuilds
();
await
vmService
.
flutterToggleProfileWidgetBuilds
(
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
Future
<
String
>
togglePlatform
({
String
from
})
async
{
final
String
to
=
nextPlatform
(
from
,
featureFlags
);
for
(
final
FlutterView
view
in
views
)
{
await
view
.
uiIsolate
.
flutterPlatformOverride
(
to
);
await
vmService
.
flutterPlatformOverride
(
platform:
to
,
isolateId:
view
.
uiIsolate
.
id
,
);
}
return
to
;
}
...
...
@@ -416,7 +445,9 @@ class FlutterDevice {
}
Future
<
void
>
initLogReader
()
async
{
(
await
device
.
getLogReader
(
app:
package
)).
appPid
=
vmService
.
vm
.
pid
;
final
vm_service
.
VM
vm
=
await
vmService
.
getVM
();
final
DeviceLogReader
logReader
=
await
device
.
getLogReader
(
app:
package
);
logReader
.
appPid
=
vm
.
pid
;
}
Future
<
int
>
runHot
({
...
...
@@ -721,8 +752,16 @@ abstract class ResidentRunner {
String
method
,
{
Map
<
String
,
dynamic
>
params
,
})
{
return
flutterDevices
.
first
.
views
.
first
.
uiIsolate
.
invokeFlutterExtensionRpcRaw
(
method
,
params:
params
);
return
flutterDevices
.
first
.
vmService
.
invokeFlutterExtensionRpcRaw
(
method
,
args:
params
,
isolateId:
flutterDevices
.
first
.
views
.
first
.
uiIsolate
.
id
);
}
/// Whether this runner can hot reload.
...
...
@@ -812,7 +851,7 @@ abstract class ResidentRunner {
void
writeVmserviceFile
()
{
if
(
debuggingOptions
.
vmserviceOutFile
!=
null
)
{
try
{
final
String
address
=
flutterDevices
.
first
.
v
mService
.
wsAddress
.
toString
();
final
String
address
=
flutterDevices
.
first
.
flutterDeprecatedV
mService
.
wsAddress
.
toString
();
final
File
vmserviceOutFile
=
globals
.
fs
.
file
(
debuggingOptions
.
vmserviceOutFile
);
vmserviceOutFile
.
createSync
(
recursive:
true
);
vmserviceOutFile
.
writeAsStringSync
(
address
);
...
...
@@ -944,7 +983,10 @@ abstract class ResidentRunner {
await
device
.
refreshViews
();
try
{
for
(
final
FlutterView
view
in
device
.
views
)
{
await
view
.
uiIsolate
.
flutterDebugAllowBanner
(
false
);
await
device
.
vmService
.
flutterDebugAllowBanner
(
false
,
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
on
Exception
catch
(
error
)
{
status
.
cancel
();
...
...
@@ -958,7 +1000,10 @@ abstract class ResidentRunner {
if
(
supportsServiceProtocol
&&
isRunningDebug
)
{
try
{
for
(
final
FlutterView
view
in
device
.
views
)
{
await
view
.
uiIsolate
.
flutterDebugAllowBanner
(
true
);
await
device
.
vmService
.
flutterDebugAllowBanner
(
true
,
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
on
Exception
catch
(
error
)
{
status
.
cancel
();
...
...
@@ -980,7 +1025,12 @@ abstract class ResidentRunner {
Future
<
void
>
debugTogglePlatform
()
async
{
await
refreshViews
();
final
String
from
=
await
flutterDevices
[
0
].
views
[
0
].
uiIsolate
.
flutterPlatformOverride
();
final
String
isolateId
=
flutterDevices
.
first
.
views
.
first
.
uiIsolate
.
id
;
final
String
from
=
await
flutterDevices
.
first
.
vmService
.
flutterPlatformOverride
(
isolateId:
isolateId
,
);
String
to
;
for
(
final
FlutterDevice
device
in
flutterDevices
)
{
to
=
await
device
.
togglePlatform
(
from:
from
);
...
...
@@ -1039,7 +1089,7 @@ abstract class ResidentRunner {
// This hooks up callbacks for when the connection stops in the future.
// We don't want to wait for them. We don't handle errors in those callbacks'
// futures either because they just print to logger and is not critical.
unawaited
(
device
.
vmService
.
d
one
.
then
<
void
>(
unawaited
(
device
.
vmService
.
onD
one
.
then
<
void
>(
_serviceProtocolDone
,
onError:
_serviceProtocolError
,
).
whenComplete
(
_serviceDisconnected
));
...
...
@@ -1056,7 +1106,7 @@ abstract class ResidentRunner {
<
String
,
dynamic
>{
'reuseWindows'
:
true
,
},
flutterDevices
.
first
.
v
mService
.
httpAddress
,
flutterDevices
.
first
.
flutterDeprecatedV
mService
.
httpAddress
,
'http://
${_devtoolsServer.address.host}
:
${_devtoolsServer.port}
'
,
false
,
// headless mode,
false
,
// machine mode
...
...
packages/flutter_tools/lib/src/run_cold.dart
View file @
9202e547
...
...
@@ -83,8 +83,8 @@ class ColdRunner extends ResidentRunner {
if
(
flutterDevices
.
first
.
observatoryUris
!=
null
)
{
// For now, only support one debugger connection.
connectionInfoCompleter
?.
complete
(
DebugConnectionInfo
(
httpUri:
flutterDevices
.
first
.
v
mService
.
httpAddress
,
wsUri:
flutterDevices
.
first
.
v
mService
.
wsAddress
,
httpUri:
flutterDevices
.
first
.
flutterDeprecatedV
mService
.
httpAddress
,
wsUri:
flutterDevices
.
first
.
flutterDeprecatedV
mService
.
wsAddress
,
));
}
...
...
@@ -105,7 +105,7 @@ class ColdRunner extends ResidentRunner {
if
(
device
.
vmService
!=
null
)
{
globals
.
printStatus
(
'Tracing startup on
${device.device.name}
.'
);
await
downloadStartupTrace
(
device
.
v
mService
,
device
.
flutterDeprecatedV
mService
,
awaitFirstFrame:
awaitFirstFrameWhenTracing
,
);
}
...
...
@@ -197,7 +197,7 @@ class ColdRunner extends ResidentRunner {
// Caution: This log line is parsed by device lab tests.
globals
.
printStatus
(
'An Observatory debugger and profiler on
$dname
is available at: '
'
${device.
v
mService.httpAddress}
'
,
'
${device.
flutterDeprecatedV
mService.httpAddress}
'
,
);
}
}
...
...
packages/flutter_tools/lib/src/run_hot.dart
View file @
9202e547
...
...
@@ -205,7 +205,10 @@ class HotRunner extends ResidentRunner {
for
(
final
FlutterDevice
device
in
flutterDevices
)
{
for
(
final
FlutterView
view
in
device
.
views
)
{
await
view
.
uiIsolate
.
flutterFastReassemble
(
classId
);
await
device
.
vmService
.
flutterFastReassemble
(
classId
,
isolateId:
view
.
uiIsolate
.
id
,
);
}
}
...
...
@@ -260,8 +263,8 @@ class HotRunner extends ResidentRunner {
// Only handle one debugger connection.
connectionInfoCompleter
.
complete
(
DebugConnectionInfo
(
httpUri:
flutterDevices
.
first
.
v
mService
.
httpAddress
,
wsUri:
flutterDevices
.
first
.
v
mService
.
wsAddress
,
httpUri:
flutterDevices
.
first
.
flutterDeprecatedV
mService
.
httpAddress
,
wsUri:
flutterDevices
.
first
.
flutterDeprecatedV
mService
.
wsAddress
,
baseUri:
baseUris
.
first
.
toString
(),
),
);
...
...
@@ -570,7 +573,7 @@ class HotRunner extends ResidentRunner {
// The engine handles killing and recreating isolates that it has spawned
// ("uiIsolates"). The isolates that were spawned from these uiIsolates
// will not be restared, and so they must be manually killed.
for
(
final
Isolate
isolate
in
device
?.
v
mService
?.
vm
?.
isolates
??
<
Isolate
>[])
{
for
(
final
Isolate
isolate
in
device
?.
flutterDeprecatedV
mService
?.
vm
?.
isolates
??
<
Isolate
>[])
{
if
(!
uiIsolates
.
contains
(
isolate
))
{
operations
.
add
(
isolate
.
invokeRpcRaw
(
'kill'
,
params:
<
String
,
dynamic
>{
'isolateId'
:
isolate
.
id
,
...
...
@@ -938,10 +941,16 @@ class HotRunner extends ResidentRunner {
}
await
Future
.
wait
(
allDevices
);
// Check if any isolates are paused.
globals
.
printTrace
(
'Evicting dirty assets'
);
await
_evictDirtyAssets
();
// Check if any isolates are paused and reassemble those
// that aren't.
final
List
<
FlutterView
>
reassembleViews
=
<
FlutterView
>[];
final
List
<
Future
<
void
>>
reassembleFutures
=
<
Future
<
void
>>[];
String
serviceEventKind
;
int
pausedIsolatesFound
=
0
;
bool
failedReassemble
=
false
;
for
(
final
FlutterDevice
device
in
flutterDevices
)
{
for
(
final
FlutterView
view
in
device
.
views
)
{
// Check if the isolate is paused, and if so, don't reassemble. Ignore the
...
...
@@ -956,6 +965,12 @@ class HotRunner extends ResidentRunner {
}
}
else
{
reassembleViews
.
add
(
view
);
reassembleFutures
.
add
(
device
.
vmService
.
flutterReassemble
(
isolateId:
view
.
uiIsolate
.
id
,
).
catchError
((
dynamic
error
)
{
failedReassemble
=
true
;
globals
.
printError
(
'Reassembling
${view.uiIsolate.name}
failed:
$error
'
);
},
test:
(
dynamic
error
)
=>
error
is
Exception
));
}
}
}
...
...
@@ -968,24 +983,10 @@ class HotRunner extends ResidentRunner {
return
OperationResult
(
OperationResult
.
ok
.
code
,
reloadMessage
);
}
}
globals
.
printTrace
(
'Evicting dirty assets'
);
await
_evictDirtyAssets
();
assert
(
reassembleViews
.
isNotEmpty
);
globals
.
printTrace
(
'Reassembling application'
);
bool
failedReassemble
=
false
;
final
List
<
Future
<
void
>>
futures
=
<
Future
<
void
>>[
for
(
final
FlutterView
view
in
reassembleViews
)
()
async
{
try
{
await
view
.
uiIsolate
.
flutterReassemble
();
}
on
Exception
catch
(
error
)
{
failedReassemble
=
true
;
globals
.
printError
(
'Reassembling
${view.uiIsolate.name}
failed:
$error
'
);
return
;
}
}(),
];
final
Future
<
void
>
reassembleFuture
=
Future
.
wait
<
void
>(
futures
);
final
Future
<
void
>
reassembleFuture
=
Future
.
wait
<
void
>(
reassembleFutures
);
await
reassembleFuture
.
timeout
(
const
Duration
(
seconds:
2
),
onTimeout:
()
async
{
...
...
@@ -1128,7 +1129,7 @@ class HotRunner extends ResidentRunner {
// Caution: This log line is parsed by device lab tests.
globals
.
printStatus
(
'An Observatory debugger and profiler on
$dname
is available at: '
'
${device.
v
mService.httpAddress}
'
,
'
${device.
flutterDeprecatedV
mService.httpAddress}
'
,
);
}
}
...
...
@@ -1144,7 +1145,13 @@ class HotRunner extends ResidentRunner {
continue
;
}
for
(
final
String
assetPath
in
device
.
devFS
.
assetPathsToEvict
)
{
futures
.
add
(
device
.
views
.
first
.
uiIsolate
.
flutterEvictAsset
(
assetPath
));
futures
.
add
(
device
.
views
.
first
.
uiIsolate
.
vmService
.
flutterEvictAsset
(
assetPath
,
isolateId:
device
.
views
.
first
.
uiIsolate
.
id
,
)
);
}
device
.
devFS
.
assetPathsToEvict
.
clear
();
}
...
...
packages/flutter_tools/lib/src/tracing.dart
View file @
9202e547
...
...
@@ -54,7 +54,10 @@ class Tracing {
});
bool
done
=
false
;
for
(
final
FlutterView
view
in
vmService
.
vm
.
views
)
{
if
(
await
view
.
uiIsolate
.
flutterAlreadyPaintedFirstUsefulFrame
())
{
if
(
await
view
.
uiIsolate
.
vmService
.
flutterAlreadyPaintedFirstUsefulFrame
(
isolateId:
view
.
uiIsolate
.
id
,
))
{
done
=
true
;
break
;
}
...
...
packages/flutter_tools/lib/src/vmservice.dart
View file @
9202e547
...
...
@@ -3,7 +3,6 @@
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:math'
as
math
;
import
'package:meta/meta.dart'
show
required
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
...
...
@@ -476,6 +475,18 @@ class VMService implements vm_service.VmService {
return
_delegateService
.
callMethod
(
method
,
isolateId:
isolateId
,
args:
args
);
}
@override
Future
<
void
>
get
onDone
=>
_delegateService
.
onDone
;
@override
Future
<
vm_service
.
Response
>
callServiceExtension
(
String
method
,
{
String
isolateId
,
Map
<
Object
,
Object
>
args
})
{
return
_delegateService
.
callServiceExtension
(
method
,
isolateId:
isolateId
,
args:
args
);
}
@override
Future
<
vm_service
.
VM
>
getVM
()
=>
_delegateService
.
getVM
();
StreamController
<
ServiceEvent
>
_getEventController
(
String
eventName
)
{
StreamController
<
ServiceEvent
>
controller
=
_eventControllers
[
eventName
];
if
(
controller
==
null
)
{
...
...
@@ -890,7 +901,6 @@ class VM extends ServiceObjectOwner {
_upgradeCollection
(
map
,
this
);
_loaded
=
true
;
_pid
=
map
[
'pid'
]
as
int
;
if
(
map
[
'_heapAllocatedMemoryUsage'
]
!=
null
)
{
_heapAllocatedMemoryUsage
=
map
[
'_heapAllocatedMemoryUsage'
]
as
int
;
}
...
...
@@ -910,10 +920,6 @@ class VM extends ServiceObjectOwner {
/// The set of live views.
final
Map
<
String
,
FlutterView
>
_viewCache
=
<
String
,
FlutterView
>{};
/// The pid of the VM's process.
int
_pid
;
int
get
pid
=>
_pid
;
/// The number of bytes allocated (e.g. by malloc) in the native heap.
int
_heapAllocatedMemoryUsage
;
int
get
heapAllocatedMemoryUsage
=>
_heapAllocatedMemoryUsage
??
0
;
...
...
@@ -1131,44 +1137,6 @@ class VM extends ServiceObjectOwner {
}
}
class
HeapSpace
extends
ServiceObject
{
HeapSpace
.
_empty
(
ServiceObjectOwner
owner
)
:
super
.
_empty
(
owner
);
int
_used
=
0
;
int
_capacity
=
0
;
int
_external
=
0
;
int
_collections
=
0
;
double
_totalCollectionTimeInSeconds
=
0.0
;
double
_averageCollectionPeriodInMillis
=
0.0
;
int
get
used
=>
_used
;
int
get
capacity
=>
_capacity
;
int
get
external
=>
_external
;
Duration
get
avgCollectionTime
{
final
double
mcs
=
_totalCollectionTimeInSeconds
*
Duration
.
microsecondsPerSecond
/
math
.
max
(
_collections
,
1
);
return
Duration
(
microseconds:
mcs
.
ceil
());
}
Duration
get
avgCollectionPeriod
{
final
double
mcs
=
_averageCollectionPeriodInMillis
*
Duration
.
microsecondsPerMillisecond
;
return
Duration
(
microseconds:
mcs
.
ceil
());
}
@override
void
_update
(
Map
<
String
,
dynamic
>
map
,
bool
mapIsRef
)
{
_used
=
map
[
'used'
]
as
int
;
_capacity
=
map
[
'capacity'
]
as
int
;
_external
=
map
[
'external'
]
as
int
;
_collections
=
map
[
'collections'
]
as
int
;
_totalCollectionTimeInSeconds
=
map
[
'time'
]
as
double
;
_averageCollectionPeriodInMillis
=
map
[
'avgCollectionPeriodMillis'
]
as
double
;
}
}
/// An isolate running inside the VM. Instances of the Isolate class are always
/// canonicalized.
class
Isolate
extends
ServiceObjectOwner
{
...
...
@@ -1250,118 +1218,6 @@ class Isolate extends ServiceObjectOwner {
pauseEvent
=
map
[
'pauseEvent'
]
as
ServiceEvent
;
}
// Flutter extension methods.
// Invoke a flutter extension method, if the flutter extension is not
// available, returns null.
Future
<
Map
<
String
,
dynamic
>>
invokeFlutterExtensionRpcRaw
(
String
method
,
{
Map
<
String
,
dynamic
>
params
,
})
async
{
try
{
return
await
invokeRpcRaw
(
method
,
params:
params
);
}
on
vm_service
.
RPCError
catch
(
err
)
{
// If an application is not using the framework
if
(
err
.
code
==
RPCErrorCodes
.
kMethodNotFound
)
{
return
null
;
}
rethrow
;
}
}
Future
<
Map
<
String
,
dynamic
>>
flutterDebugDumpApp
()
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugDumpApp'
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterDebugDumpRenderTree
()
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugDumpRenderTree'
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterDebugDumpLayerTree
()
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugDumpLayerTree'
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterDebugDumpSemanticsTreeInTraversalOrder
()
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugDumpSemanticsTreeInTraversalOrder'
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterDebugDumpSemanticsTreeInInverseHitTestOrder
()
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder'
);
}
Future
<
Map
<
String
,
dynamic
>>
_flutterToggle
(
String
name
)
async
{
Map
<
String
,
dynamic
>
state
=
await
invokeFlutterExtensionRpcRaw
(
'ext.flutter.
$name
'
);
if
(
state
!=
null
&&
state
.
containsKey
(
'enabled'
)
&&
state
[
'enabled'
]
is
String
)
{
state
=
await
invokeFlutterExtensionRpcRaw
(
'ext.flutter.
$name
'
,
params:
<
String
,
dynamic
>{
'enabled'
:
state
[
'enabled'
]
==
'true'
?
'false'
:
'true'
},
);
}
return
state
;
}
Future
<
Map
<
String
,
dynamic
>>
flutterToggleDebugPaintSizeEnabled
()
=>
_flutterToggle
(
'debugPaint'
);
Future
<
Map
<
String
,
dynamic
>>
flutterToggleDebugCheckElevationsEnabled
()
=>
_flutterToggle
(
'debugCheckElevationsEnabled'
);
Future
<
Map
<
String
,
dynamic
>>
flutterTogglePerformanceOverlayOverride
()
=>
_flutterToggle
(
'showPerformanceOverlay'
);
Future
<
Map
<
String
,
dynamic
>>
flutterToggleWidgetInspector
()
=>
_flutterToggle
(
'inspector.show'
);
Future
<
Map
<
String
,
dynamic
>>
flutterToggleProfileWidgetBuilds
()
=>
_flutterToggle
(
'profileWidgetBuilds'
);
Future
<
Map
<
String
,
dynamic
>>
flutterDebugAllowBanner
(
bool
show
)
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugAllowBanner'
,
params:
<
String
,
dynamic
>{
'enabled'
:
show
?
'true'
:
'false'
},
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterReassemble
()
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.reassemble'
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterFastReassemble
(
String
classId
)
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.fastReassemble'
,
params:
<
String
,
Object
>{
'class'
:
classId
,
});
}
Future
<
bool
>
flutterAlreadyPaintedFirstUsefulFrame
()
async
{
final
Map
<
String
,
dynamic
>
result
=
await
invokeFlutterExtensionRpcRaw
(
'ext.flutter.didSendFirstFrameRasterizedEvent'
);
// result might be null when the service extension is not initialized
return
result
!=
null
&&
result
[
'enabled'
]
==
'true'
;
}
Future
<
Map
<
String
,
dynamic
>>
uiWindowScheduleFrame
()
{
return
invokeFlutterExtensionRpcRaw
(
'ext.ui.window.scheduleFrame'
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterEvictAsset
(
String
assetPath
)
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.evict'
,
params:
<
String
,
dynamic
>{
'value'
:
assetPath
,
},
);
}
// Application control extension methods.
Future
<
Map
<
String
,
dynamic
>>
flutterExit
()
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.exit'
);
}
Future
<
String
>
flutterPlatformOverride
([
String
platform
])
async
{
final
Map
<
String
,
dynamic
>
result
=
await
invokeFlutterExtensionRpcRaw
(
'ext.flutter.platformOverride'
,
params:
platform
!=
null
?
<
String
,
dynamic
>{
'value'
:
platform
}
:
<
String
,
String
>{},
);
if
(
result
!=
null
&&
result
[
'value'
]
is
String
)
{
return
result
[
'value'
]
as
String
;
}
return
'unknown'
;
}
@override
String
toString
()
=>
'Isolate
$id
'
;
}
...
...
@@ -1523,4 +1379,213 @@ extension FlutterVmService on vm_service.VmService {
);
await
onRunnable
;
}
Future
<
Map
<
String
,
dynamic
>>
flutterDebugDumpApp
({
@required
String
isolateId
,
})
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugDumpApp'
,
isolateId:
isolateId
,
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterDebugDumpRenderTree
({
@required
String
isolateId
,
})
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugDumpRenderTree'
,
isolateId:
isolateId
,
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterDebugDumpLayerTree
({
@required
String
isolateId
,
})
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugDumpLayerTree'
,
isolateId:
isolateId
,
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterDebugDumpSemanticsTreeInTraversalOrder
({
@required
String
isolateId
,
})
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugDumpSemanticsTreeInTraversalOrder'
,
isolateId:
isolateId
,
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterDebugDumpSemanticsTreeInInverseHitTestOrder
({
@required
String
isolateId
,
})
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder'
,
isolateId:
isolateId
,
);
}
Future
<
Map
<
String
,
dynamic
>>
_flutterToggle
(
String
name
,
{
@required
String
isolateId
,
})
async
{
Map
<
String
,
dynamic
>
state
=
await
invokeFlutterExtensionRpcRaw
(
'ext.flutter.
$name
'
,
isolateId:
isolateId
,
);
if
(
state
!=
null
&&
state
.
containsKey
(
'enabled'
)
&&
state
[
'enabled'
]
is
String
)
{
state
=
await
invokeFlutterExtensionRpcRaw
(
'ext.flutter.
$name
'
,
isolateId:
isolateId
,
args:
<
String
,
dynamic
>{
'enabled'
:
state
[
'enabled'
]
==
'true'
?
'false'
:
'true'
,
},
);
}
return
state
;
}
Future
<
Map
<
String
,
dynamic
>>
flutterToggleDebugPaintSizeEnabled
({
@required
String
isolateId
,
})
=>
_flutterToggle
(
'debugPaint'
,
isolateId:
isolateId
);
Future
<
Map
<
String
,
dynamic
>>
flutterToggleDebugCheckElevationsEnabled
({
@required
String
isolateId
,
})
=>
_flutterToggle
(
'debugCheckElevationsEnabled'
,
isolateId:
isolateId
);
Future
<
Map
<
String
,
dynamic
>>
flutterTogglePerformanceOverlayOverride
({
@required
String
isolateId
,
})
=>
_flutterToggle
(
'showPerformanceOverlay'
,
isolateId:
isolateId
);
Future
<
Map
<
String
,
dynamic
>>
flutterToggleWidgetInspector
({
@required
String
isolateId
,
})
=>
_flutterToggle
(
'inspector.show'
,
isolateId:
isolateId
);
Future
<
Map
<
String
,
dynamic
>>
flutterToggleProfileWidgetBuilds
({
@required
String
isolateId
,
})
=>
_flutterToggle
(
'profileWidgetBuilds'
,
isolateId:
isolateId
);
Future
<
Map
<
String
,
dynamic
>>
flutterDebugAllowBanner
(
bool
show
,
{
@required
String
isolateId
,
})
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.debugAllowBanner'
,
isolateId:
isolateId
,
args:
<
String
,
dynamic
>{
'enabled'
:
show
?
'true'
:
'false'
},
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterReassemble
({
@required
String
isolateId
,
})
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.reassemble'
,
isolateId:
isolateId
,
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterFastReassemble
(
String
classId
,
{
@required
String
isolateId
,
})
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.fastReassemble'
,
isolateId:
isolateId
,
args:
<
String
,
Object
>{
'class'
:
classId
,
},
);
}
Future
<
bool
>
flutterAlreadyPaintedFirstUsefulFrame
({
@required
String
isolateId
,
})
async
{
final
Map
<
String
,
dynamic
>
result
=
await
invokeFlutterExtensionRpcRaw
(
'ext.flutter.didSendFirstFrameRasterizedEvent'
,
isolateId:
isolateId
,
);
// result might be null when the service extension is not initialized
return
result
!=
null
&&
result
[
'enabled'
]
==
'true'
;
}
Future
<
Map
<
String
,
dynamic
>>
uiWindowScheduleFrame
({
@required
String
isolateId
,
})
{
return
invokeFlutterExtensionRpcRaw
(
'ext.ui.window.scheduleFrame'
,
isolateId:
isolateId
,
);
}
Future
<
Map
<
String
,
dynamic
>>
flutterEvictAsset
(
String
assetPath
,
{
@required
String
isolateId
,
})
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.evict'
,
isolateId:
isolateId
,
args:
<
String
,
dynamic
>{
'value'
:
assetPath
,
},
);
}
/// Exit the application by calling [exit] from `dart:io`.
///
/// This method is only supported by certain embedders. This is
/// described by [Device.supportsFlutterExit].
Future
<
Map
<
String
,
dynamic
>>
flutterExit
({
@required
String
isolateId
,
})
{
return
invokeFlutterExtensionRpcRaw
(
'ext.flutter.exit'
,
isolateId:
isolateId
,
);
}
/// Return the current platform override for the flutter view running with
/// the main isolate [isolateId].
///
/// If a non-null value is provided for [platform], the platform override
/// is updated with this value.
Future
<
String
>
flutterPlatformOverride
({
String
platform
,
@required
String
isolateId
,
})
async
{
final
Map
<
String
,
dynamic
>
result
=
await
invokeFlutterExtensionRpcRaw
(
'ext.flutter.platformOverride'
,
isolateId:
isolateId
,
args:
platform
!=
null
?
<
String
,
dynamic
>{
'value'
:
platform
}
:
<
String
,
String
>{},
);
if
(
result
!=
null
&&
result
[
'value'
]
is
String
)
{
return
result
[
'value'
]
as
String
;
}
return
'unknown'
;
}
/// Invoke a flutter extension method, if the flutter extension is not
/// available, returns null.
Future
<
Map
<
String
,
dynamic
>>
invokeFlutterExtensionRpcRaw
(
String
method
,
{
@required
String
isolateId
,
Map
<
String
,
dynamic
>
args
,
})
async
{
try
{
final
vm_service
.
Response
response
=
await
callServiceExtension
(
method
,
args:
<
String
,
Object
>{
'isolateId'
:
isolateId
,
...?
args
,
},
);
return
response
.
json
;
}
on
vm_service
.
RPCError
catch
(
err
)
{
// If an application is not using the framework
if
(
err
.
code
==
RPCErrorCodes
.
kMethodNotFound
)
{
return
null
;
}
rethrow
;
}
}
}
packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart
View file @
9202e547
...
...
@@ -5,12 +5,17 @@
import
'dart:async'
;
import
'package:file/memory.dart'
;
import
'package:meta/meta.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:process/process.dart'
;
import
'package:quiver/testing/async.dart'
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
import
'package:flutter_tools/src/base/common.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/net.dart'
;
import
'package:flutter_tools/src/base/terminal.dart'
;
import
'package:flutter_tools/src/cache.dart'
;
import
'package:flutter_tools/src/commands/attach.dart'
;
...
...
@@ -22,10 +27,6 @@ import 'package:flutter_tools/src/project.dart';
import
'package:flutter_tools/src/resident_runner.dart'
;
import
'package:flutter_tools/src/run_hot.dart'
;
import
'package:flutter_tools/src/vmservice.dart'
;
import
'package:meta/meta.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:process/process.dart'
;
import
'package:quiver/testing/async.dart'
;
import
'package:flutter_tools/src/globals.dart'
as
globals
;
import
'../../src/common.dart'
;
...
...
@@ -142,7 +143,7 @@ void main() {
final
Process
dartProcess
=
MockProcess
();
final
StreamController
<
List
<
int
>>
compilerStdoutController
=
StreamController
<
List
<
int
>>();
when
(
dartProcess
.
stdout
).
thenAnswer
((
_
)
=>
compilerStdoutController
.
stream
);
when
(
dartProcess
.
stdout
).
thenAnswer
((
_
)
=>
compilerStdoutController
.
stream
);
when
(
dartProcess
.
stderr
)
.
thenAnswer
((
_
)
=>
Stream
<
List
<
int
>>.
fromFuture
(
Future
<
List
<
int
>>.
value
(
const
<
int
>[])));
...
...
@@ -787,6 +788,23 @@ VMServiceConnector getFakeVmServiceFactory({
when
(
vmService
.
done
).
thenAnswer
((
_
)
{
return
Future
<
void
>.
value
(
null
);
});
when
(
vmService
.
onDone
).
thenAnswer
((
_
)
{
return
Future
<
void
>.
value
(
null
);
});
when
(
vmService
.
getVM
()).
thenAnswer
((
_
)
async
{
return
vm_service
.
VM
(
pid:
1
,
architectureBits:
64
,
hostCPU:
''
,
name:
''
,
isolates:
<
vm_service
.
IsolateRef
>[],
isolateGroups:
<
vm_service
.
IsolateGroupRef
>[],
startTime:
0
,
targetCPU:
''
,
operatingSystem:
''
,
version:
''
,
);
});
when
(
vm
.
refreshViews
(
waitForViews:
anyNamed
(
'waitForViews'
)))
.
thenAnswer
((
_
)
=>
Future
<
void
>.
value
(
null
));
...
...
packages/flutter_tools/test/general.shard/resident_runner_test.dart
View file @
9202e547
...
...
@@ -41,6 +41,7 @@ void main() {
ResidentRunner
residentRunner
;
MockDevice
mockDevice
;
MockIsolate
mockIsolate
;
FakeVmServiceHost
fakeVmServiceHost
;
setUp
(()
{
testbed
=
Testbed
(
setup:
()
{
...
...
@@ -89,31 +90,12 @@ void main() {
invalidatedSourcesCount:
0
,
);
});
// TODO(jonahwilliams): replace mock with FakeVmServiceHost once all methods
// are moved to real vm service.
when
(
mockFlutterDevice
.
devFS
).
thenReturn
(
mockDevFS
);
when
(
mockFlutterDevice
.
views
).
thenReturn
(<
FlutterView
>[
mockFlutterView
,
]);
when
(
mockFlutterDevice
.
device
).
thenReturn
(
mockDevice
);
when
(
mockFlutterView
.
uiIsolate
).
thenReturn
(
mockIsolate
);
final
MockVM
mockVM
=
MockVM
();
when
(
mockVMService
.
vm
).
thenReturn
(
mockVM
);
when
(
mockVM
.
isolates
).
thenReturn
(<
Isolate
>[
mockIsolate
]);
when
(
mockVMService
.
streamListen
(
'Isolate'
)).
thenAnswer
((
Invocation
invocation
)
async
{
return
vm_service
.
Success
();
});
when
(
mockVMService
.
onIsolateEvent
).
thenAnswer
((
Invocation
invocation
)
{
return
Stream
<
vm_service
.
Event
>.
fromIterable
(<
vm_service
.
Event
>[
vm_service
.
Event
(
kind:
vm_service
.
EventKind
.
kIsolateRunnable
,
timestamp:
0
),
]);
});
when
(
mockVMService
.
callMethod
(
kRunInViewMethod
,
args:
anyNamed
(
'args'
),
)).
thenAnswer
((
Invocation
invocation
)
async
{
return
vm_service
.
Success
();
});
when
(
mockFlutterDevice
.
stopEchoingDeviceLog
()).
thenAnswer
((
Invocation
invocation
)
async
{
});
when
(
mockFlutterDevice
.
observatoryUris
).
thenAnswer
((
_
)
=>
Stream
<
Uri
>.
value
(
testUri
));
when
(
mockFlutterDevice
.
connect
(
...
...
@@ -125,7 +107,12 @@ void main() {
.
thenAnswer
((
Invocation
invocation
)
async
{
return
testUri
;
});
when
(
mockFlutterDevice
.
vmService
).
thenReturn
(
mockVMService
);
when
(
mockFlutterDevice
.
vmService
).
thenAnswer
((
Invocation
invocation
)
{
return
fakeVmServiceHost
.
vmService
;
});
when
(
mockFlutterDevice
.
flutterDeprecatedVmService
).
thenAnswer
((
Invocation
invocation
)
{
return
mockVMService
;
});
when
(
mockFlutterDevice
.
refreshViews
()).
thenAnswer
((
Invocation
invocation
)
async
{
});
when
(
mockFlutterDevice
.
getVMs
()).
thenAnswer
((
Invocation
invocation
)
async
{
});
when
(
mockFlutterDevice
.
reloadSources
(
any
,
pause:
anyNamed
(
'pause'
))).
thenReturn
(<
Future
<
vm_service
.
ReloadReport
>>[
...
...
@@ -147,15 +134,13 @@ void main() {
final
Completer
<
void
>
result
=
Completer
<
void
>.
sync
();
return
result
.
future
;
});
when
(
mockIsolate
.
flutterExit
()).
thenAnswer
((
Invocation
invocation
)
{
return
Future
<
Map
<
String
,
Object
>>.
value
(
null
);
});
when
(
mockIsolate
.
reload
()).
thenAnswer
((
Invocation
invocation
)
{
return
Future
<
ServiceObject
>.
value
(
null
);
});
});
test
(
'ResidentRunner can attach to device successfully'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
final
Completer
<
DebugConnectionInfo
>
onConnectionInfo
=
Completer
<
DebugConnectionInfo
>.
sync
();
final
Completer
<
void
>
onAppStart
=
Completer
<
void
>.
sync
();
final
Future
<
int
>
result
=
residentRunner
.
attach
(
...
...
@@ -174,6 +159,31 @@ void main() {
}));
test
(
'ResidentRunner can attach to device successfully with --fast-start'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
const
FakeVmServiceRequest
(
id:
'1'
,
method:
'streamListen'
,
args:
<
String
,
Object
>{
'streamId'
:
'Isolate'
,
}
),
const
FakeVmServiceRequest
(
id:
'2'
,
method:
kRunInViewMethod
,
args:
<
String
,
Object
>{
'viewId'
:
null
,
'mainScript'
:
'lib/main.dart.dill'
,
'assetDirectory'
:
'build/flutter_assets'
,
}
),
FakeVmServiceStreamResponse
(
streamId:
'Isolate'
,
event:
vm_service
.
Event
(
timestamp:
0
,
kind:
vm_service
.
EventKind
.
kIsolateRunnable
,
)
),
]);
when
(
mockDevice
.
supportsHotRestart
).
thenReturn
(
true
);
when
(
mockDevice
.
sdkNameAndVersion
).
thenAnswer
((
Invocation
invocation
)
async
{
return
'Example'
;
...
...
@@ -189,7 +199,11 @@ void main() {
mockFlutterDevice
,
],
stayResident:
false
,
debuggingOptions:
DebuggingOptions
.
enabled
(
BuildInfo
.
debug
,
fastStart:
true
,
startPaused:
true
),
debuggingOptions:
DebuggingOptions
.
enabled
(
BuildInfo
.
debug
,
fastStart:
true
,
startPaused:
true
,
),
);
final
Completer
<
DebugConnectionInfo
>
onConnectionInfo
=
Completer
<
DebugConnectionInfo
>.
sync
();
final
Completer
<
void
>
onAppStart
=
Completer
<
void
>.
sync
();
...
...
@@ -209,6 +223,7 @@ void main() {
}));
test
(
'ResidentRunner can handle an RPC exception from hot reload'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
when
(
mockDevice
.
sdkNameAndVersion
).
thenAnswer
((
Invocation
invocation
)
async
{
return
'Example'
;
});
...
...
@@ -255,6 +270,16 @@ void main() {
}));
test
(
'ResidentRunner can send target platform to analytics from hot reload'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
// Not all requests are present due to existing mocks
const
FakeVmServiceRequest
(
id:
'1'
,
method:
'ext.flutter.reassemble'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
},
),
]);
when
(
mockDevice
.
sdkNameAndVersion
).
thenAnswer
((
Invocation
invocation
)
async
{
return
'Example'
;
});
...
...
@@ -284,6 +309,32 @@ void main() {
}));
test
(
'ResidentRunner can send target platform to analytics from full restart'
,
()
=>
testbed
.
run
(()
async
{
// Not all requests are present due to existing mocks
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
const
FakeVmServiceRequest
(
id:
'1'
,
method:
'streamListen'
,
args:
<
String
,
Object
>{
'streamId'
:
'Isolate'
,
},
),
const
FakeVmServiceRequest
(
id:
'2'
,
method:
kRunInViewMethod
,
args:
<
String
,
Object
>{
'viewId'
:
null
,
'mainScript'
:
'lib/main.dart.dill'
,
'assetDirectory'
:
'build/flutter_assets'
,
},
),
FakeVmServiceStreamResponse
(
streamId:
'Isolate'
,
event:
vm_service
.
Event
(
timestamp:
0
,
kind:
vm_service
.
EventKind
.
kIsolateRunnable
,
)
)
]);
when
(
mockDevice
.
sdkNameAndVersion
).
thenAnswer
((
Invocation
invocation
)
async
{
return
'Example'
;
});
...
...
@@ -314,6 +365,7 @@ void main() {
}));
test
(
'ResidentRunner Can handle an RPC exception from hot restart'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
when
(
mockDevice
.
sdkNameAndVersion
).
thenAnswer
((
Invocation
invocation
)
async
{
return
'Example'
;
});
...
...
@@ -361,6 +413,7 @@ void main() {
}));
test
(
'ResidentRunner uses temp directory when there is no output dill path'
,
()
=>
testbed
.
run
(()
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
expect
(
residentRunner
.
artifactDirectory
.
path
,
contains
(
'flutter_tool.'
));
final
ResidentRunner
otherRunner
=
HotRunner
(
...
...
@@ -375,6 +428,7 @@ void main() {
}));
test
(
'ResidentRunner copies output dill to cache location during preExit'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
residentRunner
.
artifactDirectory
.
childFile
(
'app.dill'
).
writeAsStringSync
(
'hello'
);
await
residentRunner
.
preExit
();
final
File
cacheDill
=
globals
.
fs
.
file
(
globals
.
fs
.
path
.
join
(
getBuildDirectory
(),
'cache.dill'
));
...
...
@@ -384,6 +438,7 @@ void main() {
}));
test
(
'ResidentRunner handles output dill missing during preExit'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
await
residentRunner
.
preExit
();
final
File
cacheDill
=
globals
.
fs
.
file
(
globals
.
fs
.
path
.
join
(
getBuildDirectory
(),
'cache.dill'
));
...
...
@@ -391,6 +446,7 @@ void main() {
}));
test
(
'ResidentRunner printHelpDetails'
,
()
=>
testbed
.
run
(()
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
when
(
mockDevice
.
supportsHotRestart
).
thenReturn
(
true
);
when
(
mockDevice
.
supportsScreenshot
).
thenReturn
(
true
);
...
...
@@ -436,39 +492,48 @@ void main() {
}));
test
(
'ResidentRunner does support CanvasKit'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
expect
(()
=>
residentRunner
.
toggleCanvaskit
(),
throwsA
(
isA
<
Exception
>()));
}));
test
(
'ResidentRunner handles writeSkSL returning no data'
,
()
=>
testbed
.
run
(()
async
{
when
(
mockVMService
.
callMethod
(
kGetSkSLsMethod
,
args:
anyNamed
(
'args'
),
)).
thenAnswer
((
Invocation
invocation
)
async
{
return
vm_service
.
Response
.
parse
(<
String
,
Object
>{
'SkSLs'
:
<
String
,
Object
>{}
});
});
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
const
FakeVmServiceRequest
(
id:
'1'
,
method:
kGetSkSLsMethod
,
args:
<
String
,
Object
>{
'viewId'
:
null
,
},
jsonResponse:
<
String
,
Object
>{
'SkSLs'
:
<
String
,
Object
>{}
}
)
]);
await
residentRunner
.
writeSkSL
();
expect
(
testLogger
.
statusText
,
contains
(
'No data was receieved'
));
}));
test
(
'ResidentRunner can write SkSL data to a unique file with engine revision, platform, and device name'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
const
FakeVmServiceRequest
(
id:
'1'
,
method:
kGetSkSLsMethod
,
args:
<
String
,
Object
>{
'viewId'
:
null
,
},
jsonResponse:
<
String
,
Object
>{
'SkSLs'
:
<
String
,
Object
>{
'A'
:
'B'
,
}
}
)
]);
when
(
mockDevice
.
targetPlatform
).
thenAnswer
((
Invocation
invocation
)
async
{
return
TargetPlatform
.
android_arm
;
});
when
(
mockDevice
.
name
).
thenReturn
(
'test device'
);
when
(
mockVMService
.
callMethod
(
kGetSkSLsMethod
,
args:
anyNamed
(
'args'
),
)).
thenAnswer
((
Invocation
invocation
)
async
{
return
vm_service
.
Response
.
parse
(<
String
,
Object
>{
'SkSLs'
:
<
String
,
Object
>{
'A'
:
'B'
,
}
});
});
await
residentRunner
.
writeSkSL
();
expect
(
testLogger
.
statusText
,
contains
(
'flutter_01.sksl'
));
...
...
@@ -479,9 +544,28 @@ void main() {
'engineRevision'
:
'42.2'
,
// From FakeFlutterVersion
'data'
:
<
String
,
Object
>{
'A'
:
'B'
}
});
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'ResidentRunner can take screenshot on debug device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
const
FakeVmServiceRequest
(
id:
'1'
,
method:
'ext.flutter.debugAllowBanner'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
'enabled'
:
'false'
,
},
),
const
FakeVmServiceRequest
(
id:
'2'
,
method:
'ext.flutter.debugAllowBanner'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
'enabled'
:
'true'
,
},
)
]);
when
(
mockDevice
.
supportsScreenshot
).
thenReturn
(
true
);
when
(
mockDevice
.
takeScreenshot
(
any
))
.
thenAnswer
((
Invocation
invocation
)
async
{
...
...
@@ -491,23 +575,12 @@ void main() {
await
residentRunner
.
screenshot
(
mockFlutterDevice
);
// disables debug banner.
verify
(
mockIsolate
.
flutterDebugAllowBanner
(
false
)).
called
(
1
);
// Enables debug banner.
verify
(
mockIsolate
.
flutterDebugAllowBanner
(
true
)).
called
(
1
);
expect
(
testLogger
.
statusText
,
contains
(
'1kB'
));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'ResidentRunner bails taking screenshot on debug device if debugAllowBanner throws pre'
,
()
=>
testbed
.
run
(()
async
{
when
(
mockDevice
.
supportsScreenshot
).
thenReturn
(
true
);
when
(
mockIsolate
.
flutterDebugAllowBanner
(
false
)).
thenThrow
(
Exception
());
await
residentRunner
.
screenshot
(
mockFlutterDevice
);
expect
(
testLogger
.
errorText
,
contains
(
'Error'
));
}));
test
(
'ResidentTunner clears the screen when it should'
,
()
=>
testbed
.
run
(()
async
{
test
(
'ResidentRunner clears the screen when it should'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
const
String
message
=
'This should be cleared'
;
expect
(
testLogger
.
statusText
,
equals
(
''
));
testLogger
.
printStatus
(
message
);
...
...
@@ -516,16 +589,72 @@ void main() {
expect
(
testLogger
.
statusText
,
equals
(
''
));
}));
test
(
'ResidentRunner bails taking screenshot on debug device if debugAllowBanner throws post'
,
()
=>
testbed
.
run
(()
async
{
test
(
'ResidentRunner bails taking screenshot on debug device if debugAllowBanner throws RpcError'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
const
FakeVmServiceRequest
(
id:
'1'
,
method:
'ext.flutter.debugAllowBanner'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
'enabled'
:
'false'
,
},
// Failed response,
errorCode:
RPCErrorCodes
.
kInternalError
,
)
]);
when
(
mockDevice
.
supportsScreenshot
).
thenReturn
(
true
);
when
(
mockIsolate
.
flutterDebugAllowBanner
(
true
)).
thenThrow
(
Exception
()
);
await
residentRunner
.
screenshot
(
mockFlutterDevice
);
expect
(
testLogger
.
errorText
,
contains
(
'Error'
));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'ResidentRunner bails taking screenshot on debug device if debugAllowBanner during second request'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
const
FakeVmServiceRequest
(
id:
'1'
,
method:
'ext.flutter.debugAllowBanner'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
'enabled'
:
'false'
,
},
),
const
FakeVmServiceRequest
(
id:
'2'
,
method:
'ext.flutter.debugAllowBanner'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
'enabled'
:
'true'
,
},
// Failed response,
errorCode:
RPCErrorCodes
.
kInternalError
,
)
]);
when
(
mockDevice
.
supportsScreenshot
).
thenReturn
(
true
);
await
residentRunner
.
screenshot
(
mockFlutterDevice
);
expect
(
testLogger
.
errorText
,
contains
(
'Error'
));
}));
test
(
'ResidentRunner bails taking screenshot on debug device if takeScreenshot throws'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
const
FakeVmServiceRequest
(
id:
'1'
,
method:
'ext.flutter.debugAllowBanner'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
'enabled'
:
'false'
,
},
),
const
FakeVmServiceRequest
(
id:
'2'
,
method:
'ext.flutter.debugAllowBanner'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
'enabled'
:
'true'
,
},
),
]);
when
(
mockDevice
.
supportsScreenshot
).
thenReturn
(
true
);
when
(
mockDevice
.
takeScreenshot
(
any
)).
thenThrow
(
Exception
());
...
...
@@ -535,6 +664,7 @@ void main() {
}));
test
(
"ResidentRunner can't take screenshot on device without support"
,
()
=>
testbed
.
run
(()
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
when
(
mockDevice
.
supportsScreenshot
).
thenReturn
(
false
);
expect
(()
=>
residentRunner
.
screenshot
(
mockFlutterDevice
),
...
...
@@ -542,6 +672,7 @@ void main() {
}));
test
(
'ResidentRunner does not toggle banner in non-debug mode'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
residentRunner
=
HotRunner
(
<
FlutterDevice
>[
mockFlutterDevice
,
...
...
@@ -558,18 +689,17 @@ void main() {
await
residentRunner
.
screenshot
(
mockFlutterDevice
);
// doesn't disabled debug banner.
verifyNever
(
mockIsolate
.
flutterDebugAllowBanner
(
false
));
// doesn't enable debug banner.
verifyNever
(
mockIsolate
.
flutterDebugAllowBanner
(
true
));
expect
(
testLogger
.
statusText
,
contains
(
'1kB'
));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'FlutterDevice will not exit a paused isolate'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
final
TestFlutterDevice
flutterDevice
=
TestFlutterDevice
(
mockDevice
,
<
FlutterView
>[
mockFlutterView
],
);
flutterDevice
.
vmService
=
fakeVmServiceHost
.
vmService
;
final
MockServiceEvent
mockServiceEvent
=
MockServiceEvent
();
when
(
mockServiceEvent
.
isPauseEvent
).
thenReturn
(
true
);
when
(
mockIsolate
.
pauseEvent
).
thenReturn
(
mockServiceEvent
);
...
...
@@ -577,15 +707,25 @@ void main() {
await
flutterDevice
.
exitApps
();
verifyNever
(
mockIsolate
.
flutterExit
());
verify
(
mockDevice
.
stopApp
(
any
)).
called
(
1
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'FlutterDevice will exit an un-paused isolate'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
const
FakeVmServiceRequest
(
id:
'1'
,
method:
'ext.flutter.exit'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
},
)
]);
final
TestFlutterDevice
flutterDevice
=
TestFlutterDevice
(
mockDevice
,
<
FlutterView
>
[
mockFlutterView
],
<
FlutterView
>
[
mockFlutterView
],
);
flutterDevice
.
vmService
=
fakeVmServiceHost
.
vmService
;
final
MockServiceEvent
mockServiceEvent
=
MockServiceEvent
();
when
(
mockServiceEvent
.
isPauseEvent
).
thenReturn
(
false
);
...
...
@@ -593,17 +733,18 @@ void main() {
when
(
mockDevice
.
supportsFlutterExit
).
thenReturn
(
true
);
await
flutterDevice
.
exitApps
();
verify
(
mockIsolate
.
flutterExit
()).
called
(
1
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'ResidentRunner refreshViews calls flutter device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
await
residentRunner
.
refreshViews
();
verify
(
mockFlutterDevice
.
refreshViews
()).
called
(
1
);
}));
test
(
'ResidentRunner debugDumpApp calls flutter device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
await
residentRunner
.
debugDumpApp
();
verify
(
mockFlutterDevice
.
refreshViews
()).
called
(
1
);
...
...
@@ -611,6 +752,7 @@ void main() {
}));
test
(
'ResidentRunner debugDumpRenderTree calls flutter device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
await
residentRunner
.
debugDumpRenderTree
();
verify
(
mockFlutterDevice
.
refreshViews
()).
called
(
1
);
...
...
@@ -618,6 +760,7 @@ void main() {
}));
test
(
'ResidentRunner debugDumpLayerTree calls flutter device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
await
residentRunner
.
debugDumpLayerTree
();
verify
(
mockFlutterDevice
.
refreshViews
()).
called
(
1
);
...
...
@@ -625,6 +768,7 @@ void main() {
}));
test
(
'ResidentRunner debugDumpSemanticsTreeInTraversalOrder calls flutter device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
await
residentRunner
.
debugDumpSemanticsTreeInTraversalOrder
();
verify
(
mockFlutterDevice
.
refreshViews
()).
called
(
1
);
...
...
@@ -632,6 +776,7 @@ void main() {
}));
test
(
'ResidentRunner debugDumpSemanticsTreeInInverseHitTestOrder calls flutter device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
await
residentRunner
.
debugDumpSemanticsTreeInInverseHitTestOrder
();
verify
(
mockFlutterDevice
.
refreshViews
()).
called
(
1
);
...
...
@@ -639,6 +784,7 @@ void main() {
}));
test
(
'ResidentRunner debugToggleDebugPaintSizeEnabled calls flutter device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
await
residentRunner
.
debugToggleDebugPaintSizeEnabled
();
verify
(
mockFlutterDevice
.
refreshViews
()).
called
(
1
);
...
...
@@ -646,13 +792,15 @@ void main() {
}));
test
(
'ResidentRunner debugToggleDebugCheckElevationsEnabled calls flutter device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
await
residentRunner
.
debugToggleDebugCheckElevationsEnabled
();
verify
(
mockFlutterDevice
.
refreshViews
()).
called
(
1
);
verify
(
mockFlutterDevice
.
toggleDebugCheckElevationsEnabled
()).
called
(
1
);
}));
test
(
'ResidentRunner debugTogglePerformanceOverlayOverride calls flutter device'
,
()
=>
testbed
.
run
(()
async
{
test
(
'ResidentRunner debugTogglePerformanceOverlayOverride calls flutter device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
await
residentRunner
.
debugTogglePerformanceOverlayOverride
();
verify
(
mockFlutterDevice
.
refreshViews
()).
called
(
1
);
...
...
@@ -660,6 +808,7 @@ void main() {
}));
test
(
'ResidentRunner debugToggleWidgetInspector calls flutter device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
await
residentRunner
.
debugToggleWidgetInspector
();
verify
(
mockFlutterDevice
.
refreshViews
()).
called
(
1
);
...
...
@@ -667,6 +816,7 @@ void main() {
}));
test
(
'ResidentRunner debugToggleProfileWidgetBuilds calls flutter device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
await
residentRunner
.
debugToggleProfileWidgetBuilds
();
verify
(
mockFlutterDevice
.
refreshViews
()).
called
(
1
);
...
...
@@ -674,6 +824,7 @@ void main() {
}));
test
(
'HotRunner writes vm service file when providing debugging option'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
globals
.
fs
.
file
(
globals
.
fs
.
path
.
join
(
'lib'
,
'main.dart'
)).
createSync
(
recursive:
true
);
residentRunner
=
HotRunner
(
<
FlutterDevice
>[
...
...
@@ -694,6 +845,7 @@ void main() {
}));
test
(
'HotRunner unforwards device ports'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
final
MockDevicePortForwarder
mockPortForwarder
=
MockDevicePortForwarder
();
when
(
mockDevice
.
portForwarder
).
thenReturn
(
mockPortForwarder
);
globals
.
fs
.
file
(
globals
.
fs
.
path
.
join
(
'lib'
,
'main.dart'
)).
createSync
(
recursive:
true
);
...
...
@@ -721,6 +873,7 @@ void main() {
}));
test
(
'HotRunner handles failure to write vmservice file'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
globals
.
fs
.
file
(
globals
.
fs
.
path
.
join
(
'lib'
,
'main.dart'
)).
createSync
(
recursive:
true
);
residentRunner
=
HotRunner
(
<
FlutterDevice
>[
...
...
@@ -744,6 +897,7 @@ void main() {
test
(
'ColdRunner writes vm service file when providing debugging option'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
globals
.
fs
.
file
(
globals
.
fs
.
path
.
join
(
'lib'
,
'main.dart'
)).
createSync
(
recursive:
true
);
residentRunner
=
ColdRunner
(
<
FlutterDevice
>[
...
...
@@ -764,6 +918,7 @@ void main() {
}));
test
(
'FlutterDevice uses dartdevc configuration when targeting web'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
final
MockDevice
mockDevice
=
MockDevice
();
when
(
mockDevice
.
targetPlatform
).
thenAnswer
((
Invocation
invocation
)
async
{
return
TargetPlatform
.
web_javascript
;
...
...
@@ -792,6 +947,7 @@ void main() {
}));
test
(
'connect sets up log reader'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
final
MockDevice
mockDevice
=
MockDevice
();
final
MockDeviceLogReader
mockLogReader
=
MockDeviceLogReader
();
when
(
mockDevice
.
getLogReader
(
app:
anyNamed
(
'app'
))).
thenReturn
(
mockLogReader
);
...
...
packages/flutter_tools/test/general.shard/resident_web_runner_test.dart
View file @
9202e547
...
...
@@ -5,6 +5,8 @@
import
'dart:async'
;
import
'dart:convert'
;
import
'package:flutter_tools/src/vmservice.dart'
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
import
'package:dwds/dwds.dart'
;
import
'package:flutter_tools/src/base/common.dart'
;
import
'package:flutter_tools/src/base/io.dart'
;
...
...
@@ -32,11 +34,50 @@ import '../src/common.dart';
import
'../src/context.dart'
;
import
'../src/testbed.dart'
;
const
List
<
VmServiceExpectation
>
kAttachLogExpectations
=
<
VmServiceExpectation
>[
FakeVmServiceRequest
(
id:
'1'
,
method:
'streamListen'
,
args:
<
String
,
Object
>{
'streamId'
:
'Stdout'
,
},
),
FakeVmServiceRequest
(
id:
'2'
,
method:
'streamListen'
,
args:
<
String
,
Object
>{
'streamId'
:
'Stderr'
,
},
)
];
const
List
<
VmServiceExpectation
>
kAttachIsolateExpectations
=
<
VmServiceExpectation
>[
FakeVmServiceRequest
(
id:
'3'
,
method:
'streamListen'
,
args:
<
String
,
Object
>{
'streamId'
:
'Isolate'
}
),
FakeVmServiceRequest
(
id:
'4'
,
method:
'registerService'
,
args:
<
String
,
Object
>{
'service'
:
'reloadSources'
,
'alias'
:
'FlutterTools'
,
}
)
];
const
List
<
VmServiceExpectation
>
kAttachExpectations
=
<
VmServiceExpectation
>[
...
kAttachLogExpectations
,
...
kAttachIsolateExpectations
,
];
void
main
(
)
{
Testbed
testbed
;
ResidentWebRunner
residentWebRunner
;
MockDebugConnection
mockDebugConnection
;
MockVmService
mockVmService
;
MockChromeDevice
mockChromeDevice
;
MockAppConnection
mockAppConnection
;
MockFlutterDevice
mockFlutterDevice
;
...
...
@@ -49,11 +90,11 @@ void main() {
MockWipDebugger
mockWipDebugger
;
MockWebServerDevice
mockWebServerDevice
;
MockDevice
mockDevice
;
FakeVmServiceHost
fakeVmServiceHost
;
setUp
(()
{
resetChromeForTesting
();
mockDebugConnection
=
MockDebugConnection
();
mockVmService
=
MockVmService
();
mockDevice
=
MockDevice
();
mockAppConnection
=
MockAppConnection
();
mockFlutterDevice
=
MockFlutterDevice
();
...
...
@@ -110,24 +151,12 @@ void main() {
)).
thenAnswer
((
Invocation
_
)
async
{
return
UpdateFSReport
(
success:
true
,
syncedBytes:
0
)..
invalidatedModules
=
<
String
>[];
});
when
(
mockDebugConnection
.
vmService
).
thenReturn
(
mockVmService
);
when
(
mockDebugConnection
.
vmService
).
thenAnswer
((
Invocation
invocation
)
{
return
fakeVmServiceHost
.
vmService
;
});
when
(
mockDebugConnection
.
onDone
).
thenAnswer
((
Invocation
invocation
)
{
return
Completer
<
void
>().
future
;
});
when
(
mockVmService
.
onStdoutEvent
).
thenAnswer
((
Invocation
_
)
{
return
const
Stream
<
Event
>.
empty
();
});
when
(
mockVmService
.
onStderrEvent
).
thenAnswer
((
Invocation
_
)
{
return
const
Stream
<
Event
>.
empty
();
});
when
(
mockVmService
.
onDebugEvent
).
thenAnswer
((
Invocation
_
)
{
return
const
Stream
<
Event
>.
empty
();
});
when
(
mockVmService
.
onIsolateEvent
).
thenAnswer
((
Invocation
_
)
{
return
Stream
<
Event
>.
fromIterable
(<
Event
>[
Event
(
kind:
EventKind
.
kIsolateStart
,
timestamp:
1
),
]);
});
when
(
mockDebugConnection
.
uri
).
thenReturn
(
'ws://127.0.0.1/abcd/'
);
when
(
mockFlutterDevice
.
devFS
).
thenReturn
(
mockWebDevFS
);
when
(
mockWebDevFS
.
sources
).
thenReturn
(<
Uri
>[]);
...
...
@@ -144,6 +173,7 @@ void main() {
}
test
(
'runner with web server device does not support debugging without --start-paused'
,
()
=>
testbed
.
run
(()
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
when
(
mockFlutterDevice
.
device
).
thenReturn
(
WebServerDevice
());
final
ResidentRunner
profileResidentWebRunner
=
DwdsWebRunnerFactory
().
createWebRunner
(
mockFlutterDevice
,
...
...
@@ -158,9 +188,11 @@ void main() {
when
(
mockFlutterDevice
.
device
).
thenReturn
(
MockChromeDevice
());
expect
(
residentWebRunner
.
debuggingEnabled
,
true
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'runner with web server device supports debugging with --start-paused'
,
()
=>
testbed
.
run
(()
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
_setupMocks
();
when
(
mockFlutterDevice
.
device
).
thenReturn
(
WebServerDevice
());
final
ResidentRunner
profileResidentWebRunner
=
DwdsWebRunnerFactory
().
createWebRunner
(
...
...
@@ -177,6 +209,7 @@ void main() {
}));
test
(
'profile does not supportsServiceProtocol'
,
()
=>
testbed
.
run
(()
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
when
(
mockFlutterDevice
.
device
).
thenReturn
(
mockChromeDevice
);
final
ResidentRunner
profileResidentWebRunner
=
DwdsWebRunnerFactory
().
createWebRunner
(
mockFlutterDevice
,
...
...
@@ -192,6 +225,7 @@ void main() {
}));
test
(
'Exits on run if application does not support the web'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
globals
.
fs
.
file
(
'pubspec.yaml'
).
createSync
();
expect
(
await
residentWebRunner
.
run
(),
1
);
...
...
@@ -199,6 +233,7 @@ void main() {
}));
test
(
'Exits on run if target file does not exist'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
globals
.
fs
.
file
(
'pubspec.yaml'
).
createSync
();
globals
.
fs
.
file
(
globals
.
fs
.
path
.
join
(
'web'
,
'index.html'
)).
createSync
(
recursive:
true
);
...
...
@@ -208,6 +243,7 @@ void main() {
}));
test
(
'Can successfully run and connect to vmservice'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
kAttachExpectations
.
toList
());
_setupMocks
();
final
DelegateLogger
delegateLogger
=
globals
.
logger
as
DelegateLogger
;
final
BufferLogger
bufferLogger
=
delegateLogger
.
delegate
as
BufferLogger
;
...
...
@@ -220,7 +256,6 @@ void main() {
final
DebugConnectionInfo
debugConnectionInfo
=
await
connectionInfoCompleter
.
future
;
verify
(
mockAppConnection
.
runMain
()).
called
(
1
);
verify
(
mockVmService
.
registerService
(
'reloadSources'
,
'FlutterTools'
)).
called
(
1
);
verify
(
status
.
stop
()).
called
(
1
);
verify
(
pub
.
get
(
context:
PubContext
.
pubGet
,
...
...
@@ -240,6 +275,7 @@ void main() {
}));
test
(
'Can successfully run and disconnect with --no-resident'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
kAttachExpectations
.
toList
());
_setupMocks
();
residentWebRunner
=
DwdsWebRunnerFactory
().
createWebRunner
(
mockFlutterDevice
,
...
...
@@ -254,30 +290,28 @@ void main() {
}));
test
(
'Listens to stdout and stderr streams before running main'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachLogExpectations
,
FakeVmServiceStreamResponse
(
streamId:
'Stdout'
,
event:
vm_service
.
Event
(
timestamp:
0
,
kind:
vm_service
.
EventStreams
.
kStdout
,
bytes:
base64
.
encode
(
utf8
.
encode
(
'THIS MESSAGE IS IMPORTANT'
))
),
),
FakeVmServiceStreamResponse
(
streamId:
'Stderr'
,
event:
vm_service
.
Event
(
timestamp:
0
,
kind:
vm_service
.
EventStreams
.
kStderr
,
bytes:
base64
.
encode
(
utf8
.
encode
(
'SO IS THIS'
))
),
),
...
kAttachIsolateExpectations
,
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
final
StreamController
<
Event
>
stdoutController
=
StreamController
<
Event
>.
broadcast
();
final
StreamController
<
Event
>
stderrController
=
StreamController
<
Event
>.
broadcast
();
when
(
mockVmService
.
onStdoutEvent
).
thenAnswer
((
Invocation
_
)
{
return
stdoutController
.
stream
;
});
when
(
mockVmService
.
onStderrEvent
).
thenAnswer
((
Invocation
_
)
{
return
stderrController
.
stream
;
});
when
(
mockAppConnection
.
runMain
()).
thenAnswer
((
Invocation
invocation
)
{
stdoutController
.
add
(
Event
.
parse
(<
String
,
Object
>{
'type'
:
'Event'
,
'kind'
:
'WriteEvent'
,
'timestamp'
:
1569473488296
,
'bytes'
:
base64
.
encode
(
'THIS MESSAGE IS IMPORTANT'
.
codeUnits
),
}));
stderrController
.
add
(
Event
.
parse
(<
String
,
Object
>{
'type'
:
'Event'
,
'kind'
:
'WriteEvent'
,
'timestamp'
:
1569473488296
,
'bytes'
:
base64
.
encode
(
'SO IS THIS'
.
codeUnits
),
}));
});
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
...
...
@@ -288,6 +322,7 @@ void main() {
}));
test
(
'Does not run main with --start-paused'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
kAttachExpectations
.
toList
());
residentWebRunner
=
DwdsWebRunnerFactory
().
createWebRunner
(
mockFlutterDevice
,
flutterProject:
FlutterProject
.
current
(),
...
...
@@ -298,10 +333,7 @@ void main() {
)
as
ResidentWebRunner
;
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
final
StreamController
<
Event
>
controller
=
StreamController
<
Event
>.
broadcast
();
when
(
mockVmService
.
onStdoutEvent
).
thenAnswer
((
Invocation
_
)
{
return
controller
.
stream
;
});
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
...
...
@@ -311,6 +343,17 @@ void main() {
}));
test
(
'Can hot reload after attaching'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
method:
'hotRestart'
,
id:
'5'
,
args:
null
,
jsonResponse:
<
String
,
Object
>{
'type'
:
'Success'
,
}
),
]);
_setupMocks
();
launchChromeInstance
(
mockChrome
);
when
(
mockWebDevFS
.
update
(
...
...
@@ -362,6 +405,17 @@ void main() {
}));
test
(
'Can hot restart after attaching'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
method:
'hotRestart'
,
id:
'5'
,
args:
null
,
jsonResponse:
<
String
,
Object
>{
'type'
:
'Success'
,
}
),
]);
_setupMocks
();
launchChromeInstance
(
mockChrome
);
Uri
entrypointFileUri
;
...
...
@@ -417,6 +471,7 @@ void main() {
}));
test
(
'Can hot restart after attaching with web-server device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests
:
kAttachExpectations
);
_setupMocks
();
when
(
mockFlutterDevice
.
device
).
thenReturn
(
mockWebServerDevice
);
when
(
mockWebDevFS
.
update
(
...
...
@@ -454,10 +509,13 @@ void main() {
}));
test
(
'web resident runner is debuggable'
,
()
=>
testbed
.
run
(()
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
kAttachExpectations
.
toList
());
expect
(
residentWebRunner
.
debuggingEnabled
,
true
);
}));
test
(
'web resident runner can toggle CanvasKit'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
final
WebAssetServer
webAssetServer
=
WebAssetServer
(
null
,
null
,
null
,
null
,
null
);
when
(
mockWebDevFS
.
webAssetServer
).
thenReturn
(
webAssetServer
);
...
...
@@ -471,6 +529,7 @@ void main() {
}));
test
(
'Exits when initial compile fails'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
_setupMocks
();
when
(
mockWebDevFS
.
update
(
mainUri:
anyNamed
(
'mainUri'
),
...
...
@@ -501,30 +560,34 @@ void main() {
}));
test
(
'Faithfully displays stdout messages with leading/trailing spaces'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachLogExpectations
,
FakeVmServiceStreamResponse
(
streamId:
'Stdout'
,
event:
vm_service
.
Event
(
timestamp:
0
,
kind:
vm_service
.
EventStreams
.
kStdout
,
bytes:
base64
.
encode
(
utf8
.
encode
(
' This is a message with 4 leading and trailing spaces '
),
),
),
),
...
kAttachIsolateExpectations
,
]);
_setupMocks
();
final
StreamController
<
Event
>
stdoutController
=
StreamController
<
Event
>();
when
(
mockVmService
.
onStdoutEvent
).
thenAnswer
((
Invocation
invocation
)
{
return
stdoutController
.
stream
;
});
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
await
connectionInfoCompleter
.
future
;
stdoutController
.
add
(
Event
(
timestamp:
0
,
kind:
'Stdout'
,
bytes:
base64
.
encode
(
utf8
.
encode
(
' This is a message with 4 leading and trailing spaces '
))),
);
// Wait one event loop for the stream listener to fire.
await
null
;
expect
(
testLogger
.
statusText
,
contains
(
' This is a message with 4 leading and trailing spaces '
));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'Fails on compilation errors in hot restart'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
kAttachExpectations
.
toList
());
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
...
...
@@ -559,62 +622,55 @@ void main() {
}));
test
(
'Fails non-fatally on vmservice response error for hot restart'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
id:
'5'
,
method:
'hotRestart'
,
args:
null
,
jsonResponse:
<
String
,
Object
>{
'type'
:
'Failed'
,
}
)
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
await
connectionInfoCompleter
.
future
;
when
(
mockVmService
.
callMethod
(
'hotRestart'
)).
thenAnswer
((
Invocation
_
)
async
{
return
Response
.
parse
(<
String
,
Object
>{
'type'
:
'Failed'
});
});
final
OperationResult
result
=
await
residentWebRunner
.
restart
(
fullRestart:
false
);
expect
(
result
.
code
,
0
);
}));
test
(
'Fails fatally on vmservice RpcError'
,
()
=>
testbed
.
run
(()
async
{
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
await
connectionInfoCompleter
.
future
;
when
(
mockVmService
.
callMethod
(
'hotRestart'
)).
thenThrow
(
RPCError
(
'Something went wrong'
,
2
,
'123'
));
final
OperationResult
result
=
await
residentWebRunner
.
restart
(
fullRestart:
false
);
expect
(
result
.
code
,
1
);
expect
(
result
.
message
,
contains
(
'Something went wrong'
));
}));
test
(
'Fails fatally on vmservice WipError'
,
()
=>
testbed
.
run
(()
async
{
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
await
connectionInfoCompleter
.
future
;
when
(
mockVmService
.
callMethod
(
'hotRestart'
)).
thenThrow
(
WipError
(<
String
,
String
>{}));
final
OperationResult
result
=
await
residentWebRunner
.
restart
(
fullRestart:
false
);
expect
(
result
.
code
,
1
);
expect
(
result
.
code
,
0
);
}));
test
(
'Fails fatally on vmservice Exception'
,
()
=>
testbed
.
run
(()
async
{
test
(
'Fails fatally on Vm Service error response'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
id:
'5'
,
method:
'hotRestart'
,
args:
null
,
// Failed response,
errorCode:
RPCErrorCodes
.
kInternalError
,
),
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
await
connectionInfoCompleter
.
future
;
when
(
mockVmService
.
callMethod
(
'hotRestart'
)).
thenThrow
(
Exception
(
'Something went wrong'
));
final
OperationResult
result
=
await
residentWebRunner
.
restart
(
fullRestart:
false
);
expect
(
result
.
code
,
1
);
expect
(
result
.
message
,
contains
(
'Something went wrong'
));
expect
(
result
.
message
,
contains
(
RPCErrorCodes
.
kInternalError
.
toString
()));
}));
test
(
'printHelp without details has web warning'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
residentWebRunner
.
printHelp
(
details:
false
);
expect
(
testLogger
.
statusText
,
contains
(
'Warning'
));
...
...
@@ -623,6 +679,16 @@ void main() {
}));
test
(
'debugDumpApp'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
id:
'5'
,
method:
'ext.flutter.debugDumpApp'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
},
),
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
...
...
@@ -631,10 +697,20 @@ void main() {
await
connectionInfoCompleter
.
future
;
await
residentWebRunner
.
debugDumpApp
();
verify
(
mockVmService
.
callServiceExtension
(
'ext.flutter.debugDumpApp'
)).
called
(
1
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'debugDumpLayerTree'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
id:
'5'
,
method:
'ext.flutter.debugDumpLayerTree'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
},
),
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
...
...
@@ -643,10 +719,20 @@ void main() {
await
connectionInfoCompleter
.
future
;
await
residentWebRunner
.
debugDumpLayerTree
();
verify
(
mockVmService
.
callServiceExtension
(
'ext.flutter.debugDumpLayerTree'
)).
called
(
1
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'debugDumpRenderTree'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
id:
'5'
,
method:
'ext.flutter.debugDumpRenderTree'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
},
),
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
...
...
@@ -655,10 +741,20 @@ void main() {
await
connectionInfoCompleter
.
future
;
await
residentWebRunner
.
debugDumpRenderTree
();
verify
(
mockVmService
.
callServiceExtension
(
'ext.flutter.debugDumpRenderTree'
)).
called
(
1
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'debugDumpSemanticsTreeInTraversalOrder'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
id:
'5'
,
method:
'ext.flutter.debugDumpSemanticsTreeInTraversalOrder'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
},
),
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
...
...
@@ -667,113 +763,224 @@ void main() {
await
connectionInfoCompleter
.
future
;
await
residentWebRunner
.
debugDumpSemanticsTreeInTraversalOrder
();
verify
(
mockVmService
.
callServiceExtension
(
'ext.flutter.debugDumpSemanticsTreeInTraversalOrder'
)).
called
(
1
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'debugDumpSemanticsTreeInInverseHitTestOrder'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
id:
'5'
,
method:
'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
},
),
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
await
connectionInfoCompleter
.
future
;
await
residentWebRunner
.
debugDumpSemanticsTreeInInverseHitTestOrder
();
verify
(
mockVmService
.
callServiceExtension
(
'ext.flutter.debugDumpSemanticsTreeInInverseHitTestOrder'
)).
called
(
1
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'debugToggleDebugPaintSizeEnabled'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
id:
'5'
,
method:
'ext.flutter.debugPaint'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
},
jsonResponse:
<
String
,
Object
>{
'enabled'
:
'false'
},
),
const
FakeVmServiceRequest
(
id:
'6'
,
method:
'ext.flutter.debugPaint'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
'enabled'
:
'true'
,
},
jsonResponse:
<
String
,
Object
>{
'value'
:
'true'
},
)
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
await
connectionInfoCompleter
.
future
;
when
(
mockVmService
.
callServiceExtension
(
'ext.flutter.debugPaint'
))
.
thenAnswer
((
Invocation
_
)
async
{
return
Response
.
parse
(<
String
,
Object
>{
'enabled'
:
false
});
});
await
residentWebRunner
.
debugToggleDebugPaintSizeEnabled
();
verify
(
mockVmService
.
callServiceExtension
(
'ext.flutter.debugPaint'
,
args:
<
String
,
Object
>{
'enabled'
:
true
})).
called
(
1
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'debugTogglePerformanceOverlayOverride'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
id:
'5'
,
method:
'ext.flutter.showPerformanceOverlay'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
},
jsonResponse:
<
String
,
Object
>{
'enabled'
:
'false'
},
),
const
FakeVmServiceRequest
(
id:
'6'
,
method:
'ext.flutter.showPerformanceOverlay'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
'enabled'
:
'true'
,
},
jsonResponse:
<
String
,
Object
>{
'enabled'
:
'true'
},
)
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
await
connectionInfoCompleter
.
future
;
when
(
mockVmService
.
callServiceExtension
(
'ext.flutter.showPerformanceOverlay'
))
.
thenAnswer
((
Invocation
_
)
async
{
return
Response
.
parse
(<
String
,
Object
>{
'enabled'
:
false
});
});
await
residentWebRunner
.
debugTogglePerformanceOverlayOverride
();
verify
(
mockVmService
.
callServiceExtension
(
'ext.flutter.showPerformanceOverlay'
,
args:
<
String
,
Object
>{
'enabled'
:
true
})).
called
(
1
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'debugToggleWidgetInspector'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
id:
'5'
,
method:
'ext.flutter.inspector.show'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
},
jsonResponse:
<
String
,
Object
>{
'enabled'
:
'false'
},
),
const
FakeVmServiceRequest
(
id:
'6'
,
method:
'ext.flutter.inspector.show'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
'enabled'
:
'true'
,
},
jsonResponse:
<
String
,
Object
>{
'enabled'
:
'true'
},
)
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
await
connectionInfoCompleter
.
future
;
when
(
mockVmService
.
callServiceExtension
(
'ext.flutter.debugToggleWidgetInspector'
))
.
thenAnswer
((
Invocation
_
)
async
{
return
Response
.
parse
(<
String
,
Object
>{
'enabled'
:
false
});
});
await
residentWebRunner
.
debugToggleWidgetInspector
();
verify
(
mockVmService
.
callServiceExtension
(
'ext.flutter.debugToggleWidgetInspector'
,
args:
<
String
,
Object
>{
'enabled'
:
true
})).
called
(
1
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'debugToggleProfileWidgetBuilds'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
id:
'5'
,
method:
'ext.flutter.profileWidgetBuilds'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
},
jsonResponse:
<
String
,
Object
>{
'enabled'
:
'false'
},
),
const
FakeVmServiceRequest
(
id:
'6'
,
method:
'ext.flutter.profileWidgetBuilds'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
'enabled'
:
'true'
,
},
jsonResponse:
<
String
,
Object
>{
'enabled'
:
'true'
},
)
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
await
connectionInfoCompleter
.
future
;
when
(
mockVmService
.
callServiceExtension
(
'ext.flutter.profileWidgetBuilds'
))
.
thenAnswer
((
Invocation
_
)
async
{
return
Response
.
parse
(<
String
,
Object
>{
'enabled'
:
false
});
});
await
residentWebRunner
.
debugToggleProfileWidgetBuilds
();
verify
(
mockVmService
.
callServiceExtension
(
'ext.flutter.profileWidgetBuilds'
,
args:
<
String
,
Object
>{
'enabled'
:
true
})).
called
(
1
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'debugTogglePlatform'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
const
FakeVmServiceRequest
(
id:
'5'
,
method:
'ext.flutter.platformOverride'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
},
jsonResponse:
<
String
,
Object
>{
'value'
:
'iOS'
},
),
const
FakeVmServiceRequest
(
id:
'6'
,
method:
'ext.flutter.platformOverride'
,
args:
<
String
,
Object
>{
'isolateId'
:
null
,
'value'
:
'fuchsia'
,
},
jsonResponse:
<
String
,
Object
>{
'value'
:
'fuchsia'
},
),
]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
unawaited
(
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
));
await
connectionInfoCompleter
.
future
;
when
(
mockVmService
.
callServiceExtension
(
'ext.flutter.platformOverride'
))
.
thenAnswer
((
Invocation
_
)
async
{
return
Response
.
parse
(<
String
,
Object
>{
'value'
:
'iOS'
});
});
await
residentWebRunner
.
debugTogglePlatform
();
expect
(
testLogger
.
statusText
,
contains
(
'Switched operating system to fuchsia'
));
verify
(
mockVmService
.
callServiceExtension
(
'ext.flutter.platformOverride'
,
args:
<
String
,
Object
>{
'value'
:
'fuchsia'
})).
called
(
1
);
expect
(
testLogger
.
statusText
,
contains
(
'Switched operating system to fuchsia'
));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'cleanup of resources is safe to call multiple times'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
]);
_setupMocks
();
bool
debugClosed
=
false
;
when
(
mockDevice
.
stopApp
(
any
)).
thenAnswer
((
Invocation
invocation
)
async
{
...
...
@@ -793,9 +1000,13 @@ void main() {
await
residentWebRunner
.
exit
();
verifyNever
(
mockDebugConnection
.
close
());
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'cleans up Chrome if tab is closed'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
]);
_setupMocks
();
final
Completer
<
void
>
onDone
=
Completer
<
void
>();
when
(
mockDebugConnection
.
onDone
).
thenAnswer
((
Invocation
invocation
)
{
...
...
@@ -809,9 +1020,13 @@ void main() {
onDone
.
complete
();
await
result
;
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'Prints target and device name on run'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachExpectations
,
]);
_setupMocks
();
when
(
mockDevice
.
name
).
thenReturn
(
'Chromez'
);
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
...
...
@@ -820,10 +1035,32 @@ void main() {
));
await
connectionInfoCompleter
.
future
;
expect
(
testLogger
.
statusText
,
contains
(
'Launching
${globals.fs.path.join('lib', 'main.dart')}
on Chromez in debug mode'
));
expect
(
testLogger
.
statusText
,
contains
(
'Launching
${globals.fs.path.join('lib', 'main.dart')}
on '
'Chromez in debug mode'
,
));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'Sends launched app.webLaunchUrl event for Chrome device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
...
kAttachLogExpectations
,
const
FakeVmServiceRequest
(
id:
'3'
,
method:
'streamListen'
,
args:
<
String
,
Object
>{
'streamId'
:
'Isolate'
}
),
const
FakeVmServiceRequest
(
id:
'4'
,
method:
'registerService'
,
args:
<
String
,
Object
>{
'service'
:
'reloadSources'
,
'alias'
:
'FlutterTools'
,
}
)
]);
_setupMocks
();
when
(
mockFlutterDevice
.
device
).
thenReturn
(
ChromeDevice
());
when
(
mockWebDevFS
.
create
()).
thenAnswer
((
Invocation
invocation
)
async
{
...
...
@@ -870,12 +1107,14 @@ void main() {
},
},
)));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
},
overrides:
<
Type
,
Generator
>{
Logger:
()
=>
DelegateLogger
(
BufferLogger
.
test
()),
ChromeLauncher:
()
=>
MockChromeLauncher
(),
}));
test
(
'Sends unlaunched app.webLaunchUrl event for Web Server device'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
_setupMocks
();
when
(
mockFlutterDevice
.
device
).
thenReturn
(
WebServerDevice
());
when
(
mockWebDevFS
.
create
()).
thenAnswer
((
Invocation
invocation
)
async
{
...
...
@@ -910,106 +1149,65 @@ void main() {
},
},
)));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
},
overrides:
<
Type
,
Generator
>{
Logger:
()
=>
DelegateLogger
(
BufferLogger
.
test
())
}));
test
(
'Successfully turns WebSocketException into ToolExit'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
final
Completer
<
void
>
unhandledErrorCompleter
=
Completer
<
void
>();
when
(
mockWebDevFS
.
connect
(
any
)).
thenAnswer
((
Invocation
_
)
async
{
unawaited
(
unhandledErrorCompleter
.
future
.
then
((
void
value
)
{
throw
const
WebSocketException
();
}));
return
ConnectionResult
(
mockAppConnection
,
mockDebugConnection
);
});
final
Future
<
void
>
expectation
=
expectLater
(()
=>
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
),
throwsToolExit
());
when
(
mockWebDevFS
.
connect
(
any
))
.
thenThrow
(
const
WebSocketException
());
unhandledErrorCompleter
.
complete
(
);
await
expectation
;
await
expectLater
(()
=>
residentWebRunner
.
run
(),
throwsToolExit
()
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
)
;
}));
test
(
'Successfully turns AppConnectionException into ToolExit'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
final
Completer
<
void
>
unhandledErrorCompleter
=
Completer
<
void
>();
when
(
mockWebDevFS
.
connect
(
any
)).
thenAnswer
((
Invocation
_
)
async
{
unawaited
(
unhandledErrorCompleter
.
future
.
then
((
void
value
)
{
throw
AppConnectionException
(
'Could not connect to application with appInstanceId: c0ae0750-ee91-11e9-cea6-35d95a968356'
);
}));
return
ConnectionResult
(
mockAppConnection
,
mockDebugConnection
);
});
final
Future
<
void
>
expectation
=
expectLater
(()
=>
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
),
throwsToolExit
());
when
(
mockWebDevFS
.
connect
(
any
))
.
thenThrow
(
AppConnectionException
(
''
));
unhandledErrorCompleter
.
complete
(
);
await
expectation
;
await
expectLater
(()
=>
residentWebRunner
.
run
(),
throwsToolExit
()
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
)
;
}));
test
(
'Successfully turns ChromeDebugError into ToolExit'
,
()
=>
testbed
.
run
(()
async
{
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
final
Completer
<
void
>
unhandledErrorCompleter
=
Completer
<
void
>();
when
(
mockWebDevFS
.
connect
(
any
)).
thenAnswer
((
Invocation
_
)
async
{
unawaited
(
unhandledErrorCompleter
.
future
.
then
((
void
value
)
{
throw
ChromeDebugException
(<
String
,
dynamic
>{});
}));
return
ConnectionResult
(
mockAppConnection
,
mockDebugConnection
);
});
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
_setupMocks
();
final
Future
<
void
>
expectation
=
expectLater
(()
=>
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
),
throwsToolExit
());
when
(
mockWebDevFS
.
connect
(
any
))
.
thenThrow
(
ChromeDebugException
(<
String
,
dynamic
>{}));
unhandledErrorCompleter
.
complete
(
);
await
expectation
;
await
expectLater
(()
=>
residentWebRunner
.
run
(),
throwsToolExit
()
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
)
;
}));
test
(
'Rethrows Exception type'
,
()
=>
testbed
.
run
(()
async
{
test
(
'Rethrows unknown Exception type from dwds'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
_setupMocks
();
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
final
Completer
<
void
>
unhandledErrorCompleter
=
Completer
<
void
>();
when
(
mockWebDevFS
.
connect
(
any
)).
thenAnswer
((
Invocation
_
)
async
{
unawaited
(
unhandledErrorCompleter
.
future
.
then
((
void
value
)
{
throw
Exception
(
'Something went wrong'
);
}));
return
ConnectionResult
(
mockAppConnection
,
mockDebugConnection
);
});
when
(
mockWebDevFS
.
connect
(
any
)).
thenThrow
(
Exception
());
final
Future
<
void
>
expectation
=
expectLater
(()
=>
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
),
throwsException
);
unhandledErrorCompleter
.
complete
();
await
expectation
;
await
expectLater
(()
=>
residentWebRunner
.
run
(),
throwsException
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
}));
test
(
'Rethrows unknown exception type from web tooling'
,
()
=>
testbed
.
run
(()
async
{
test
(
'Rethrows unknown Error type from dwds tooling'
,
()
=>
testbed
.
run
(()
async
{
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[]);
_setupMocks
();
final
DelegateLogger
delegateLogger
=
globals
.
logger
as
DelegateLogger
;
final
MockStatus
mockStatus
=
MockStatus
();
delegateLogger
.
status
=
mockStatus
;
final
Completer
<
DebugConnectionInfo
>
connectionInfoCompleter
=
Completer
<
DebugConnectionInfo
>();
final
Completer
<
void
>
unhandledErrorCompleter
=
Completer
<
void
>();
when
(
mockWebDevFS
.
connect
(
any
)).
thenAnswer
((
Invocation
_
)
async
{
unawaited
(
unhandledErrorCompleter
.
future
.
then
((
void
value
)
{
throw
StateError
(
'Something went wrong'
);
}));
return
ConnectionResult
(
mockAppConnection
,
mockDebugConnection
);
});
final
Future
<
void
>
expectation
=
expectLater
(()
=>
residentWebRunner
.
run
(
connectionInfoCompleter:
connectionInfoCompleter
,
),
throwsStateError
);
when
(
mockWebDevFS
.
connect
(
any
)).
thenThrow
(
StateError
(
''
));
unhandledErrorCompleter
.
complete
();
await
expectation
;
await
expectLater
(()
=>
residentWebRunner
.
run
(),
throwsStateError
);
verify
(
mockStatus
.
stop
()).
called
(
1
);
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
},
overrides:
<
Type
,
Generator
>{
Logger:
()
=>
DelegateLogger
(
BufferLogger
(
terminal:
AnsiTerminal
(
...
...
packages/flutter_tools/test/general.shard/vmservice_test.dart
View file @
9202e547
...
...
@@ -6,7 +6,6 @@ import 'dart:async';
import
'package:flutter_tools/src/base/common.dart'
;
import
'package:flutter_tools/src/convert.dart'
;
import
'package:meta/meta.dart'
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
import
'package:mockito/mockito.dart'
;
import
'package:flutter_tools/src/base/logger.dart'
;
...
...
@@ -285,10 +284,10 @@ void main() {
testWithoutContext
(
'runInView forwards arguments correctly'
,
()
async
{
final
FakeVmServiceHost
fakeVmServiceHost
=
FakeVmServiceHost
(
requests:
<
VmServiceExpectation
>[
const
FakeVmServiceRequest
(
method:
'streamListen'
,
id:
'1'
,
param
s:
<
String
,
Object
>{
const
FakeVmServiceRequest
(
method:
'streamListen'
,
id:
'1'
,
arg
s:
<
String
,
Object
>{
'streamId'
:
'Isolate'
}),
const
FakeVmServiceRequest
(
method:
kRunInViewMethod
,
id:
'2'
,
param
s:
<
String
,
Object
>{
const
FakeVmServiceRequest
(
method:
kRunInViewMethod
,
id:
'2'
,
arg
s:
<
String
,
Object
>{
'viewId'
:
'1234'
,
'mainScript'
:
'main.dart'
,
'assetDirectory'
:
'flutter_assets/'
,
...
...
@@ -312,95 +311,6 @@ void main() {
});
}
class
FakeVmServiceHost
{
FakeVmServiceHost
({
@required
List
<
VmServiceExpectation
>
requests
,
})
:
_requests
=
requests
{
_vmService
=
vm_service
.
VmService
(
_input
.
stream
,
_output
.
add
,
);
_applyStreamListen
();
_output
.
stream
.
listen
((
String
data
)
{
final
Map
<
String
,
Object
>
request
=
json
.
decode
(
data
)
as
Map
<
String
,
Object
>;
if
(
_requests
.
isEmpty
)
{
throw
Exception
(
'Unexpected request:
$request
'
);
}
final
FakeVmServiceRequest
fakeRequest
=
_requests
.
removeAt
(
0
)
as
FakeVmServiceRequest
;
expect
(
fakeRequest
,
isA
<
FakeVmServiceRequest
>()
.
having
((
FakeVmServiceRequest
request
)
=>
request
.
method
,
'method'
,
request
[
'method'
])
.
having
((
FakeVmServiceRequest
request
)
=>
request
.
id
,
'id'
,
request
[
'id'
])
.
having
((
FakeVmServiceRequest
request
)
=>
request
.
params
,
'params'
,
request
[
'params'
])
);
_input
.
add
(
json
.
encode
(<
String
,
Object
>{
'jsonrpc'
:
'2.0'
,
'id'
:
fakeRequest
.
id
,
'result'
:
fakeRequest
.
jsonResponse
??
<
String
,
Object
>{
'type'
:
'Success'
},
}));
_applyStreamListen
();
});
}
final
List
<
VmServiceExpectation
>
_requests
;
final
StreamController
<
String
>
_input
=
StreamController
<
String
>();
final
StreamController
<
String
>
_output
=
StreamController
<
String
>();
vm_service
.
VmService
get
vmService
=>
_vmService
;
vm_service
.
VmService
_vmService
;
bool
get
hasRemainingExpectations
=>
_requests
.
isNotEmpty
;
// remove FakeStreamResponse objects from _requests until it is empty
// or until we hit a FakeRequest
void
_applyStreamListen
()
{
while
(
_requests
.
isNotEmpty
&&
!
_requests
.
first
.
isRequest
)
{
final
FakeVmServiceStreamResponse
response
=
_requests
.
removeAt
(
0
)
as
FakeVmServiceStreamResponse
;
_input
.
add
(
json
.
encode
(<
String
,
Object
>{
'jsonrpc'
:
'2.0'
,
'method'
:
'streamNotify'
,
'params'
:
<
String
,
Object
>{
'streamId'
:
response
.
streamId
,
'event'
:
response
.
event
.
toJson
(),
},
}));
}
}
}
abstract
class
VmServiceExpectation
{
bool
get
isRequest
;
}
class
FakeVmServiceRequest
implements
VmServiceExpectation
{
const
FakeVmServiceRequest
({
@required
this
.
method
,
@required
this
.
id
,
@required
this
.
params
,
this
.
jsonResponse
,
});
final
String
method
;
final
String
id
;
final
Map
<
String
,
Object
>
params
;
final
Map
<
String
,
Object
>
jsonResponse
;
@override
bool
get
isRequest
=>
true
;
}
class
FakeVmServiceStreamResponse
implements
VmServiceExpectation
{
const
FakeVmServiceStreamResponse
({
@required
this
.
event
,
@required
this
.
streamId
,
});
final
vm_service
.
Event
event
;
final
String
streamId
;
@override
bool
get
isRequest
=>
false
;
}
class
MockDevice
extends
Mock
implements
Device
{}
class
MockVMService
extends
Mock
implements
vm_service
.
VmService
{}
class
MockFlutterVersion
extends
Mock
implements
FlutterVersion
{
...
...
packages/flutter_tools/test/src/common.dart
View file @
9202e547
...
...
@@ -5,10 +5,12 @@
import
'dart:async'
;
import
'package:args/command_runner.dart'
;
import
'package:flutter_tools/src/convert.dart'
;
import
'package:vm_service/vm_service.dart'
as
vm_service
;
import
'package:flutter_tools/src/base/common.dart'
;
import
'package:flutter_tools/src/base/context.dart'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/base/process.dart'
;
import
'package:flutter_tools/src/commands/create.dart'
;
import
'package:flutter_tools/src/runner/flutter_command.dart'
;
...
...
@@ -217,3 +219,109 @@ class NoContext implements AppContext {
return
body
();
}
}
/// A fake implementation of a vm_service that mocks the JSON-RPC request
/// and response structure.
class
FakeVmServiceHost
{
FakeVmServiceHost
({
@required
List
<
VmServiceExpectation
>
requests
,
})
:
_requests
=
requests
{
_vmService
=
vm_service
.
VmService
(
_input
.
stream
,
_output
.
add
,
);
_applyStreamListen
();
_output
.
stream
.
listen
((
String
data
)
{
final
Map
<
String
,
Object
>
request
=
json
.
decode
(
data
)
as
Map
<
String
,
Object
>;
if
(
_requests
.
isEmpty
)
{
throw
Exception
(
'Unexpected request:
$request
'
);
}
final
FakeVmServiceRequest
fakeRequest
=
_requests
.
removeAt
(
0
)
as
FakeVmServiceRequest
;
expect
(
request
,
isA
<
Map
<
String
,
Object
>>()
.
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
)
);
if
(
fakeRequest
.
errorCode
==
null
)
{
_input
.
add
(
json
.
encode
(<
String
,
Object
>{
'jsonrpc'
:
'2.0'
,
'id'
:
fakeRequest
.
id
,
'result'
:
fakeRequest
.
jsonResponse
??
<
String
,
Object
>{
'type'
:
'Success'
},
}));
}
else
{
_input
.
add
(
json
.
encode
(<
String
,
Object
>{
'jsonrpc'
:
'2.0'
,
'id'
:
fakeRequest
.
id
,
'error'
:
<
String
,
Object
>{
'code'
:
fakeRequest
.
errorCode
,
}
}));
}
_applyStreamListen
();
});
}
final
List
<
VmServiceExpectation
>
_requests
;
final
StreamController
<
String
>
_input
=
StreamController
<
String
>();
final
StreamController
<
String
>
_output
=
StreamController
<
String
>();
vm_service
.
VmService
get
vmService
=>
_vmService
;
vm_service
.
VmService
_vmService
;
bool
get
hasRemainingExpectations
=>
_requests
.
isNotEmpty
;
// remove FakeStreamResponse objects from _requests until it is empty
// or until we hit a FakeRequest
void
_applyStreamListen
()
{
while
(
_requests
.
isNotEmpty
&&
!
_requests
.
first
.
isRequest
)
{
final
FakeVmServiceStreamResponse
response
=
_requests
.
removeAt
(
0
)
as
FakeVmServiceStreamResponse
;
_input
.
add
(
json
.
encode
(<
String
,
Object
>{
'jsonrpc'
:
'2.0'
,
'method'
:
'streamNotify'
,
'params'
:
<
String
,
Object
>{
'streamId'
:
response
.
streamId
,
'event'
:
response
.
event
.
toJson
(),
},
}));
}
}
}
abstract
class
VmServiceExpectation
{
bool
get
isRequest
;
}
class
FakeVmServiceRequest
implements
VmServiceExpectation
{
const
FakeVmServiceRequest
({
@required
this
.
method
,
@required
this
.
id
,
@required
this
.
args
,
this
.
jsonResponse
,
this
.
errorCode
,
});
final
String
method
;
final
String
id
;
/// If non-null, the error code for a [vm_service.RPCError] in place of a
/// standard response.
final
int
errorCode
;
final
Map
<
String
,
Object
>
args
;
final
Map
<
String
,
Object
>
jsonResponse
;
@override
bool
get
isRequest
=>
true
;
}
class
FakeVmServiceStreamResponse
implements
VmServiceExpectation
{
const
FakeVmServiceStreamResponse
({
@required
this
.
event
,
@required
this
.
streamId
,
});
final
vm_service
.
Event
event
;
final
String
streamId
;
@override
bool
get
isRequest
=>
false
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment