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
342c6286
Unverified
Commit
342c6286
authored
May 13, 2020
by
Jia Hao
Committed by
GitHub
May 13, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Eagerly wait for the driver extension on FlutterDriver.connect() (#56428)
parent
4b814cf8
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
62 additions
and
46 deletions
+62
-46
vmservice_driver.dart
packages/flutter_driver/lib/src/driver/vmservice_driver.dart
+45
-45
flutter_driver_test.dart
packages/flutter_driver/test/flutter_driver_test.dart
+17
-1
No files found.
packages/flutter_driver/lib/src/driver/vmservice_driver.dart
View file @
342c6286
...
...
@@ -8,7 +8,6 @@ import 'dart:io';
import
'package:file/file.dart'
as
f
;
import
'package:fuchsia_remote_debug_protocol/fuchsia_remote_debug_protocol.dart'
as
fuchsia
;
import
'package:json_rpc_2/error_code.dart'
as
error_code
;
import
'package:json_rpc_2/json_rpc_2.dart'
as
rpc
;
import
'package:meta/meta.dart'
;
import
'package:path/path.dart'
as
p
;
...
...
@@ -150,11 +149,37 @@ class VMServiceFlutterDriver extends FlutterDriver {
}
/// Waits for a signal from the VM service that the extension is registered.
/// Returns [_flutterExtensionMethodName]
Future
<
String
>
waitForServiceExtension
()
{
return
isolate
.
onExtensionAdded
.
firstWhere
((
String
extension
)
{
return
extension
==
_flutterExtensionMethodName
;
});
///
/// Looks at the list of loaded extensions for the current [isolateRef], as
/// well as the stream of added extensions.
Future
<
void
>
waitForServiceExtension
()
async
{
final
Future
<
void
>
extensionAlreadyAdded
=
isolateRef
.
loadRunnable
()
.
then
((
VMIsolate
isolate
)
async
{
if
(
isolate
.
extensionRpcs
.
contains
(
_flutterExtensionMethodName
))
{
return
;
}
// Never complete. Rely on the stream listener to find the service
// extension instead.
return
Completer
<
void
>().
future
;
});
final
Completer
<
void
>
extensionAdded
=
Completer
<
void
>();
StreamSubscription
<
String
>
isolateAddedSubscription
;
isolateAddedSubscription
=
isolate
.
onExtensionAdded
.
listen
(
(
String
extensionName
)
{
if
(
extensionName
==
_flutterExtensionMethodName
)
{
extensionAdded
.
complete
();
isolateAddedSubscription
.
cancel
();
}
},
onError:
extensionAdded
.
completeError
,
cancelOnError:
true
);
await
Future
.
any
(<
Future
<
void
>>[
extensionAlreadyAdded
,
extensionAdded
.
future
,
]);
}
/// Tells the Dart VM Service to notify us about "Isolate" events.
...
...
@@ -174,25 +199,7 @@ class VMServiceFlutterDriver extends FlutterDriver {
if
(
isolate
.
pauseEvent
is
VMPauseStartEvent
)
{
_log
(
'Isolate is paused at start.'
);
// If the isolate is paused at the start, e.g. via the --start-paused
// option, then the VM service extension is not registered yet. Wait for
// it to be registered.
await
enableIsolateStreams
();
final
Future
<
String
>
whenServiceExtensionReady
=
waitForServiceExtension
();
final
Future
<
dynamic
>
whenResumed
=
resumeLeniently
();
await
whenResumed
;
_log
(
'Waiting for service extension'
);
// We will never receive the extension event if the user does not
// register it. If that happens, show a message but continue waiting.
await
_warnIfSlow
<
String
>(
future:
whenServiceExtensionReady
,
timeout:
kUnusuallyLongTimeout
,
message:
'Flutter Driver extension is taking a long time to become available. '
'Ensure your test app (often "lib/main.dart") imports '
'"package:flutter_driver/driver_extension.dart" and '
'calls enableFlutterDriverExtension() as the first call in main().'
,
);
await
resumeLeniently
();
}
else
if
(
isolate
.
pauseEvent
is
VMPauseExitEvent
||
isolate
.
pauseEvent
is
VMPauseBreakpointEvent
||
isolate
.
pauseEvent
is
VMPauseExceptionEvent
||
...
...
@@ -210,27 +217,20 @@ class VMServiceFlutterDriver extends FlutterDriver {
);
}
// Invoked checkHealth and try to fix delays in the registration of Service
// extensions
Future
<
Health
>
checkHealth
()
async
{
try
{
// At this point the service extension must be installed. Verify it.
return
await
driver
.
checkHealth
();
}
on
rpc
.
RpcException
catch
(
e
)
{
if
(
e
.
code
!=
error_code
.
METHOD_NOT_FOUND
)
{
rethrow
;
}
_log
(
'Check Health failed, try to wait for the service extensions to be '
'registered.'
);
await
enableIsolateStreams
();
await
waitForServiceExtension
();
return
driver
.
checkHealth
();
}
}
await
enableIsolateStreams
();
// We will never receive the extension event if the user does not register
// it. If that happens, show a message but continue waiting.
await
_warnIfSlow
<
void
>(
future:
waitForServiceExtension
(),
timeout:
kUnusuallyLongTimeout
,
message:
'Flutter Driver extension is taking a long time to become available. '
'Ensure your test app (often "lib/main.dart") imports '
'"package:flutter_driver/driver_extension.dart" and '
'calls enableFlutterDriverExtension() as the first call in main().'
,
);
final
Health
health
=
await
checkHealth
();
final
Health
health
=
await
driver
.
checkHealth
();
if
(
health
.
status
!=
HealthStatus
.
ok
)
{
await
client
.
close
();
throw
DriverError
(
'Flutter application health check failed.'
);
...
...
packages/flutter_driver/test/flutter_driver_test.dart
View file @
342c6286
...
...
@@ -49,6 +49,10 @@ void main() {
when
(
mockClient
.
getVM
()).
thenAnswer
((
_
)
=>
Future
<
MockVM
>.
value
(
mockVM
));
when
(
mockVM
.
isolates
).
thenReturn
(<
VMRunnableIsolate
>[
mockIsolate
]);
when
(
mockIsolate
.
loadRunnable
()).
thenAnswer
((
_
)
=>
Future
<
MockIsolate
>.
value
(
mockIsolate
));
when
(
mockIsolate
.
extensionRpcs
).
thenReturn
(<
String
>[]);
when
(
mockIsolate
.
onExtensionAdded
).
thenAnswer
((
Invocation
invocation
)
{
return
Stream
<
String
>.
fromIterable
(<
String
>[
'ext.flutter.driver'
]);
});
when
(
mockIsolate
.
invokeExtension
(
any
,
any
)).
thenAnswer
(
(
Invocation
invocation
)
=>
makeMockResponse
(<
String
,
dynamic
>{
'status'
:
'ok'
}));
vmServiceConnectFunction
=
(
String
url
,
{
Map
<
String
,
dynamic
>
headers
})
{
...
...
@@ -81,7 +85,7 @@ void main() {
final
FlutterDriver
driver
=
await
FlutterDriver
.
connect
(
dartVmServiceUrl:
''
);
expect
(
driver
,
isNotNull
);
expectLogContains
(
'Isolate is paused at start'
);
expect
(
connectionLog
,
<
String
>[
'
streamListen'
,
'onExtensionAdded'
,
'resume
'
]);
expect
(
connectionLog
,
<
String
>[
'
resume'
,
'streamListen'
,
'onExtensionAdded
'
]);
});
test
(
'connects to isolate paused mid-flight'
,
()
async
{
...
...
@@ -117,6 +121,18 @@ void main() {
expectLogContains
(
'Isolate is not paused. Assuming application is ready.'
);
});
test
(
'connects to unpaused when onExtensionAdded does not contain the '
'driver extension'
,
()
async
{
when
(
mockIsolate
.
pauseEvent
).
thenReturn
(
MockVMResumeEvent
());
when
(
mockIsolate
.
extensionRpcs
).
thenReturn
(<
String
>[
'ext.flutter.driver'
]);
when
(
mockIsolate
.
onExtensionAdded
).
thenAnswer
((
Invocation
invocation
)
{
return
const
Stream
<
String
>.
empty
();
});
final
FlutterDriver
driver
=
await
FlutterDriver
.
connect
(
dartVmServiceUrl:
''
);
expect
(
driver
,
isNotNull
);
expectLogContains
(
'Isolate is not paused. Assuming application is ready.'
);
});
test
(
'connects with headers'
,
()
async
{
Map
<
String
,
dynamic
>
actualHeaders
;
vmServiceConnectFunction
=
(
String
url
,
{
Map
<
String
,
dynamic
>
headers
})
{
...
...
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