From 937b98e1b9c6d318049a1be848a3073cf4b456c3 Mon Sep 17 00:00:00 2001 From: Carlo Bernaschina Date: Mon, 21 Aug 2017 13:21:00 -0700 Subject: [PATCH] Fix flakiness of commands_test (#11705) - Wait for full Hot Reload - Wait for full Restart - Fallback if checkHealth throws METHOD_NOT_FOUND. We try to wait for the service extensions to be registered and retry. --- dev/devicelab/bin/tasks/commands_test.dart | 6 ++ dev/devicelab/manifest.yaml | 1 - packages/flutter_driver/lib/src/driver.dart | 64 ++++++++++++++------- 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/dev/devicelab/bin/tasks/commands_test.dart b/dev/devicelab/bin/tasks/commands_test.dart index dc3ddebf68..f75a3d7083 100644 --- a/dev/devicelab/bin/tasks/commands_test.dart +++ b/dev/devicelab/bin/tasks/commands_test.dart @@ -77,15 +77,21 @@ void main() { await driver.drive('none'); final Future reloadStartingText = stdout.stream.firstWhere((String line) => line.endsWith('hot reload...')); + final Future reloadEndingText = + stdout.stream.firstWhere((String line) => line.contains('Hot reload performed in ')); print('test: pressing "r" to perform a hot reload...'); run.stdin.write('r'); await reloadStartingText; + await reloadEndingText; await driver.drive('none'); final Future restartStartingText = stdout.stream.firstWhere((String line) => line.endsWith('full restart...')); + final Future restartEndingText = + stdout.stream.firstWhere((String line) => line.contains('Restart performed in ')); print('test: pressing "R" to perform a full reload...'); run.stdin.write('R'); await restartStartingText; + await restartEndingText; await driver.drive('none'); run.stdin.write('q'); final int result = await run.exitCode; diff --git a/dev/devicelab/manifest.yaml b/dev/devicelab/manifest.yaml index c06e4427fb..a5e0b1108d 100644 --- a/dev/devicelab/manifest.yaml +++ b/dev/devicelab/manifest.yaml @@ -125,7 +125,6 @@ tasks: Runs tests of flutter run commands. stage: devicelab required_agent_capabilities: ["has-android-device"] - flaky: true android_sample_catalog_generator: description: > diff --git a/packages/flutter_driver/lib/src/driver.dart b/packages/flutter_driver/lib/src/driver.dart index 291d2e0807..03d8bd61ad 100644 --- a/packages/flutter_driver/lib/src/driver.dart +++ b/packages/flutter_driver/lib/src/driver.dart @@ -7,6 +7,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:file/file.dart' as f; +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; @@ -207,30 +208,30 @@ class FlutterDriver { }); } + // Waits for a signal from the VM service that the extension is registered + Future waitForServiceExtension() { + return isolate.onExtensionAdded.firstWhere((String extension) { + return extension == _kFlutterExtensionMethod; + }); + } + + /// Tells the Dart VM Service to notify us about "Isolate" events. + /// + /// This is a workaround for an issue in package:vm_service_client, which + /// subscribes to the "Isolate" stream lazily upon subscription, which + /// results in lost events. + /// + /// Details: https://github.com/dart-lang/vm_service_client/issues/17 + Future enableIsolateStreams() async { + await connection.peer.sendRequest('streamListen', { + 'streamId': 'Isolate', + }); + } + // Attempt to resume isolate if it was paused if (isolate.pauseEvent is VMPauseStartEvent) { _log.trace('Isolate is paused at start.'); - // Waits for a signal from the VM service that the extension is registered - Future waitForServiceExtension() { - return isolate.onExtensionAdded.firstWhere((String extension) { - return extension == _kFlutterExtensionMethod; - }); - } - - /// Tells the Dart VM Service to notify us about "Isolate" events. - /// - /// This is a workaround for an issue in package:vm_service_client, which - /// subscribes to the "Isolate" stream lazily upon subscription, which - /// results in lost events. - /// - /// Details: https://github.com/dart-lang/vm_service_client/issues/17 - Future enableIsolateStreams() async { - await connection.peer.sendRequest('streamListen', { - 'streamId': 'Isolate', - }); - } - // 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. @@ -269,8 +270,27 @@ class FlutterDriver { ); } - // At this point the service extension must be installed. Verify it. - final Health health = await driver.checkHealth(); + // Invoked checkHealth and try to fix delays in the registration of Service + // extensions + Future 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.trace( + 'Check Health failed, try to wait for the service extensions to be' + 'registered.' + ); + await enableIsolateStreams(); + await waitForServiceExtension().timeout(_kLongTimeout * 2); + return driver.checkHealth(); + } + } + + final Health health = await checkHealth(); if (health.status != HealthStatus.ok) { await client.close(); throw new DriverError('Flutter application health check failed.');