Unverified Commit 305a855f authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Migrate integration test shard test data to null safety (#92147)

parent 12ec91a5
...@@ -2,15 +2,13 @@ ...@@ -2,15 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:file/file.dart'; import 'package:file/file.dart';
import '../test_utils.dart'; import '../test_utils.dart';
abstract class DeferredComponentsConfig { abstract class DeferredComponentsConfig {
String get deferredLibrary; String get deferredLibrary;
String get deferredComponentsGolden; String? get deferredComponentsGolden;
String get androidSettings; String get androidSettings;
String get androidBuild; String get androidBuild;
String get androidLocalProperties; String get androidLocalProperties;
...@@ -30,8 +28,9 @@ abstract class DeferredComponentsConfig { ...@@ -30,8 +28,9 @@ abstract class DeferredComponentsConfig {
if (deferredLibrary != null) { if (deferredLibrary != null) {
writeFile(fileSystem.path.join(dir.path, 'lib', 'deferred_library.dart'), deferredLibrary); writeFile(fileSystem.path.join(dir.path, 'lib', 'deferred_library.dart'), deferredLibrary);
} }
if (deferredComponentsGolden != null) { final String? golden = deferredComponentsGolden;
writeFile(fileSystem.path.join(dir.path, 'deferred_components_loading_units.yaml'), deferredComponentsGolden); if (golden != null) {
writeFile(fileSystem.path.join(dir.path, 'deferred_components_loading_units.yaml'), golden);
} }
if (androidSettings != null) { if (androidSettings != null) {
writeFile(fileSystem.path.join(dir.path, 'android', 'settings.gradle'), androidSettings); writeFile(fileSystem.path.join(dir.path, 'android', 'settings.gradle'), androidSettings);
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io' as io; // flutter_ignore: dart_io_import import 'dart:io' as io; // flutter_ignore: dart_io_import
...@@ -13,7 +11,6 @@ import 'package:flutter_tools/src/base/common.dart'; ...@@ -13,7 +11,6 @@ import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/utils.dart'; import 'package:flutter_tools/src/base/utils.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import 'package:vm_service/vm_service.dart'; import 'package:vm_service/vm_service.dart';
import 'package:vm_service/vm_service_io.dart'; import 'package:vm_service/vm_service_io.dart';
...@@ -42,28 +39,28 @@ const Duration quitTimeout = Duration(seconds: 10); ...@@ -42,28 +39,28 @@ const Duration quitTimeout = Duration(seconds: 10);
abstract class FlutterTestDriver { abstract class FlutterTestDriver {
FlutterTestDriver( FlutterTestDriver(
this._projectFolder, { this._projectFolder, {
String logPrefix, String? logPrefix,
}) : _logPrefix = logPrefix != null ? '$logPrefix: ' : ''; }) : _logPrefix = logPrefix != null ? '$logPrefix: ' : '';
final Directory _projectFolder; final Directory _projectFolder;
final String _logPrefix; final String _logPrefix;
Process _process; Process? _process;
int _processPid; int? _processPid;
final StreamController<String> _stdout = StreamController<String>.broadcast(); final StreamController<String> _stdout = StreamController<String>.broadcast();
final StreamController<String> _stderr = StreamController<String>.broadcast(); final StreamController<String> _stderr = StreamController<String>.broadcast();
final StreamController<String> _allMessages = StreamController<String>.broadcast(); final StreamController<String> _allMessages = StreamController<String>.broadcast();
final StringBuffer _errorBuffer = StringBuffer(); final StringBuffer _errorBuffer = StringBuffer();
String _lastResponse; String? _lastResponse;
Uri _vmServiceWsUri; Uri? _vmServiceWsUri;
int _attachPort; int? _attachPort;
bool _hasExited = false; bool _hasExited = false;
VmService _vmService; VmService? _vmService;
String get lastErrorInfo => _errorBuffer.toString(); String get lastErrorInfo => _errorBuffer.toString();
Stream<String> get stdout => _stdout.stream; Stream<String> get stdout => _stdout.stream;
int get vmServicePort => _vmServiceWsUri.port; int? get vmServicePort => _vmServiceWsUri?.port;
bool get hasExited => _hasExited; bool get hasExited => _hasExited;
Uri get vmServiceWsUri => _vmServiceWsUri; Uri? get vmServiceWsUri => _vmServiceWsUri;
String lastTime = ''; String lastTime = '';
void _debugPrint(String message, { String topic = '' }) { void _debugPrint(String message, { String topic = '' }) {
...@@ -89,7 +86,7 @@ abstract class FlutterTestDriver { ...@@ -89,7 +86,7 @@ abstract class FlutterTestDriver {
Future<void> _setupProcess( Future<void> _setupProcess(
List<String> arguments, { List<String> arguments, {
String script, String? script,
bool withDebugger = false, bool withDebugger = false,
bool singleWidgetReloads = false, bool singleWidgetReloads = false,
}) async { }) async {
...@@ -122,12 +119,12 @@ abstract class FlutterTestDriver { ...@@ -122,12 +119,12 @@ abstract class FlutterTestDriver {
// This class doesn't use the result of the future. It's made available // This class doesn't use the result of the future. It's made available
// via a getter for external uses. // via a getter for external uses.
unawaited(_process.exitCode.then((int code) { unawaited(_process!.exitCode.then((int code) {
_debugPrint('Process exited ($code)'); _debugPrint('Process exited ($code)');
_hasExited = true; _hasExited = true;
})); }));
transformToLines(_process.stdout).listen(_stdout.add); transformToLines(_process!.stdout).listen(_stdout.add);
transformToLines(_process.stderr).listen(_stderr.add); transformToLines(_process!.stderr).listen(_stderr.add);
// Capture stderr to a buffer so we can show it all if any requests fail. // Capture stderr to a buffer so we can show it all if any requests fail.
_stderr.stream.listen(_errorBuffer.writeln); _stderr.stream.listen(_errorBuffer.writeln);
...@@ -137,18 +134,18 @@ abstract class FlutterTestDriver { ...@@ -137,18 +134,18 @@ abstract class FlutterTestDriver {
_stderr.stream.listen((String message) => _debugPrint(message, topic: '<=stderr=')); _stderr.stream.listen((String message) => _debugPrint(message, topic: '<=stderr='));
} }
Future<void> get done => _process.exitCode; Future<void> get done async => _process?.exitCode;
Future<void> connectToVmService({ bool pauseOnExceptions = false }) async { Future<void> connectToVmService({ bool pauseOnExceptions = false }) async {
_vmService = await vmServiceConnectUri('$_vmServiceWsUri'); _vmService = await vmServiceConnectUri('$_vmServiceWsUri');
_vmService.onSend.listen((String s) => _debugPrint(s, topic: '=vm=>')); _vmService!.onSend.listen((String s) => _debugPrint(s, topic: '=vm=>'));
_vmService.onReceive.listen((String s) => _debugPrint(s, topic: '<=vm=')); _vmService!.onReceive.listen((String s) => _debugPrint(s, topic: '<=vm='));
final Completer<void> isolateStarted = Completer<void>(); final Completer<void> isolateStarted = Completer<void>();
_vmService.onIsolateEvent.listen((Event event) { _vmService!.onIsolateEvent.listen((Event event) {
if (event.kind == EventKind.kIsolateStart) { if (event.kind == EventKind.kIsolateStart) {
isolateStarted.complete(); isolateStarted.complete();
} else if (event.kind == EventKind.kIsolateExit && event.isolate.id == _flutterIsolateId) { } else if (event.kind == EventKind.kIsolateExit && event.isolate?.id == _flutterIsolateId) {
// Hot restarts cause all the isolates to exit, so we need to refresh // Hot restarts cause all the isolates to exit, so we need to refresh
// our idea of what the Flutter isolate ID is. // our idea of what the Flutter isolate ID is.
_flutterIsolateId = null; _flutterIsolateId = null;
...@@ -156,17 +153,17 @@ abstract class FlutterTestDriver { ...@@ -156,17 +153,17 @@ abstract class FlutterTestDriver {
}); });
await Future.wait(<Future<Success>>[ await Future.wait(<Future<Success>>[
_vmService.streamListen('Isolate'), _vmService!.streamListen('Isolate'),
_vmService.streamListen('Debug'), _vmService!.streamListen('Debug'),
]); ]);
if ((await _vmService.getVM()).isolates.isEmpty) { if ((await _vmService!.getVM()).isolates?.isEmpty != false) {
await isolateStarted.future; await isolateStarted.future;
} }
await waitForPause(); await waitForPause();
if (pauseOnExceptions) { if (pauseOnExceptions) {
await _vmService.setExceptionPauseMode( await _vmService!.setExceptionPauseMode(
await _getFlutterIsolateId(), await _getFlutterIsolateId(),
ExceptionPauseMode.kUnhandled, ExceptionPauseMode.kUnhandled,
); );
...@@ -175,9 +172,9 @@ abstract class FlutterTestDriver { ...@@ -175,9 +172,9 @@ abstract class FlutterTestDriver {
Future<Response> callServiceExtension( Future<Response> callServiceExtension(
String extension, { String extension, {
Map<String, dynamic> args = const <String, dynamic>{}, Map<String, Object?> args = const <String, Object>{},
}) async { }) async {
final int port = _vmServiceWsUri != null ? vmServicePort : _attachPort; final int? port = _vmServiceWsUri != null ? vmServicePort : _attachPort;
final VmService vmService = await vmServiceConnectUri('ws://localhost:$port/ws'); final VmService vmService = await vmServiceConnectUri('ws://localhost:$port/ws');
final Isolate isolate = await waitForExtension(vmService, extension); final Isolate isolate = await waitForExtension(vmService, extension);
return vmService.callServiceExtension( return vmService.callServiceExtension(
...@@ -203,29 +200,29 @@ abstract class FlutterTestDriver { ...@@ -203,29 +200,29 @@ abstract class FlutterTestDriver {
}); });
_debugPrint('Sending SIGTERM to $_processPid..'); _debugPrint('Sending SIGTERM to $_processPid..');
io.Process.killPid(_processPid, io.ProcessSignal.sigterm); io.Process.killPid(_processPid!);
return _process.exitCode.timeout(quitTimeout, onTimeout: _killForcefully); return _process!.exitCode.timeout(quitTimeout, onTimeout: _killForcefully);
} }
Future<int> _killForcefully() { Future<int> _killForcefully() {
_debugPrint('Sending SIGKILL to $_processPid..'); _debugPrint('Sending SIGKILL to $_processPid..');
ProcessSignal.sigkill.send(_processPid); ProcessSignal.sigkill.send(_processPid!);
return _process.exitCode; return _process!.exitCode;
} }
String _flutterIsolateId; String? _flutterIsolateId;
Future<String> _getFlutterIsolateId() async { Future<String> _getFlutterIsolateId() async {
// Currently these tests only have a single isolate. If this // Currently these tests only have a single isolate. If this
// ceases to be the case, this code will need changing. // ceases to be the case, this code will need changing.
if (_flutterIsolateId == null) { if (_flutterIsolateId == null) {
final VM vm = await _vmService.getVM(); final VM vm = await _vmService!.getVM();
_flutterIsolateId = vm.isolates.single.id; _flutterIsolateId = vm.isolates!.single.id;
} }
return _flutterIsolateId; return _flutterIsolateId!;
} }
Future<Isolate> getFlutterIsolate() async { Future<Isolate> getFlutterIsolate() async {
final Isolate isolate = await _vmService.getIsolate(await _getFlutterIsolateId()); final Isolate isolate = await _vmService!.getIsolate(await _getFlutterIsolateId());
return isolate; return isolate;
} }
...@@ -247,7 +244,7 @@ abstract class FlutterTestDriver { ...@@ -247,7 +244,7 @@ abstract class FlutterTestDriver {
Future<void> addBreakpoint(Uri uri, int line) async { Future<void> addBreakpoint(Uri uri, int line) async {
_debugPrint('Sending breakpoint for: $uri:$line'); _debugPrint('Sending breakpoint for: $uri:$line');
await _vmService.addBreakpointWithScriptUri( await _vmService!.addBreakpointWithScriptUri(
await _getFlutterIsolateId(), await _getFlutterIsolateId(),
uri.toString(), uri.toString(),
line, line,
...@@ -286,10 +283,10 @@ abstract class FlutterTestDriver { ...@@ -286,10 +283,10 @@ abstract class FlutterTestDriver {
Future<Event> subscribeToDebugEvent(String kind, String isolateId) { Future<Event> subscribeToDebugEvent(String kind, String isolateId) {
_debugPrint('Start listening for $kind events'); _debugPrint('Start listening for $kind events');
return _vmService.onDebugEvent return _vmService!.onDebugEvent
.where((Event event) { .where((Event event) {
return event.isolate.id == isolateId return event.isolate?.id == isolateId
&& event.kind.startsWith(kind); && event.kind?.startsWith(kind) == true;
}).first; }).first;
} }
...@@ -302,85 +299,87 @@ abstract class FlutterTestDriver { ...@@ -302,85 +299,87 @@ abstract class FlutterTestDriver {
// But also check if the isolate was already at the state we need (only after we've // But also check if the isolate was already at the state we need (only after we've
// set up the subscription) to avoid races. If it already in the desired state, we // set up the subscription) to avoid races. If it already in the desired state, we
// don't need to wait for the event. // don't need to wait for the event.
final Isolate isolate = await _vmService.getIsolate(isolateId); final VmService vmService = _vmService!;
if (isolate.pauseEvent.kind.startsWith(kind)) { final Isolate isolate = await vmService.getIsolate(isolateId);
_debugPrint('Isolate was already at "$kind" (${isolate.pauseEvent.kind}).'); if (isolate.pauseEvent?.kind?.startsWith(kind) == true) {
_debugPrint('Isolate was already at "$kind" (${isolate.pauseEvent!.kind}).');
event.ignore(); event.ignore();
} else { } else {
_debugPrint('Waiting for "$kind" event to arrive...'); _debugPrint('Waiting for "$kind" event to arrive...');
await event; await event;
} }
return _vmService.getIsolate(isolateId); return vmService.getIsolate(isolateId);
}, },
task: 'Waiting for isolate to $kind', task: 'Waiting for isolate to $kind',
); );
} }
Future<Isolate> resume({ bool waitForNextPause = false }) => _resume(null, waitForNextPause); Future<Isolate?> resume({ bool waitForNextPause = false }) => _resume(null, waitForNextPause);
Future<Isolate> stepOver({ bool waitForNextPause = true }) => _resume(StepOption.kOver, waitForNextPause); Future<Isolate?> stepOver({ bool waitForNextPause = true }) => _resume(StepOption.kOver, waitForNextPause);
Future<Isolate> stepOverAsync({ bool waitForNextPause = true }) => _resume(StepOption.kOverAsyncSuspension, waitForNextPause); Future<Isolate?> stepOverAsync({ bool waitForNextPause = true }) => _resume(StepOption.kOverAsyncSuspension, waitForNextPause);
Future<Isolate> stepInto({ bool waitForNextPause = true }) => _resume(StepOption.kInto, waitForNextPause); Future<Isolate?> stepInto({ bool waitForNextPause = true }) => _resume(StepOption.kInto, waitForNextPause);
Future<Isolate> stepOut({ bool waitForNextPause = true }) => _resume(StepOption.kOut, waitForNextPause); Future<Isolate?> stepOut({ bool waitForNextPause = true }) => _resume(StepOption.kOut, waitForNextPause);
Future<bool> isAtAsyncSuspension() async { Future<bool> isAtAsyncSuspension() async {
final Isolate isolate = await getFlutterIsolate(); final Isolate isolate = await getFlutterIsolate();
return isolate.pauseEvent.atAsyncSuspension == true; return isolate.pauseEvent?.atAsyncSuspension == true;
} }
Future<Isolate> stepOverOrOverAsyncSuspension({ bool waitForNextPause = true }) async { Future<Isolate?> stepOverOrOverAsyncSuspension({ bool waitForNextPause = true }) async {
if (await isAtAsyncSuspension()) { if (await isAtAsyncSuspension()) {
return stepOverAsync(waitForNextPause: waitForNextPause); return stepOverAsync(waitForNextPause: waitForNextPause);
} }
return stepOver(waitForNextPause: waitForNextPause); return stepOver(waitForNextPause: waitForNextPause);
} }
Future<Isolate> _resume(String step, bool waitForNextPause) async { Future<Isolate?> _resume(String? step, bool waitForNextPause) async {
assert(waitForNextPause != null); assert(waitForNextPause != null);
final String isolateId = await _getFlutterIsolateId(); final String isolateId = await _getFlutterIsolateId();
final Future<Event> resume = subscribeToResumeEvent(isolateId); final Future<Event> resume = subscribeToResumeEvent(isolateId);
final Future<Event> pause = subscribeToPauseEvent(isolateId); final Future<Event> pause = subscribeToPauseEvent(isolateId);
await _timeoutWithMessages<dynamic>( await _timeoutWithMessages<Object?>(
() async => _vmService.resume(isolateId, step: step), () async => _vmService!.resume(isolateId, step: step),
task: 'Resuming isolate (step=$step)', task: 'Resuming isolate (step=$step)',
); );
await waitForResumeEvent(isolateId, resume); await waitForResumeEvent(isolateId, resume);
return waitForNextPause? waitForPauseEvent(isolateId, pause): null; return waitForNextPause ? waitForPauseEvent(isolateId, pause) : null;
} }
Future<ObjRef> evaluateInFrame(String expression) async { Future<ObjRef> evaluateInFrame(String expression) async {
return _timeoutWithMessages<ObjRef>( return _timeoutWithMessages<ObjRef>(
() async => await _vmService.evaluateInFrame(await _getFlutterIsolateId(), 0, expression) as ObjRef, () async => await _vmService!.evaluateInFrame(await _getFlutterIsolateId(), 0, expression) as ObjRef,
task: 'Evaluating expression ($expression)', task: 'Evaluating expression ($expression)',
); );
} }
Future<InstanceRef> evaluate(String targetId, String expression) async { Future<InstanceRef> evaluate(String targetId, String expression) async {
return _timeoutWithMessages<InstanceRef>( return _timeoutWithMessages<InstanceRef>(
() async => await _vmService.evaluate(await _getFlutterIsolateId(), targetId, expression) as InstanceRef, () async => await _vmService!.evaluate(await _getFlutterIsolateId(), targetId, expression) as InstanceRef,
task: 'Evaluating expression ($expression for $targetId)', task: 'Evaluating expression ($expression for $targetId)',
); );
} }
Future<Frame> getTopStackFrame() async { Future<Frame> getTopStackFrame() async {
final String flutterIsolateId = await _getFlutterIsolateId(); final String flutterIsolateId = await _getFlutterIsolateId();
final Stack stack = await _vmService.getStack(flutterIsolateId); final Stack stack = await _vmService!.getStack(flutterIsolateId);
if (stack.frames.isEmpty) { final List<Frame>? frames = stack.frames;
if (frames == null || frames.isEmpty) {
throw Exception('Stack is empty'); throw Exception('Stack is empty');
} }
return stack.frames.first; return frames.first;
} }
Future<SourcePosition> getSourceLocation() async { Future<SourcePosition?> getSourceLocation() async {
final String flutterIsolateId = await _getFlutterIsolateId(); final String flutterIsolateId = await _getFlutterIsolateId();
final Frame frame = await getTopStackFrame(); final Frame frame = await getTopStackFrame();
final Script script = await _vmService.getObject(flutterIsolateId, frame.location.script.id) as Script; final Script script = await _vmService!.getObject(flutterIsolateId, frame.location!.script!.id!) as Script;
return _lookupTokenPos(script.tokenPosTable, frame.location.tokenPos); return _lookupTokenPos(script.tokenPosTable!, frame.location!.tokenPos!);
} }
SourcePosition _lookupTokenPos(List<List<int>> table, int tokenPos) { SourcePosition? _lookupTokenPos(List<List<int>> table, int tokenPos) {
for (final List<int> row in table) { for (final List<int> row in table) {
final int lineNumber = row[0]; final int lineNumber = row[0];
int index = 1; int index = 1;
...@@ -395,9 +394,9 @@ abstract class FlutterTestDriver { ...@@ -395,9 +394,9 @@ abstract class FlutterTestDriver {
return null; return null;
} }
Future<Map<String, dynamic>> _waitFor({ Future<Map<String, Object?>> _waitFor({
String event, String? event,
int id, int? id,
Duration timeout = defaultTimeout, Duration timeout = defaultTimeout,
bool ignoreAppStopEvent = false, bool ignoreAppStopEvent = false,
}) async { }) async {
...@@ -405,30 +404,31 @@ abstract class FlutterTestDriver { ...@@ -405,30 +404,31 @@ abstract class FlutterTestDriver {
assert(event != null || id != null); assert(event != null || id != null);
assert(event == null || id == null); assert(event == null || id == null);
final String interestingOccurrence = event != null ? '$event event' : 'response to request $id'; final String interestingOccurrence = event != null ? '$event event' : 'response to request $id';
final Completer<Map<String, dynamic>> response = Completer<Map<String, dynamic>>(); final Completer<Map<String, Object?>> response = Completer<Map<String, Object?>>();
StreamSubscription<String> subscription; StreamSubscription<String>? subscription;
subscription = _stdout.stream.listen((String line) async { subscription = _stdout.stream.listen((String line) async {
final Map<String, dynamic> json = parseFlutterResponse(line); final Map<String, Object?>? json = parseFlutterResponse(line);
_lastResponse = line; _lastResponse = line;
if (json == null) { if (json == null) {
return; return;
} }
if ((event != null && json['event'] == event) || if ((event != null && json['event'] == event) ||
(id != null && json['id'] == id)) { (id != null && json['id'] == id)) {
await subscription.cancel(); await subscription?.cancel();
_debugPrint('OK ($interestingOccurrence)'); _debugPrint('OK ($interestingOccurrence)');
response.complete(json); response.complete(json);
} else if (!ignoreAppStopEvent && json['event'] == 'app.stop') { } else if (!ignoreAppStopEvent && json['event'] == 'app.stop') {
await subscription.cancel(); await subscription?.cancel();
final StringBuffer error = StringBuffer(); final StringBuffer error = StringBuffer();
error.write('Received app.stop event while waiting for $interestingOccurrence\n\n$_errorBuffer'); error.write('Received app.stop event while waiting for $interestingOccurrence\n\n$_errorBuffer');
if (json['params'] != null) { final Object? jsonParams = json['params'];
final Map<String, dynamic> params = json['params'] as Map<String, dynamic>; if (jsonParams is Map<String, Object?>) {
if (params['error'] != null) { if (jsonParams['error'] != null) {
error.write('${params['error']}\n\n'); error.write('${jsonParams['error']}\n\n');
} }
if (json['params'] != null && params['trace'] != null) { final Object? trace = jsonParams['trace'];
error.write('${params['trace']}\n\n'); if (trace != null) {
error.write('$trace\n\n');
} }
} }
response.completeError(Exception(error.toString())); response.completeError(Exception(error.toString()));
...@@ -444,7 +444,7 @@ abstract class FlutterTestDriver { ...@@ -444,7 +444,7 @@ abstract class FlutterTestDriver {
Future<T> _timeoutWithMessages<T>( Future<T> _timeoutWithMessages<T>(
Future<T> Function() callback, { Future<T> Function() callback, {
@required String task, required String task,
Duration timeout = defaultTimeout, Duration timeout = defaultTimeout,
}) { }) {
assert(task != null); assert(task != null);
...@@ -476,7 +476,7 @@ abstract class FlutterTestDriver { ...@@ -476,7 +476,7 @@ abstract class FlutterTestDriver {
}); });
final Future<T> future = callback().whenComplete(longWarning.cancel); final Future<T> future = callback().whenComplete(longWarning.cancel);
return future.catchError((dynamic error) { return future.catchError((Object error) {
if (!timeoutExpired) { if (!timeoutExpired) {
timeoutExpired = true; timeoutExpired = true;
_debugPrint(messages.toString()); _debugPrint(messages.toString());
...@@ -489,11 +489,11 @@ abstract class FlutterTestDriver { ...@@ -489,11 +489,11 @@ abstract class FlutterTestDriver {
class FlutterRunTestDriver extends FlutterTestDriver { class FlutterRunTestDriver extends FlutterTestDriver {
FlutterRunTestDriver( FlutterRunTestDriver(
Directory projectFolder, { Directory projectFolder, {
String logPrefix, String? logPrefix,
this.spawnDdsInstance = true, this.spawnDdsInstance = true,
}) : super(projectFolder, logPrefix: logPrefix); }) : super(projectFolder, logPrefix: logPrefix);
String _currentRunningAppId; String? _currentRunningAppId;
Future<void> run({ Future<void> run({
bool withDebugger = false, bool withDebugger = false,
...@@ -503,8 +503,8 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -503,8 +503,8 @@ class FlutterRunTestDriver extends FlutterTestDriver {
bool expressionEvaluation = true, bool expressionEvaluation = true,
bool structuredErrors = false, bool structuredErrors = false,
bool singleWidgetReloads = false, bool singleWidgetReloads = false,
String script, String? script,
List<String> additionalCommandArgs, List<String>? additionalCommandArgs,
}) async { }) async {
await _setupProcess( await _setupProcess(
<String>[ <String>[
...@@ -541,7 +541,7 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -541,7 +541,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
bool startPaused = false, bool startPaused = false,
bool pauseOnExceptions = false, bool pauseOnExceptions = false,
bool singleWidgetReloads = false, bool singleWidgetReloads = false,
List<String> additionalCommandArgs, List<String>? additionalCommandArgs,
}) async { }) async {
_attachPort = port; _attachPort = port;
await _setupProcess( await _setupProcess(
...@@ -568,12 +568,12 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -568,12 +568,12 @@ class FlutterRunTestDriver extends FlutterTestDriver {
@override @override
Future<void> _setupProcess( Future<void> _setupProcess(
List<String> args, { List<String> args, {
String script, String? script,
bool withDebugger = false, bool withDebugger = false,
bool startPaused = false, bool startPaused = false,
bool pauseOnExceptions = false, bool pauseOnExceptions = false,
bool singleWidgetReloads = false, bool singleWidgetReloads = false,
int attachPort, int? attachPort,
}) async { }) async {
assert(!startPaused || withDebugger); assert(!startPaused || withDebugger);
await super._setupProcess( await super._setupProcess(
...@@ -589,7 +589,7 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -589,7 +589,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
// exited prematurely. This causes the currently suspended `await` to // exited prematurely. This causes the currently suspended `await` to
// deadlock until the test times out. Instead, this causes the test to fail // deadlock until the test times out. Instead, this causes the test to fail
// fast. // fast.
unawaited(_process.exitCode.then((_) { unawaited(_process?.exitCode.then((_) {
if (!prematureExitGuard.isCompleted) { if (!prematureExitGuard.isCompleted) {
prematureExitGuard.completeError(Exception('Process exited prematurely: ${args.join(' ')}: $_errorBuffer')); prematureExitGuard.completeError(Exception('Process exited prematurely: ${args.join(' ')}: $_errorBuffer'));
} }
...@@ -600,16 +600,16 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -600,16 +600,16 @@ class FlutterRunTestDriver extends FlutterTestDriver {
// Stash the PID so that we can terminate the VM more reliably than using // Stash the PID so that we can terminate the VM more reliably than using
// _process.kill() (`flutter` is a shell script so _process itself is a // _process.kill() (`flutter` is a shell script so _process itself is a
// shell, not the flutter tool's Dart process). // shell, not the flutter tool's Dart process).
final Map<String, dynamic> connected = await _waitFor(event: 'daemon.connected'); final Map<String, Object?> connected = await _waitFor(event: 'daemon.connected');
_processPid = (connected['params'] as Map<String, dynamic>)['pid'] as int; _processPid = (connected['params'] as Map<String, Object?>?)?['pid'] as int?;
// Set this up now, but we don't wait it yet. We want to make sure we don't // Set this up now, but we don't wait it yet. We want to make sure we don't
// miss it while waiting for debugPort below. // miss it while waiting for debugPort below.
final Future<Map<String, dynamic>> started = _waitFor(event: 'app.started', timeout: appStartTimeout); final Future<Map<String, Object?>> started = _waitFor(event: 'app.started', timeout: appStartTimeout);
if (withDebugger) { if (withDebugger) {
final Map<String, dynamic> debugPort = await _waitFor(event: 'app.debugPort', timeout: appStartTimeout); final Map<String, Object?> debugPort = await _waitFor(event: 'app.debugPort', timeout: appStartTimeout);
final String wsUriString = (debugPort['params'] as Map<String, dynamic>)['wsUri'] as String; final String wsUriString = (debugPort['params']! as Map<String, Object?>)['wsUri']! as String;
_vmServiceWsUri = Uri.parse(wsUriString); _vmServiceWsUri = Uri.parse(wsUriString);
await connectToVmService(pauseOnExceptions: pauseOnExceptions); await connectToVmService(pauseOnExceptions: pauseOnExceptions);
if (!startPaused) { if (!startPaused) {
...@@ -626,7 +626,7 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -626,7 +626,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
// Now await the started event; if it had already happened the future will // Now await the started event; if it had already happened the future will
// have already completed. // have already completed.
_currentRunningAppId = ((await started)['params'] as Map<String, dynamic>)['appId'] as String; _currentRunningAppId = ((await started)['params'] as Map<String, Object?>?)?['appId'] as String?;
prematureExitGuard.complete(); prematureExitGuard.complete();
} on Exception catch (error, stackTrace) { } on Exception catch (error, stackTrace) {
prematureExitGuard.completeError(Exception(error.toString()), stackTrace); prematureExitGuard.completeError(Exception(error.toString()), stackTrace);
...@@ -637,7 +637,7 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -637,7 +637,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
} }
Future<void> hotRestart({ bool pause = false, bool debounce = false}) => _restart(fullRestart: true, pause: pause); Future<void> hotRestart({ bool pause = false, bool debounce = false}) => _restart(fullRestart: true, pause: pause);
Future<void> hotReload({ bool debounce = false, int debounceDurationOverrideMs }) => Future<void> hotReload({ bool debounce = false, int? debounceDurationOverrideMs }) =>
_restart(debounce: debounce, debounceDurationOverrideMs: debounceDurationOverrideMs); _restart(debounce: debounce, debounceDurationOverrideMs: debounceDurationOverrideMs);
Future<void> scheduleFrame() async { Future<void> scheduleFrame() async {
...@@ -646,20 +646,20 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -646,20 +646,20 @@ class FlutterRunTestDriver extends FlutterTestDriver {
} }
await _sendRequest( await _sendRequest(
'app.callServiceExtension', 'app.callServiceExtension',
<String, dynamic>{'appId': _currentRunningAppId, 'methodName': 'ext.ui.window.scheduleFrame'}, <String, Object?>{'appId': _currentRunningAppId, 'methodName': 'ext.ui.window.scheduleFrame'},
); );
} }
Future<void> _restart({ bool fullRestart = false, bool pause = false, bool debounce = false, int debounceDurationOverrideMs }) async { Future<void> _restart({ bool fullRestart = false, bool pause = false, bool debounce = false, int? debounceDurationOverrideMs }) async {
if (_currentRunningAppId == null) { if (_currentRunningAppId == null) {
throw Exception('App has not started yet'); throw Exception('App has not started yet');
} }
_debugPrint('Performing ${ pause ? "paused " : "" }${ fullRestart ? "hot restart" : "hot reload" }...'); _debugPrint('Performing ${ pause ? "paused " : "" }${ fullRestart ? "hot restart" : "hot reload" }...');
final Map<String, dynamic> hotReloadResponse = await _sendRequest( final Map<String, Object?>? hotReloadResponse = await _sendRequest(
'app.restart', 'app.restart',
<String, dynamic>{'appId': _currentRunningAppId, 'fullRestart': fullRestart, 'pause': pause, 'debounce': debounce, 'debounceDurationOverrideMs': debounceDurationOverrideMs}, <String, Object?>{'appId': _currentRunningAppId, 'fullRestart': fullRestart, 'pause': pause, 'debounce': debounce, 'debounceDurationOverrideMs': debounceDurationOverrideMs},
) as Map<String, dynamic>; ) as Map<String, Object?>?;
_debugPrint('${fullRestart ? "Hot restart" : "Hot reload"} complete.'); _debugPrint('${fullRestart ? "Hot restart" : "Hot reload"} complete.');
if (hotReloadResponse == null || hotReloadResponse['code'] != 0) { if (hotReloadResponse == null || hotReloadResponse['code'] != 0) {
...@@ -668,20 +668,22 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -668,20 +668,22 @@ class FlutterRunTestDriver extends FlutterTestDriver {
} }
Future<int> detach() async { Future<int> detach() async {
if (_process == null) { final Process? process = _process;
if (process == null) {
return 0; return 0;
} }
if (_vmService != null) { final VmService? vmService = _vmService;
if (vmService != null) {
_debugPrint('Closing VM service...'); _debugPrint('Closing VM service...');
await _vmService.dispose(); await vmService.dispose();
} }
if (_currentRunningAppId != null) { if (_currentRunningAppId != null) {
_debugPrint('Detaching from app...'); _debugPrint('Detaching from app...');
await Future.any<void>(<Future<void>>[ await Future.any<void>(<Future<void>>[
_process.exitCode, process.exitCode,
_sendRequest( _sendRequest(
'app.detach', 'app.detach',
<String, dynamic>{'appId': _currentRunningAppId}, <String, Object?>{'appId': _currentRunningAppId},
), ),
]).timeout( ]).timeout(
quitTimeout, quitTimeout,
...@@ -690,21 +692,23 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -690,21 +692,23 @@ class FlutterRunTestDriver extends FlutterTestDriver {
_currentRunningAppId = null; _currentRunningAppId = null;
} }
_debugPrint('Waiting for process to end...'); _debugPrint('Waiting for process to end...');
return _process.exitCode.timeout(quitTimeout, onTimeout: _killGracefully); return process.exitCode.timeout(quitTimeout, onTimeout: _killGracefully);
} }
Future<int> stop() async { Future<int> stop() async {
if (_vmService != null) { final VmService? vmService = _vmService;
if (vmService != null) {
_debugPrint('Closing VM service...'); _debugPrint('Closing VM service...');
await _vmService.dispose(); await vmService.dispose();
} }
final Process? process = _process;
if (_currentRunningAppId != null) { if (_currentRunningAppId != null) {
_debugPrint('Stopping application...'); _debugPrint('Stopping application...');
await Future.any<void>(<Future<void>>[ await Future.any<void>(<Future<void>>[
_process.exitCode, process!.exitCode,
_sendRequest( _sendRequest(
'app.stop', 'app.stop',
<String, dynamic>{'appId': _currentRunningAppId}, <String, Object?>{'appId': _currentRunningAppId},
), ),
]).timeout( ]).timeout(
quitTimeout, quitTimeout,
...@@ -712,33 +716,33 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -712,33 +716,33 @@ class FlutterRunTestDriver extends FlutterTestDriver {
); );
_currentRunningAppId = null; _currentRunningAppId = null;
} }
if (_process != null) { if (process != null) {
_debugPrint('Waiting for process to end...'); _debugPrint('Waiting for process to end...');
return _process.exitCode.timeout(quitTimeout, onTimeout: _killGracefully); return process.exitCode.timeout(quitTimeout, onTimeout: _killGracefully);
} }
return 0; return 0;
} }
int id = 1; int id = 1;
Future<dynamic> _sendRequest(String method, dynamic params) async { Future<Object?> _sendRequest(String method, Object? params) async {
final int requestId = id++; final int requestId = id++;
final Map<String, dynamic> request = <String, dynamic>{ final Map<String, Object?> request = <String, Object?>{
'id': requestId, 'id': requestId,
'method': method, 'method': method,
'params': params, 'params': params,
}; };
final String jsonEncoded = json.encode(<Map<String, dynamic>>[request]); final String jsonEncoded = json.encode(<Map<String, Object?>>[request]);
_debugPrint(jsonEncoded, topic: '=stdin=>'); _debugPrint(jsonEncoded, topic: '=stdin=>');
// Set up the response future before we send the request to avoid any // Set up the response future before we send the request to avoid any
// races. If the method we're calling is app.stop then we tell _waitFor not // races. If the method we're calling is app.stop then we tell _waitFor not
// to throw if it sees an app.stop event before the response to this request. // to throw if it sees an app.stop event before the response to this request.
final Future<Map<String, dynamic>> responseFuture = _waitFor( final Future<Map<String, Object?>> responseFuture = _waitFor(
id: requestId, id: requestId,
ignoreAppStopEvent: method == 'app.stop', ignoreAppStopEvent: method == 'app.stop',
); );
_process.stdin.writeln(jsonEncoded); _process?.stdin.writeln(jsonEncoded);
final Map<String, dynamic> response = await responseFuture; final Map<String, Object?> response = await responseFuture;
if (response['error'] != null || response['result'] == null) { if (response['error'] != null || response['result'] == null) {
_throwErrorResponse('Unexpected error response'); _throwErrorResponse('Unexpected error response');
...@@ -755,7 +759,7 @@ class FlutterRunTestDriver extends FlutterTestDriver { ...@@ -755,7 +759,7 @@ class FlutterRunTestDriver extends FlutterTestDriver {
} }
class FlutterTestTestDriver extends FlutterTestDriver { class FlutterTestTestDriver extends FlutterTestDriver {
FlutterTestTestDriver(Directory _projectFolder, {String logPrefix}) FlutterTestTestDriver(Directory _projectFolder, {String? logPrefix})
: super(_projectFolder, logPrefix: logPrefix); : super(_projectFolder, logPrefix: logPrefix);
Future<void> test({ Future<void> test({
...@@ -763,7 +767,7 @@ class FlutterTestTestDriver extends FlutterTestDriver { ...@@ -763,7 +767,7 @@ class FlutterTestTestDriver extends FlutterTestDriver {
bool withDebugger = false, bool withDebugger = false,
bool pauseOnExceptions = false, bool pauseOnExceptions = false,
bool coverage = false, bool coverage = false,
Future<void> Function() beforeStart, Future<void> Function()? beforeStart,
}) async { }) async {
await _setupProcess(<String>[ await _setupProcess(<String>[
'test', 'test',
...@@ -778,10 +782,10 @@ class FlutterTestTestDriver extends FlutterTestDriver { ...@@ -778,10 +782,10 @@ class FlutterTestTestDriver extends FlutterTestDriver {
@override @override
Future<void> _setupProcess( Future<void> _setupProcess(
List<String> args, { List<String> args, {
String script, String? script,
bool withDebugger = false, bool withDebugger = false,
bool pauseOnExceptions = false, bool pauseOnExceptions = false,
Future<void> Function() beforeStart, Future<void> Function()? beforeStart,
bool singleWidgetReloads = false, bool singleWidgetReloads = false,
}) async { }) async {
await super._setupProcess( await super._setupProcess(
...@@ -794,13 +798,13 @@ class FlutterTestTestDriver extends FlutterTestDriver { ...@@ -794,13 +798,13 @@ class FlutterTestTestDriver extends FlutterTestDriver {
// Stash the PID so that we can terminate the VM more reliably than using // Stash the PID so that we can terminate the VM more reliably than using
// _proc.kill() (because _proc is a shell, because `flutter` is a shell // _proc.kill() (because _proc is a shell, because `flutter` is a shell
// script). // script).
final Map<String, dynamic> version = await _waitForJson(); final Map<String, Object?>? version = await _waitForJson();
_processPid = version['pid'] as int; _processPid = version?['pid'] as int?;
if (withDebugger) { if (withDebugger) {
final Map<String, dynamic> startedProcessParams = final Map<String, Object?> startedProcessParams =
(await _waitFor(event: 'test.startedProcess', timeout: appStartTimeout))['params'] as Map<String, dynamic>; (await _waitFor(event: 'test.startedProcess', timeout: appStartTimeout))['params']! as Map<String, Object?>;
final String vmServiceHttpString = startedProcessParams['observatoryUri'] as String; final String vmServiceHttpString = startedProcessParams['observatoryUri']! as String;
_vmServiceWsUri = Uri.parse(vmServiceHttpString).replace(scheme: 'ws', path: '/ws'); _vmServiceWsUri = Uri.parse(vmServiceHttpString).replace(scheme: 'ws', path: '/ws');
await connectToVmService(pauseOnExceptions: pauseOnExceptions); await connectToVmService(pauseOnExceptions: pauseOnExceptions);
// Allow us to run code before we start, eg. to set up breakpoints. // Allow us to run code before we start, eg. to set up breakpoints.
...@@ -811,19 +815,19 @@ class FlutterTestTestDriver extends FlutterTestDriver { ...@@ -811,19 +815,19 @@ class FlutterTestTestDriver extends FlutterTestDriver {
} }
} }
Future<Map<String, dynamic>> _waitForJson({ Future<Map<String, Object?>?> _waitForJson({
Duration timeout = defaultTimeout, Duration timeout = defaultTimeout,
}) async { }) async {
assert(timeout != null); assert(timeout != null);
return _timeoutWithMessages<Map<String, dynamic>>( return _timeoutWithMessages<Map<String, Object?>?>(
() => _stdout.stream.map<Map<String, dynamic>>(_parseJsonResponse) () => _stdout.stream.map<Map<String, Object?>?>(_parseJsonResponse)
.firstWhere((Map<String, dynamic> output) => output != null), .firstWhere((Map<String, Object?>? output) => output != null),
timeout: timeout, timeout: timeout,
task: 'Waiting for JSON', task: 'Waiting for JSON',
); );
} }
Map<String, dynamic> _parseJsonResponse(String line) { Map<String, Object?>? _parseJsonResponse(String line) {
try { try {
return castStringKeyedMap(json.decode(line)); return castStringKeyedMap(json.decode(line));
} on Exception { } on Exception {
...@@ -838,7 +842,7 @@ class FlutterTestTestDriver extends FlutterTestDriver { ...@@ -838,7 +842,7 @@ class FlutterTestTestDriver extends FlutterTestDriver {
// end of test run. // end of test run.
final StreamSubscription<String> subscription = _stdout.stream.listen( final StreamSubscription<String> subscription = _stdout.stream.listen(
(String line) async { (String line) async {
final Map<String, dynamic> json = _parseJsonResponse(line); final Map<String, Object?>? json = _parseJsonResponse(line);
if (json != null && json['type'] != null && json['success'] != null) { if (json != null && json['type'] != null && json['success'] != null) {
done.complete(json['type'] == 'done' && json['success'] == true); done.complete(json['type'] == 'done' && json['success'] == true);
} }
...@@ -846,9 +850,9 @@ class FlutterTestTestDriver extends FlutterTestDriver { ...@@ -846,9 +850,9 @@ class FlutterTestTestDriver extends FlutterTestDriver {
await resume(); await resume();
final Future<dynamic> timeoutFuture = final Future<Object> timeoutFuture =
Future<dynamic>.delayed(defaultTimeout); Future<Object>.delayed(defaultTimeout);
await Future.any<dynamic>(<Future<dynamic>>[done.future, timeoutFuture]); await Future.any<Object>(<Future<Object>>[done.future, timeoutFuture]);
await subscription.cancel(); await subscription.cancel();
if (!done.isCompleted) { if (!done.isCompleted) {
await quit(); await quit();
...@@ -860,10 +864,10 @@ Stream<String> transformToLines(Stream<List<int>> byteStream) { ...@@ -860,10 +864,10 @@ Stream<String> transformToLines(Stream<List<int>> byteStream) {
return byteStream.transform<String>(utf8.decoder).transform<String>(const LineSplitter()); return byteStream.transform<String>(utf8.decoder).transform<String>(const LineSplitter());
} }
Map<String, dynamic> parseFlutterResponse(String line) { Map<String, Object?>? parseFlutterResponse(String line) {
if (line.startsWith('[') && line.endsWith(']') && line.length > 2) { if (line.startsWith('[') && line.endsWith(']') && line.length > 2) {
try { try {
final Map<String, dynamic> response = castStringKeyedMap((json.decode(line) as List<dynamic>)[0]); final Map<String, Object?>? response = castStringKeyedMap((json.decode(line) as List<Object?>)[0]);
return response; return response;
} on FormatException { } on FormatException {
// Not valid JSON, so likely some other output that was surrounded by [brackets] // Not valid JSON, so likely some other output that was surrounded by [brackets]
...@@ -888,13 +892,13 @@ Future<Isolate> waitForExtension(VmService vmService, String extension) async { ...@@ -888,13 +892,13 @@ Future<Isolate> waitForExtension(VmService vmService, String extension) async {
// Do nothing, already subscribed. // Do nothing, already subscribed.
} }
vmService.onExtensionEvent.listen((Event event) { vmService.onExtensionEvent.listen((Event event) {
if (event.json['extensionKind'] == 'Flutter.FrameworkInitialization') { if (event.json?['extensionKind'] == 'Flutter.FrameworkInitialization') {
completer.complete(); completer.complete();
} }
}); });
final IsolateRef isolateRef = (await vmService.getVM()).isolates.first; final IsolateRef isolateRef = (await vmService.getVM()).isolates!.first;
final Isolate isolate = await vmService.getIsolate(isolateRef.id); final Isolate isolate = await vmService.getIsolate(isolateRef.id!);
if (isolate.extensionRPCs.contains(extension)) { if (isolate.extensionRPCs!.contains(extension)) {
return isolate; return isolate;
} }
await completer.future; await completer.future;
......
...@@ -2,13 +2,10 @@ ...@@ -2,13 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// @dart = 2.8
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/local.dart'; import 'package:file/local.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import 'package:vm_service/vm_service.dart'; import 'package:vm_service/vm_service.dart';
...@@ -91,18 +88,18 @@ List<String> getLocalEngineArguments() { ...@@ -91,18 +88,18 @@ List<String> getLocalEngineArguments() {
} }
Future<void> pollForServiceExtensionValue<T>({ Future<void> pollForServiceExtensionValue<T>({
@required FlutterTestDriver testDriver, required FlutterTestDriver testDriver,
@required String extension, required String extension,
@required T continuePollingValue, required T continuePollingValue,
@required Matcher matches, required Matcher matches,
String valueKey = 'value', String valueKey = 'value',
}) async { }) async {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
final Response response = await testDriver.callServiceExtension(extension); final Response response = await testDriver.callServiceExtension(extension);
if (response.json[valueKey] as T == continuePollingValue) { if (response.json?[valueKey] as T == continuePollingValue) {
await Future<void>.delayed(const Duration(seconds: 1)); await Future<void>.delayed(const Duration(seconds: 1));
} else { } else {
expect(response.json[valueKey] as T, matches); expect(response.json?[valueKey] as T, matches);
return; return;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment