From ef5ffd08f6b306c517445a2d820816c1ffaa2f14 Mon Sep 17 00:00:00 2001 From: Darren Austin Date: Tue, 13 Jul 2021 12:14:50 -0700 Subject: [PATCH] Migrate devicelab framework code to null safety. (#86325) (Attempt to reland #85993) --- dev/devicelab/lib/command/test.dart | 20 ++- dev/devicelab/lib/command/upload_metrics.dart | 6 +- dev/devicelab/lib/framework/ab.dart | 43 +++--- dev/devicelab/lib/framework/apk_utils.dart | 33 +++-- dev/devicelab/lib/framework/browser.dart | 127 +++++++++--------- dev/devicelab/lib/framework/cocoon.dart | 55 ++++---- dev/devicelab/lib/framework/devices.dart | 124 +++++++++-------- dev/devicelab/lib/framework/framework.dart | 32 +++-- dev/devicelab/lib/framework/ios.dart | 19 +-- dev/devicelab/lib/framework/manifest.dart | 25 ++-- dev/devicelab/lib/framework/runner.dart | 42 +++--- .../lib/framework/running_processes.dart | 20 ++- dev/devicelab/lib/framework/task_result.dart | 12 +- dev/devicelab/lib/framework/utils.dart | 91 ++++++------- dev/devicelab/lib/microbenchmarks.dart | 2 - dev/devicelab/lib/tasks/analysis.dart | 2 - dev/devicelab/lib/tasks/build_test_task.dart | 11 +- .../lib/tasks/dart_plugin_registry_tests.dart | 6 +- dev/devicelab/lib/tasks/gallery.dart | 10 +- dev/devicelab/lib/tasks/hot_mode_tests.dart | 20 ++- .../lib/tasks/integration_tests.dart | 2 - dev/devicelab/lib/tasks/microbenchmarks.dart | 2 - dev/devicelab/lib/tasks/new_gallery.dart | 2 - dev/devicelab/lib/tasks/perf_tests.dart | 125 ++++++++--------- .../tasks/platform_channels_benchmarks.dart | 2 - dev/devicelab/lib/tasks/plugin_tests.dart | 14 +- dev/devicelab/lib/tasks/web_benchmarks.dart | 27 ++-- .../lib/tasks/web_dev_mode_tests.dart | 2 - 28 files changed, 406 insertions(+), 470 deletions(-) diff --git a/dev/devicelab/lib/command/test.dart b/dev/devicelab/lib/command/test.dart index feab3caca0..9e35fdde2d 100644 --- a/dev/devicelab/lib/command/test.dart +++ b/dev/devicelab/lib/command/test.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'package:args/command_runner.dart'; import 'package:flutter_devicelab/framework/runner.dart'; @@ -64,19 +62,19 @@ class TestCommand extends Command { @override Future run() async { - final List taskArgsRaw = argResults['task-args'] as List; + final List taskArgsRaw = argResults!['task-args'] as List; // Prepend '--' to convert args to options when passed to task final List taskArgs = taskArgsRaw.map((String taskArg) => '--$taskArg').toList(); print(taskArgs); await runTasks( - [argResults['task'] as String], - deviceId: argResults['device-id'] as String, - gitBranch: argResults['git-branch'] as String, - localEngine: argResults['local-engine'] as String, - localEngineSrcPath: argResults['local-engine-src-path'] as String, - luciBuilder: argResults['luci-builder'] as String, - resultsPath: argResults['results-file'] as String, - silent: argResults['silent'] as bool, + [argResults!['task'] as String], + deviceId: argResults!['device-id'] as String?, + gitBranch: argResults!['git-branch'] as String?, + localEngine: argResults!['local-engine'] as String?, + localEngineSrcPath: argResults!['local-engine-src-path'] as String?, + luciBuilder: argResults!['luci-builder'] as String?, + resultsPath: argResults!['results-file'] as String?, + silent: (argResults!['silent'] as bool?) ?? false, taskArgs: taskArgs, ); } diff --git a/dev/devicelab/lib/command/upload_metrics.dart b/dev/devicelab/lib/command/upload_metrics.dart index f44da32bc3..89742cb148 100644 --- a/dev/devicelab/lib/command/upload_metrics.dart +++ b/dev/devicelab/lib/command/upload_metrics.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'package:args/command_runner.dart'; import '../framework/cocoon.dart'; @@ -25,8 +23,8 @@ class UploadMetricsCommand extends Command { @override Future run() async { - final String resultsPath = argResults['results-file'] as String; - final String serviceAccountTokenFile = argResults['service-account-token-file'] as String; + final String resultsPath = argResults!['results-file'] as String; + final String? serviceAccountTokenFile = argResults!['service-account-token-file'] as String?; final Cocoon cocoon = Cocoon(serviceAccountTokenPath: serviceAccountTokenFile); return cocoon.sendResultsPath(resultsPath); diff --git a/dev/devicelab/lib/framework/ab.dart b/dev/devicelab/lib/framework/ab.dart index af3c737c27..4f214f9c88 100644 --- a/dev/devicelab/lib/framework/ab.dart +++ b/dev/devicelab/lib/framework/ab.dart @@ -2,10 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:math' as math; -import 'package:meta/meta.dart'; import 'task_result.dart'; @@ -43,8 +40,8 @@ class ABTest { final String localEngine; final String taskName; final DateTime runStart; - DateTime _runEnd; - DateTime get runEnd => _runEnd; + DateTime? _runEnd; + DateTime? get runEnd => _runEnd; final Map> _aResults; final Map> _bResults; @@ -91,15 +88,15 @@ class ABTest { kLocalEngineKeyName: localEngine, kTaskNameKeyName: taskName, kRunStartKeyName: runStart.toIso8601String(), - kRunEndKeyName: runEnd.toIso8601String(), + kRunEndKeyName: runEnd!.toIso8601String(), kAResultsKeyName: _aResults, kBResultsKeyName: _bResults, }; - static void updateColumnLengths(List lengths, List results) { + static void updateColumnLengths(List lengths, List results) { for (int column = 0; column < lengths.length; column++) { if (results[column] != null) { - lengths[column] = math.max(lengths[column], results[column].length); + lengths[column] = math.max(lengths[column], results[column]?.length ?? 0); } } } @@ -107,10 +104,10 @@ class ABTest { static void formatResult(StringBuffer buffer, List lengths, List aligns, - List values) { + List values) { for (int column = 0; column < lengths.length; column++) { final int len = lengths[column]; - String value = values[column]; + String? value = values[column]; if (value == null) { value = ''.padRight(len); } else { @@ -142,9 +139,9 @@ class ABTest { final Map summariesA = _summarize(_aResults); final Map summariesB = _summarize(_bResults); - final List> tableRows = >[ + final List> tableRows = >[ for (final String scoreKey in {...summariesA.keys, ...summariesB.keys}) - [ + [ scoreKey, summariesA[scoreKey]?.averageString, summariesA[scoreKey]?.noiseString, summariesB[scoreKey]?.averageString, summariesB[scoreKey]?.noiseString, @@ -167,7 +164,7 @@ class ABTest { final List lengths = List.filled(6, 0); updateColumnLengths(lengths, titles); - for (final List row in tableRows) { + for (final List row in tableRows) { updateColumnLengths(lengths, row); } @@ -177,7 +174,7 @@ class ABTest { FieldJustification.CENTER, ...alignments.skip(1), ], titles); - for (final List row in tableRows) { + for (final List row in tableRows) { formatResult(buffer, lengths, alignments, row); } @@ -192,7 +189,7 @@ class ABTest { buffer.writeln('$scoreKey:'); buffer.write(' A:\t'); if (_aResults.containsKey(scoreKey)) { - for (final double score in _aResults[scoreKey]) { + for (final double score in _aResults[scoreKey]!) { buffer.write('${score.toStringAsFixed(2)}\t'); } } else { @@ -202,7 +199,7 @@ class ABTest { buffer.write(' B:\t'); if (_bResults.containsKey(scoreKey)) { - for (final double score in _bResults[scoreKey]) { + for (final double score in _bResults[scoreKey]!) { buffer.write('${score.toStringAsFixed(2)}\t'); } } else { @@ -232,8 +229,8 @@ class ABTest { ); for (final String scoreKey in _allScoreKeys) { - final _ScoreSummary summaryA = summariesA[scoreKey]; - final _ScoreSummary summaryB = summariesB[scoreKey]; + final _ScoreSummary? summaryA = summariesA[scoreKey]; + final _ScoreSummary? summaryB = summariesB[scoreKey]; buffer.write('$scoreKey\t'); if (summaryA != null) { @@ -261,8 +258,8 @@ class ABTest { class _ScoreSummary { _ScoreSummary({ - @required this.average, - @required this.noise, + required this.average, + required this.noise, }); /// Average (arithmetic mean) of a series of values collected by a benchmark. @@ -275,14 +272,14 @@ class _ScoreSummary { String get averageString => average.toStringAsFixed(2); String get noiseString => '(${_ratioToPercent(noise)})'; - String improvementOver(_ScoreSummary other) { + String improvementOver(_ScoreSummary? other) { return other == null ? '' : '${(average / other.average).toStringAsFixed(2)}x'; } } void _addResult(TaskResult result, Map> results) { - for (final String scoreKey in result.benchmarkScoreKeys) { - final double score = (result.data[scoreKey] as num).toDouble(); + for (final String scoreKey in result.benchmarkScoreKeys ?? []) { + final double score = (result.data![scoreKey] as num).toDouble(); results.putIfAbsent(scoreKey, () => []).add(score); } } diff --git a/dev/devicelab/lib/framework/apk_utils.dart b/dev/devicelab/lib/framework/apk_utils.dart index 2def05b0d8..2baec6c682 100644 --- a/dev/devicelab/lib/framework/apk_utils.dart +++ b/dev/devicelab/lib/framework/apk_utils.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:io'; import 'package:path/path.dart' as path; @@ -106,7 +104,7 @@ bool hasMultipleOccurrences(String text, Pattern pattern) { /// The Android home directory. String get _androidHome { - final String androidHome = Platform.environment['ANDROID_HOME'] ?? + final String? androidHome = Platform.environment['ANDROID_HOME'] ?? Platform.environment['ANDROID_SDK_ROOT']; if (androidHome == null || androidHome.isEmpty) { throw Exception('Environment variable `ANDROID_SDK_ROOT` is not set.'); @@ -118,9 +116,9 @@ String get _androidHome { Future _evalApkAnalyzer( List args, { bool printStdout = false, - String workingDirectory, + String? workingDirectory, }) async { - final String javaHome = await findJavaHome(); + final String? javaHome = await findJavaHome(); if (javaHome == null || javaHome.isEmpty) { throw Exception('No JAVA_HOME set.'); } @@ -259,7 +257,7 @@ class FlutterProject { String get androidPath => path.join(rootPath, 'android'); String get iosPath => path.join(rootPath, 'ios'); - Future addCustomBuildType(String name, {String initWith}) async { + Future addCustomBuildType(String name, {required String initWith}) async { final File buildScript = File( path.join(androidPath, 'app', 'build.gradle'), ); @@ -276,7 +274,7 @@ android { '''); } - Future addGlobalBuildType(String name, {String initWith}) async { + Future addGlobalBuildType(String name, {required String initWith}) async { final File buildScript = File( path.join(androidPath, 'build.gradle'), ); @@ -360,11 +358,11 @@ flutter: pubspec.writeAsStringSync(newContents); } - Future runGradleTask(String task, {List options}) async { + Future runGradleTask(String task, {List? options}) async { return _runGradleTask(workingDirectory: androidPath, task: task, options: options); } - Future resultOfGradleTask(String task, {List options}) { + Future resultOfGradleTask(String task, {List? options}) { return _resultOfGradleTask(workingDirectory: androidPath, task: task, options: options); } @@ -416,7 +414,11 @@ class FlutterModuleProject { String get rootPath => path.join(parent.path, name); } -Future _runGradleTask({String workingDirectory, String task, List options}) async { +Future _runGradleTask({ + required String workingDirectory, + required String task, + List? options, +}) async { final ProcessResult result = await _resultOfGradleTask( workingDirectory: workingDirectory, task: task, @@ -431,10 +433,13 @@ Future _runGradleTask({String workingDirectory, String task, List throw 'Gradle exited with error'; } -Future _resultOfGradleTask({String workingDirectory, String task, - List options}) async { +Future _resultOfGradleTask({ + required String workingDirectory, + required String task, + List? options, +}) async { section('Find Java'); - final String javaHome = await findJavaHome(); + final String? javaHome = await findJavaHome(); if (javaHome == null) throw TaskResult.failure('Could not find Java'); @@ -465,7 +470,7 @@ Future _resultOfGradleTask({String workingDirectory, String task, } /// Returns [null] if target matches [expectedTarget], otherwise returns an error message. -String validateSnapshotDependency(FlutterProject project, String expectedTarget) { +String? validateSnapshotDependency(FlutterProject project, String expectedTarget) { final File snapshotBlob = File( path.join(project.rootPath, 'build', 'app', 'intermediates', 'flutter', 'debug', 'flutter_build.d')); diff --git a/dev/devicelab/lib/framework/browser.dart b/dev/devicelab/lib/framework/browser.dart index 9d2f544bec..c9b786db40 100644 --- a/dev/devicelab/lib/framework/browser.dart +++ b/dev/devicelab/lib/framework/browser.dart @@ -2,15 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:convert' show json, utf8, LineSplitter, JsonEncoder; import 'dart:io' as io; import 'dart:math' as math; import 'package:flutter_devicelab/common.dart'; -import 'package:meta/meta.dart'; import 'package:path/path.dart' as path; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; @@ -32,10 +29,10 @@ class ChromeOptions { }); /// If not null passed as `--user-data-dir`. - final String userDataDirectory; + final String? userDataDirectory; /// If not null launches a Chrome tab at this URL. - final String url; + final String? url; /// The width of the Chrome window. /// @@ -49,14 +46,14 @@ class ChromeOptions { /// Launches code in "headless" mode, which allows running Chrome in /// environments without a display, such as LUCI and Cirrus. - final bool headless; + final bool? headless; /// The port Chrome will use for its debugging protocol. /// /// If null, Chrome is launched without debugging. When running in headless /// mode without a debug port, Chrome quits immediately. For most tests it is /// typical to set [headless] to true and set a non-null debug port. - final int debugPort; + final int? debugPort; } /// A function called when the Chrome process encounters an error. @@ -79,7 +76,7 @@ class Chrome { /// The [onError] callback is called with an error message when the Chrome /// process encounters an error. In particular, [onError] is called when the /// Chrome process exits prematurely, i.e. before [stop] is called. - static Future launch(ChromeOptions options, { String workingDirectory, @required ChromeErrorCallback onError }) async { + static Future launch(ChromeOptions options, { String? workingDirectory, required ChromeErrorCallback onError }) async { if (!io.Platform.isWindows) { final io.ProcessResult versionResult = io.Process.runSync(_findSystemChromeExecutable(), const ['--version']); print('Launching ${versionResult.stdout}'); @@ -92,10 +89,10 @@ class Chrome { if (options.userDataDirectory != null) '--user-data-dir=${options.userDataDirectory}', if (options.url != null) - options.url, + options.url!, if (io.Platform.environment['CHROME_NO_SANDBOX'] == 'true') '--no-sandbox', - if (options.headless) + if (options.headless == true) '--headless', if (withDebugging) '--remote-debugging-port=${options.debugPort}', @@ -116,9 +113,9 @@ class Chrome { workingDirectory: workingDirectory, ); - WipConnection debugConnection; + WipConnection? debugConnection; if (withDebugging) { - debugConnection = await _connectToChromeDebugPort(chromeProcess, options.debugPort); + debugConnection = await _connectToChromeDebugPort(chromeProcess, options.debugPort!); } return Chrome._(chromeProcess, onError, debugConnection); @@ -126,12 +123,12 @@ class Chrome { final io.Process _chromeProcess; final ChromeErrorCallback _onError; - final WipConnection _debugConnection; + final WipConnection? _debugConnection; bool _isStopped = false; - Completer _tracingCompleter; - StreamSubscription _tracingSubscription; - List> _tracingData; + Completer ?_tracingCompleter; + StreamSubscription? _tracingSubscription; + List>? _tracingData; /// Starts recording a performance trace. /// @@ -151,24 +148,24 @@ class Chrome { // Subscribe to tracing events prior to calling "Tracing.start". Otherwise, // we'll miss tracing data. - _tracingSubscription = _debugConnection.onNotification.listen((WipEvent event) { + _tracingSubscription = _debugConnection?.onNotification.listen((WipEvent event) { // We receive data as a sequence of "Tracing.dataCollected" followed by // "Tracing.tracingComplete" at the end. Until "Tracing.tracingComplete" // is received, the data may be incomplete. if (event.method == 'Tracing.tracingComplete') { - _tracingCompleter.complete(); - _tracingSubscription.cancel(); + _tracingCompleter!.complete(); + _tracingSubscription!.cancel(); _tracingSubscription = null; } else if (event.method == 'Tracing.dataCollected') { - final dynamic value = event.params['value']; + final dynamic value = event.params?['value']; if (value is! List) { throw FormatException('"Tracing.dataCollected" returned malformed data. ' 'Expected a List but got: ${value.runtimeType}'); } - _tracingData.addAll((event.params['value'] as List).cast>()); + _tracingData?.addAll((event.params?['value'] as List).cast>()); } }); - await _debugConnection.sendCommand('Tracing.start', { + await _debugConnection?.sendCommand('Tracing.start', { // The choice of categories is as follows: // // blink: @@ -190,22 +187,23 @@ class Chrome { /// Stops a performance tracing session started by [beginRecordingPerformance]. /// /// Returns all the collected tracing data unfiltered. - Future>> endRecordingPerformance() async { - await _debugConnection.sendCommand('Tracing.end'); - await _tracingCompleter.future; - final List> data = _tracingData; + Future>?> endRecordingPerformance() async { + await _debugConnection!.sendCommand('Tracing.end'); + await _tracingCompleter!.future; + final List>? data = _tracingData; _tracingCompleter = null; _tracingData = null; return data; } Future reloadPage({bool ignoreCache = false}) async { - await _debugConnection.page.reload(ignoreCache: ignoreCache); + await _debugConnection?.page.reload(ignoreCache: ignoreCache); } /// Stops the Chrome process. void stop() { _isStopped = true; + _tracingSubscription?.cancel(); _chromeProcess.kill(); } } @@ -214,7 +212,7 @@ String _findSystemChromeExecutable() { // On some environments, such as the Dart HHH tester, Chrome resides in a // non-standard location and is provided via the following environment // variable. - final String envExecutable = io.Platform.environment['CHROME_EXECUTABLE']; + final String? envExecutable = io.Platform.environment['CHROME_EXECUTABLE']; if (envExecutable != null) { return envExecutable; } @@ -232,15 +230,12 @@ String _findSystemChromeExecutable() { return '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'; } else if (io.Platform.isWindows) { const String kWindowsExecutable = r'Google\Chrome\Application\chrome.exe'; - final List kWindowsPrefixes = [ + final List kWindowsPrefixes = [ io.Platform.environment['LOCALAPPDATA'], io.Platform.environment['PROGRAMFILES'], io.Platform.environment['PROGRAMFILES(X86)'], - ]; + ].whereType().toList(); final String windowsPrefix = kWindowsPrefixes.firstWhere((String prefix) { - if (prefix == null) { - return false; - } final String expectedPath = path.join(prefix, kWindowsExecutable); return io.File(expectedPath).existsSync(); }, orElse: () => '.'); @@ -269,7 +264,7 @@ Future _getRemoteDebuggerUrl(Uri base) async { final io.HttpClient client = io.HttpClient(); final io.HttpClientRequest request = await client.getUrl(base.resolve('/json/list')); final io.HttpClientResponse response = await request.close(); - final List jsonObject = await json.fuse(utf8).decoder.bind(response).single as List; + final List? jsonObject = await json.fuse(utf8).decoder.bind(response).single as List?; if (jsonObject == null || jsonObject.isEmpty) { return base; } @@ -279,17 +274,17 @@ Future _getRemoteDebuggerUrl(Uri base) async { /// Summarizes a Blink trace down to a few interesting values. class BlinkTraceSummary { BlinkTraceSummary._({ - @required this.averageBeginFrameTime, - @required this.averageUpdateLifecyclePhasesTime, + required this.averageBeginFrameTime, + required this.averageUpdateLifecyclePhasesTime, }) : averageTotalUIFrameTime = averageBeginFrameTime + averageUpdateLifecyclePhasesTime; - static BlinkTraceSummary fromJson(List> traceJson) { + static BlinkTraceSummary? fromJson(List> traceJson) { try { // Convert raw JSON data to BlinkTraceEvent objects sorted by timestamp. List events = traceJson .map(BlinkTraceEvent.fromJson) .toList() - ..sort((BlinkTraceEvent a, BlinkTraceEvent b) => a.ts - b.ts); + ..sort((BlinkTraceEvent a, BlinkTraceEvent b) => a.ts! - b.ts!); Exception noMeasuredFramesFound() => Exception( 'No measured frames found in benchmark tracing data. This likely ' @@ -316,7 +311,7 @@ class BlinkTraceSummary { return null; } - final int tabPid = firstMeasuredFrameEvent.pid; + final int tabPid = firstMeasuredFrameEvent.pid!; // Filter out data from unrelated processes events = events.where((BlinkTraceEvent element) => element.pid == tabPid).toList(); @@ -352,8 +347,8 @@ class BlinkTraceSummary { // Compute averages and summarize. return BlinkTraceSummary._( - averageBeginFrameTime: _computeAverageDuration(frames.map((BlinkFrame frame) => frame.beginFrame).toList()), - averageUpdateLifecyclePhasesTime: _computeAverageDuration(frames.map((BlinkFrame frame) => frame.updateAllLifecyclePhases).toList()), + averageBeginFrameTime: _computeAverageDuration(frames.map((BlinkFrame frame) => frame.beginFrame).whereType().toList()), + averageUpdateLifecyclePhasesTime: _computeAverageDuration(frames.map((BlinkFrame frame) => frame.updateAllLifecyclePhases).whereType().toList()), ); } catch (_, __) { final io.File traceFile = io.File('./chrome-trace.json'); @@ -392,16 +387,16 @@ class BlinkTraceSummary { /// Contains events pertaining to a single frame in the Blink trace data. class BlinkFrame { /// Corresponds to 'WebViewImpl::beginFrame' event. - BlinkTraceEvent beginFrame; + BlinkTraceEvent? beginFrame; /// Corresponds to 'WebViewImpl::updateAllLifecyclePhases' event. - BlinkTraceEvent updateAllLifecyclePhases; + BlinkTraceEvent? updateAllLifecyclePhases; /// Corresponds to 'measured_frame' begin event. - BlinkTraceEvent beginMeasuredFrame; + BlinkTraceEvent? beginMeasuredFrame; /// Corresponds to 'measured_frame' end event. - BlinkTraceEvent endMeasuredFrame; + BlinkTraceEvent? endMeasuredFrame; } /// Takes a list of events that have non-null [BlinkTraceEvent.tdur] computes @@ -414,7 +409,7 @@ Duration _computeAverageDuration(List events) { if (event.tdur == null) { throw FormatException('Trace event lacks "tdur" field: $event'); } - return previousValue + event.tdur; + return previousValue + event.tdur!; }); final int sampleCount = math.min(events.length, _kMeasuredSampleCount); return Duration(microseconds: sum ~/ sampleCount); @@ -426,15 +421,15 @@ Duration _computeAverageDuration(List events) { /// * https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview class BlinkTraceEvent { BlinkTraceEvent._({ - @required this.args, - @required this.cat, - @required this.name, - @required this.ph, - @required this.pid, - @required this.tid, - @required this.ts, - @required this.tts, - @required this.tdur, + required this.args, + required this.cat, + required this.name, + required this.ph, + this.pid, + this.tid, + this.ts, + this.tts, + this.tdur, }); /// Parses an event from its JSON representation. @@ -488,19 +483,19 @@ class BlinkTraceEvent { final String ph; /// Process ID of the process that emitted the event. - final int pid; + final int? pid; /// Thread ID of the thread that emitted the event. - final int tid; + final int? tid; /// Timestamp in microseconds using tracer clock. - final int ts; + final int? ts; /// Timestamp in microseconds using thread clock. - final int tts; + final int? tts; /// Event duration in microseconds. - final int tdur; + final int? tdur; /// A "begin frame" event contains all of the scripting time of an animation /// frame (JavaScript, WebAssembly), plus a negligible amount of internal @@ -556,8 +551,8 @@ class BlinkTraceEvent { /// validation and conversion is needed. /// /// Returns null if the value is null. -int _readInt(Map json, String key) { - final num jsonValue = json[key] as num; +int? _readInt(Map json, String key) { + final num? jsonValue = json[key] as num?; if (jsonValue == null) { return null; @@ -578,10 +573,10 @@ int _readInt(Map json, String key) { /// Inconsistency detected by ld.so: ../elf/dl-tls.c: 493: _dl_allocate_tls_init: Assertion `listp->slotinfo[cnt].gen <= GL(dl_tls_generation)' failed! const String _kGlibcError = 'Inconsistency detected by ld.so'; -Future _spawnChromiumProcess(String executable, List args, { String workingDirectory }) async { +Future _spawnChromiumProcess(String executable, List args, { String? workingDirectory }) async { // Keep attempting to launch the browser until one of: // - Chrome launched successfully, in which case we just return from the loop. - // - The tool detected an unretriable Chrome error, in which case we throw ToolExit. + // - The tool detected an unretryable Chrome error, in which case we throw ToolExit. while (true) { final io.Process process = await io.Process.start(executable, args, workingDirectory: workingDirectory); @@ -611,7 +606,7 @@ Future _spawnChromiumProcess(String executable, List args, { 'Encountered glibc bug https://sourceware.org/bugzilla/show_bug.cgi?id=19329. ' 'Will try launching browser again.', ); - return null; + return ''; } print('Failed to launch browser. Command used to launch it: ${args.join(' ')}'); throw Exception( @@ -630,7 +625,7 @@ Future _spawnChromiumProcess(String executable, List args, { // launching more processes. unawaited(process.exitCode.timeout(const Duration(seconds: 1), onTimeout: () { process.kill(); - return null; + return 0; })); } } diff --git a/dev/devicelab/lib/framework/cocoon.dart b/dev/devicelab/lib/framework/cocoon.dart index 1f09875a9f..6805590f9a 100644 --- a/dev/devicelab/lib/framework/cocoon.dart +++ b/dev/devicelab/lib/framework/cocoon.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:convert' show Encoding, json; import 'dart:io'; @@ -20,12 +18,12 @@ import 'utils.dart'; typedef ProcessRunSync = ProcessResult Function( String, List, { - Map environment, + Map? environment, bool includeParentEnvironment, bool runInShell, - Encoding stderrEncoding, - Encoding stdoutEncoding, - String workingDirectory, + Encoding? stderrEncoding, + Encoding? stdoutEncoding, + String? workingDirectory, }); /// Class for test runner to interact with Flutter's infrastructure service, Cocoon. @@ -34,8 +32,8 @@ typedef ProcessRunSync = ProcessResult Function( /// To retrieve these results, the test runner needs to send results back so the database can be updated. class Cocoon { Cocoon({ - String serviceAccountTokenPath, - @visibleForTesting Client httpClient, + String? serviceAccountTokenPath, + @visibleForTesting Client? httpClient, @visibleForTesting this.fs = const LocalFileSystem(), @visibleForTesting this.processRunSync = Process.runSync, @visibleForTesting this.requestRetryLimit = 5, @@ -58,7 +56,7 @@ class Cocoon { final int requestRetryLimit; String get commitSha => _commitSha ?? _readCommitSha(); - String _commitSha; + String? _commitSha; /// Parse the local repo for the current running commit. String _readCommitSha() { @@ -85,9 +83,9 @@ class Cocoon { /// Send [TaskResult] to Cocoon. // TODO(chillers): Remove when sendResultsPath is used in prod. https://github.com/flutter/flutter/issues/72457 Future sendTaskResult({ - @required String builderName, - @required TaskResult result, - @required String gitBranch, + required String builderName, + required TaskResult result, + required String gitBranch, }) async { assert(builderName != null); assert(gitBranch != null); @@ -109,16 +107,11 @@ class Cocoon { /// Write the given parameters into an update task request and store the JSON in [resultsPath]. Future writeTaskResultToFile({ - @required String builderName, - @required String gitBranch, - @required TaskResult result, - @required String resultsPath, + String? builderName, + String? gitBranch, + required TaskResult result, + required String resultsPath, }) async { - assert(builderName != null); - assert(gitBranch != null); - assert(result != null); - assert(resultsPath != null); - final Map updateRequest = _constructUpdateRequest( gitBranch: gitBranch, builderName: builderName, @@ -134,9 +127,9 @@ class Cocoon { } Map _constructUpdateRequest({ - @required String builderName, - @required TaskResult result, - @required String gitBranch, + String? builderName, + required TaskResult result, + String? gitBranch, }) { final Map updateRequest = { 'CommitBranch': gitBranch, @@ -151,12 +144,12 @@ class Cocoon { final List validScoreKeys = []; if (result.benchmarkScoreKeys != null) { - for (final String scoreKey in result.benchmarkScoreKeys) { - final Object score = result.data[scoreKey]; + for (final String scoreKey in result.benchmarkScoreKeys!) { + final Object score = result.data![scoreKey] as Object; if (score is num) { // Convert all metrics to double, which provide plenty of precision // without having to add support for multiple numeric types in Cocoon. - result.data[scoreKey] = score.toDouble(); + result.data![scoreKey] = score.toDouble(); validScoreKeys.add(scoreKey); } } @@ -195,15 +188,15 @@ class Cocoon { class AuthenticatedCocoonClient extends BaseClient { AuthenticatedCocoonClient( this._serviceAccountTokenPath, { - @visibleForTesting Client httpClient, - @visibleForTesting FileSystem filesystem, + @visibleForTesting Client? httpClient, + @visibleForTesting FileSystem? filesystem, }) : _delegate = httpClient ?? Client(), _fs = filesystem ?? const LocalFileSystem(); /// Authentication token to have the ability to upload and record test results. /// /// This is intended to only be passed on automated runs on LUCI post-submit. - final String _serviceAccountTokenPath; + final String? _serviceAccountTokenPath; /// Underlying [HttpClient] to send requests to. final Client _delegate; @@ -213,7 +206,7 @@ class AuthenticatedCocoonClient extends BaseClient { /// Value contained in the service account token file that can be used in http requests. String get serviceAccountToken => _serviceAccountToken ?? _readServiceAccountTokenFile(); - String _serviceAccountToken; + String? _serviceAccountToken; /// Get [serviceAccountToken] from the given service account file. String _readServiceAccountTokenFile() { diff --git a/dev/devicelab/lib/framework/devices.dart b/dev/devicelab/lib/framework/devices.dart index 4800311014..071bdcf65c 100644 --- a/dev/devicelab/lib/framework/devices.dart +++ b/dev/devicelab/lib/framework/devices.dart @@ -2,15 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:math' as math; import 'package:flutter_devicelab/common.dart'; -import 'package:meta/meta.dart'; import 'package:path/path.dart' as path; import 'utils.dart'; @@ -37,8 +34,8 @@ String getArtifactPath() { } /// Return the item is in idList if find a match, otherwise return null -String _findMatchId(List idList, String idPattern) { - String candidate; +String? _findMatchId(List idList, String idPattern) { + String? candidate; idPattern = idPattern.toLowerCase(); for(final String id in idList) { if (id.toLowerCase() == idPattern) { @@ -184,47 +181,46 @@ enum AndroidCPU { } class AndroidDeviceDiscovery implements DeviceDiscovery { - factory AndroidDeviceDiscovery({AndroidCPU cpu}) { + factory AndroidDeviceDiscovery({AndroidCPU? cpu}) { return _instance ??= AndroidDeviceDiscovery._(cpu); } AndroidDeviceDiscovery._(this.cpu); - final AndroidCPU cpu; + final AndroidCPU? cpu; // Parses information about a device. Example: // // 015d172c98400a03 device usb:340787200X product:nakasi model:Nexus_7 device:grouper static final RegExp _kDeviceRegex = RegExp(r'^(\S+)\s+(\S+)(.*)'); - static AndroidDeviceDiscovery _instance; + static AndroidDeviceDiscovery? _instance; - AndroidDevice _workingDevice; + AndroidDevice? _workingDevice; @override Future get workingDevice async { if (_workingDevice == null) { if (Platform.environment.containsKey(DeviceIdEnvName)) { - final String deviceId = Platform.environment[DeviceIdEnvName]; + final String deviceId = Platform.environment[DeviceIdEnvName]!; await chooseWorkingDeviceById(deviceId); - return _workingDevice; + return _workingDevice!; } await chooseWorkingDevice(); } - return _workingDevice; + return _workingDevice!; } Future _matchesCPURequirement(AndroidDevice device) async { - if (cpu == null) - return true; switch (cpu) { + case null: + return true; case AndroidCPU.arm64: return device.isArm64(); case AndroidCPU.arm: return device.isArm(); } - return true; } /// Picks a random Android device out of connected devices and sets it as @@ -259,11 +255,11 @@ class AndroidDeviceDiscovery implements DeviceDiscovery { @override Future chooseWorkingDeviceById(String deviceId) async { - final String matchedId = _findMatchId(await discoverDevices(), deviceId); + final String? matchedId = _findMatchId(await discoverDevices(), deviceId); if (matchedId != null) { _workingDevice = AndroidDevice(deviceId: matchedId); if (cpu != null) { - if (!await _matchesCPURequirement(_workingDevice)) { + if (!await _matchesCPURequirement(_workingDevice!)) { throw DeviceException('The selected device $matchedId does not match the cpu requirement'); } } @@ -290,10 +286,10 @@ class AndroidDeviceDiscovery implements DeviceDiscovery { continue; if (_kDeviceRegex.hasMatch(line)) { - final Match match = _kDeviceRegex.firstMatch(line); + final Match match = _kDeviceRegex.firstMatch(line)!; - final String deviceID = match[1]; - final String deviceState = match[2]; + final String deviceID = match[1]!; + final String deviceState = match[2]!; if (!const ['unauthorized', 'offline'].contains(deviceState)) { results.add(deviceID); @@ -342,9 +338,9 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery { FuchsiaDeviceDiscovery._(); - static FuchsiaDeviceDiscovery _instance; + static FuchsiaDeviceDiscovery? _instance; - FuchsiaDevice _workingDevice; + FuchsiaDevice? _workingDevice; String get _ffx { final String ffx = path.join(getArtifactPath(), 'fuchsia', 'tools','x64', 'ffx'); @@ -358,13 +354,13 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery { Future get workingDevice async { if (_workingDevice == null) { if (Platform.environment.containsKey(DeviceIdEnvName)) { - final String deviceId = Platform.environment[DeviceIdEnvName]; + final String deviceId = Platform.environment[DeviceIdEnvName]!; await chooseWorkingDeviceById(deviceId); - return _workingDevice; + return _workingDevice!; } await chooseWorkingDevice(); } - return _workingDevice; + return _workingDevice!; } /// Picks the first connected Fuchsia device. @@ -383,8 +379,8 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery { @override Future chooseWorkingDeviceById(String deviceId) async { - final String matchedId = _findMatchId(await discoverDevices(), deviceId); - if (deviceId != null) { + final String? matchedId = _findMatchId(await discoverDevices(), deviceId); + if (matchedId != null) { _workingDevice = FuchsiaDevice(deviceId: matchedId); print('Choose device by ID: $matchedId'); return; @@ -442,7 +438,7 @@ class FuchsiaDeviceDiscovery implements DeviceDiscovery { } class AndroidDevice extends Device { - AndroidDevice({@required this.deviceId}) { + AndroidDevice({required this.deviceId}) { _updateDeviceInfo(); } @@ -540,19 +536,19 @@ class AndroidDevice extends Device { } /// Executes [command] on `adb shell` and returns its exit code. - Future shellExec(String command, List arguments, { Map environment, bool silent = false }) async { + Future shellExec(String command, List arguments, { Map? environment, bool silent = false }) async { await adb(['shell', command, ...arguments], environment: environment, silent: silent); } /// Executes [command] on `adb shell` and returns its standard output as a [String]. - Future shellEval(String command, List arguments, { Map environment, bool silent = false }) { + Future shellEval(String command, List arguments, { Map? environment, bool silent = false }) { return adb(['shell', command, ...arguments], environment: environment, silent: silent); } /// Runs `adb` with the given [arguments], selecting this device. Future adb( List arguments, { - Map environment, + Map? environment, bool silent = false, }) { return eval( @@ -568,18 +564,18 @@ class AndroidDevice extends Device { @override Future> getMemoryStats(String packageName) async { final String meminfo = await shellEval('dumpsys', ['meminfo', packageName]); - final Match match = RegExp(r'TOTAL\s+(\d+)').firstMatch(meminfo); + final Match? match = RegExp(r'TOTAL\s+(\d+)').firstMatch(meminfo); assert(match != null, 'could not parse dumpsys meminfo output'); return { - 'total_kb': int.parse(match.group(1)), + 'total_kb': int.parse(match!.group(1)!), }; } @override bool get canStreamLogs => true; - bool _abortedLogging/*!*/ = false; - Process/*?*/ _loggingProcess; + bool _abortedLogging = false; + Process? _loggingProcess; @override Future startLoggingToSink(IOSink sink, {bool clear = true}) async { @@ -596,17 +592,17 @@ class AndroidDevice extends Device { // to view the whole log, or just run logcat alongside this. ['-s', deviceId, 'logcat', 'ActivityManager:I', 'flutter:V', '*:F'], ); - _loggingProcess.stdout + _loggingProcess!.stdout .transform(const Utf8Decoder(allowMalformed: true)) .listen((String line) { sink.write(line); }); - _loggingProcess.stderr + _loggingProcess!.stderr .transform(const Utf8Decoder(allowMalformed: true)) .listen((String line) { sink.write(line); }); - unawaited(_loggingProcess.exitCode.then((int exitCode) { + unawaited(_loggingProcess!.exitCode.then((int exitCode) { if (!_abortedLogging) { sink.writeln('adb logcat failed with exit code $exitCode.\n'); } @@ -617,8 +613,8 @@ class AndroidDevice extends Device { Future stopLoggingToSink() async { if (_loggingProcess != null) { _abortedLogging = true; - _loggingProcess.kill(); - await _loggingProcess.exitCode; + _loggingProcess!.kill(); + await _loggingProcess!.exitCode; } } @@ -629,7 +625,7 @@ class AndroidDevice extends Device { final Completer processDone = Completer(); final Completer abort = Completer(); bool aborted = false; - StreamController stream; + late final StreamController stream; stream = StreamController( onListen: () async { await adb(['logcat', '--clear']); @@ -713,22 +709,22 @@ class IosDeviceDiscovery implements DeviceDiscovery { IosDeviceDiscovery._(); - static IosDeviceDiscovery _instance; + static IosDeviceDiscovery? _instance; - IosDevice _workingDevice; + IosDevice? _workingDevice; @override Future get workingDevice async { if (_workingDevice == null) { if (Platform.environment.containsKey(DeviceIdEnvName)) { - final String deviceId = Platform.environment[DeviceIdEnvName]; + final String deviceId = Platform.environment[DeviceIdEnvName]!; await chooseWorkingDeviceById(deviceId); - return _workingDevice; + return _workingDevice!; } await chooseWorkingDevice(); } - return _workingDevice; + return _workingDevice!; } /// Picks a random iOS device out of connected devices and sets it as @@ -749,7 +745,7 @@ class IosDeviceDiscovery implements DeviceDiscovery { @override Future chooseWorkingDeviceById(String deviceId) async { - final String matchedId = _findMatchId(await discoverDevices(), deviceId); + final String? matchedId = _findMatchId(await discoverDevices(), deviceId); if (matchedId != null) { _workingDevice = IosDevice(deviceId: matchedId); print('Choose device by ID: $matchedId'); @@ -824,7 +820,7 @@ class IosDeviceDiscovery implements DeviceDiscovery { /// iOS device. class IosDevice extends Device { - IosDevice({ @required this.deviceId }); + IosDevice({ required this.deviceId }); @override final String deviceId; @@ -846,8 +842,8 @@ class IosDevice extends Device { @override bool get canStreamLogs => true; - bool _abortedLogging/*!*/ = false; - Process/*?*/ _loggingProcess; + bool _abortedLogging = false; + Process? _loggingProcess; @override Future startLoggingToSink(IOSink sink, {bool clear = true}) async { @@ -859,17 +855,17 @@ class IosDevice extends Device { 'DYLD_LIBRARY_PATH': dyldLibraryPath, }, ); - _loggingProcess.stdout + _loggingProcess!.stdout .transform(const Utf8Decoder(allowMalformed: true)) .listen((String line) { sink.write(line); }); - _loggingProcess.stderr + _loggingProcess!.stderr .transform(const Utf8Decoder(allowMalformed: true)) .listen((String line) { sink.write(line); }); - unawaited(_loggingProcess.exitCode.then((int exitCode) { + unawaited(_loggingProcess!.exitCode.then((int exitCode) { if (!_abortedLogging) { sink.writeln('idevicesyslog failed with exit code $exitCode.\n'); } @@ -880,8 +876,8 @@ class IosDevice extends Device { Future stopLoggingToSink() async { if (_loggingProcess != null) { _abortedLogging = true; - _loggingProcess.kill(); - await _loggingProcess.exitCode; + _loggingProcess!.kill(); + await _loggingProcess!.exitCode; } } @@ -934,7 +930,7 @@ class IosDevice extends Device { /// Fuchsia device. class FuchsiaDevice extends Device { - const FuchsiaDevice({ @required this.deviceId }); + const FuchsiaDevice({ required this.deviceId }); @override final String deviceId; @@ -982,7 +978,7 @@ class FuchsiaDevice extends Device { /// Path to the `adb` executable. String get adbPath { - final String androidHome = Platform.environment['ANDROID_HOME'] ?? Platform.environment['ANDROID_SDK_ROOT']; + final String? androidHome = Platform.environment['ANDROID_HOME'] ?? Platform.environment['ANDROID_SDK_ROOT']; if (androidHome == null) { throw const DeviceException( @@ -1001,7 +997,7 @@ String get adbPath { } class FakeDevice extends Device { - const FakeDevice({ @required this.deviceId }); + const FakeDevice({ required this.deviceId }); @override final String deviceId; @@ -1055,22 +1051,22 @@ class FakeDeviceDiscovery implements DeviceDiscovery { FakeDeviceDiscovery._(); - static FakeDeviceDiscovery _instance; + static FakeDeviceDiscovery? _instance; - FakeDevice _workingDevice; + FakeDevice? _workingDevice; @override Future get workingDevice async { if (_workingDevice == null) { if (Platform.environment.containsKey(DeviceIdEnvName)) { - final String deviceId = Platform.environment[DeviceIdEnvName]; + final String deviceId = Platform.environment[DeviceIdEnvName]!; await chooseWorkingDeviceById(deviceId); - return _workingDevice; + return _workingDevice!; } await chooseWorkingDevice(); } - return _workingDevice; + return _workingDevice!; } /// The Fake is only available for by ID device discovery. @@ -1081,7 +1077,7 @@ class FakeDeviceDiscovery implements DeviceDiscovery { @override Future chooseWorkingDeviceById(String deviceId) async { - final String matchedId = _findMatchId(await discoverDevices(), deviceId); + final String? matchedId = _findMatchId(await discoverDevices(), deviceId); if (matchedId != null) { _workingDevice = FakeDevice(deviceId: matchedId); print('Choose device by ID: $matchedId'); diff --git a/dev/devicelab/lib/framework/framework.dart b/dev/devicelab/lib/framework/framework.dart index e73e373a5b..a304102b7a 100644 --- a/dev/devicelab/lib/framework/framework.dart +++ b/dev/devicelab/lib/framework/framework.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:convert'; import 'dart:developer'; @@ -64,8 +62,8 @@ class _TaskRunner { _TaskRunner(this.task) { registerExtension('ext.cocoonRunTask', (String method, Map parameters) async { - final Duration taskTimeout = parameters.containsKey('timeoutInMinutes') - ? Duration(minutes: int.parse(parameters['timeoutInMinutes'])) + final Duration? taskTimeout = parameters.containsKey('timeoutInMinutes') + ? Duration(minutes: int.parse(parameters['timeoutInMinutes']!)) : null; // This is only expected to be passed in unit test runs so they do not // kill the Dart process that is running them and waste time running config. @@ -82,7 +80,7 @@ class _TaskRunner { final TaskFunction task; - Future _getWorkingDeviceIfAvailable() async { + Future _getWorkingDeviceIfAvailable() async { try { return await devices.workingDevice; } on DeviceException { @@ -91,8 +89,8 @@ class _TaskRunner { } // TODO(ianh): workaround for https://github.com/dart-lang/sdk/issues/23797 - RawReceivePort _keepAlivePort; - Timer _startTaskTimeout; + RawReceivePort? _keepAlivePort; + Timer? _startTaskTimeout; bool _taskStarted = false; final Completer _completer = Completer(); @@ -102,7 +100,7 @@ class _TaskRunner { /// Signals that this task runner finished running the task. Future get whenDone => _completer.future; - Future run(Duration taskTimeout, { + Future run(Duration? taskTimeout, { bool runFlutterConfig = true, bool runProcessCleanup = true, }) async { @@ -110,7 +108,7 @@ class _TaskRunner { _taskStarted = true; print('Running task with a timeout of $taskTimeout.'); final String exe = Platform.isWindows ? '.exe' : ''; - Set beforeRunningDartInstances; + late Set beforeRunningDartInstances; if (runProcessCleanup) { section('Checking running Dart$exe processes'); beforeRunningDartInstances = await getRunningProcesses( @@ -136,7 +134,7 @@ class _TaskRunner { '--enable-windows-desktop', '--enable-linux-desktop', '--enable-web', - if (localEngine != null) ...['--local-engine', localEngine], + if (localEngine != null) ...['--local-engine', localEngine!], ], canFail: true); if (configResult != 0) { print('Failed to enable configuration, tasks may not run.'); @@ -145,12 +143,12 @@ class _TaskRunner { print('Skipping enabling configs for macOS, Linux, Windows, and Web'); } - final Device/*?*/ device = await _getWorkingDeviceIfAvailable(); - /*late*/ TaskResult result; - IOSink/*?*/ sink; + final Device? device = await _getWorkingDeviceIfAvailable(); + late TaskResult result; + IOSink? sink; try { if (device != null && device.canStreamLogs && hostAgent.dumpDirectory != null) { - sink = File(path.join(hostAgent.dumpDirectory.path, '${device.deviceId}.log')).openWrite(); + sink = File(path.join(hostAgent.dumpDirectory!.path, '${device.deviceId}.log')).openWrite(); await device.startLoggingToSink(sink); } @@ -212,7 +210,7 @@ class _TaskRunner { final File rebootFile = _rebootFile(); int runCount; if (rebootFile.existsSync()) { - runCount = int.tryParse(rebootFile.readAsStringSync().trim()); + runCount = int.tryParse(rebootFile.readAsStringSync().trim()) ?? 0; } else { runCount = 0; } @@ -283,10 +281,10 @@ class _TaskRunner { File _rebootFile() { if (Platform.isLinux || Platform.isMacOS) { - return File(path.join(Platform.environment['HOME'], '.reboot-count')); + return File(path.join(Platform.environment['HOME']!, '.reboot-count')); } if (!Platform.isWindows) { throw StateError('Unexpected platform ${Platform.operatingSystem}'); } - return File(path.join(Platform.environment['USERPROFILE'], '.reboot-count')); + return File(path.join(Platform.environment['USERPROFILE']!, '.reboot-count')); } diff --git a/dev/devicelab/lib/framework/ios.dart b/dev/devicelab/lib/framework/ios.dart index 6598011a72..3e03bd9ba1 100644 --- a/dev/devicelab/lib/framework/ios.dart +++ b/dev/devicelab/lib/framework/ios.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:convert'; import 'utils.dart'; @@ -42,17 +40,10 @@ Future containsBitcode(String pathToBinary) async { final List lines = LineSplitter.split(loadCommands).toList(); lines.asMap().forEach((int index, String line) { if (line.contains('segname __LLVM') && lines.length - index - 1 > 3) { - final String emptyBitcodeMarker = lines + emptyBitcodeMarkerFound |= lines .skip(index - 1) .take(4) - .firstWhere( - (String line) => line.contains(' size 0x0000000000000001'), - orElse: () => null, - ); - if (emptyBitcodeMarker != null) { - emptyBitcodeMarkerFound = true; - return; - } + .any((String line) => line.contains(' size 0x0000000000000001')); } }); return !emptyBitcodeMarkerFound; @@ -79,16 +70,16 @@ Future testWithNewIOSSimulator( workingDirectory: flutterDirectory.path, ); - String iOSSimRuntime; + String? iOSSimRuntime; final RegExp iOSRuntimePattern = RegExp(r'iOS .*\) - (.*)'); for (final String runtime in LineSplitter.split(availableRuntimes)) { // These seem to be in order, so allow matching multiple lines so it grabs // the last (hopefully latest) one. - final RegExpMatch iOSRuntimeMatch = iOSRuntimePattern.firstMatch(runtime); + final RegExpMatch? iOSRuntimeMatch = iOSRuntimePattern.firstMatch(runtime); if (iOSRuntimeMatch != null) { - iOSSimRuntime = iOSRuntimeMatch.group(1).trim(); + iOSSimRuntime = iOSRuntimeMatch.group(1)!.trim(); continue; } } diff --git a/dev/devicelab/lib/framework/manifest.dart b/dev/devicelab/lib/framework/manifest.dart index 836c8ab3b2..a52ab10363 100644 --- a/dev/devicelab/lib/framework/manifest.dart +++ b/dev/devicelab/lib/framework/manifest.dart @@ -2,17 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:io'; -import 'package:meta/meta.dart'; import 'package:yaml/yaml.dart'; import 'utils.dart'; /// Loads manifest data from `manifest.yaml` file or from [yaml], if present. -Manifest loadTaskManifest([ String yaml ]) { +Manifest loadTaskManifest([ String? yaml ]) { final dynamic manifestYaml = yaml == null ? loadYaml(file('manifest.yaml').readAsStringSync()) : loadYamlNode(yaml); @@ -32,13 +29,13 @@ class Manifest { /// A CI task. class ManifestTask { ManifestTask._({ - @required this.name, - @required this.description, - @required this.stage, - @required this.requiredAgentCapabilities, - @required this.isFlaky, - @required this.timeoutInMinutes, - @required this.onLuci, + required this.name, + required this.description, + required this.stage, + required this.requiredAgentCapabilities, + required this.isFlaky, + required this.timeoutInMinutes, + required this.onLuci, }) { final String taskName = 'task "$name"'; _checkIsNotBlank(name, 'Task name', taskName); @@ -148,9 +145,9 @@ ManifestTask _validateAndParseTask(String taskName, dynamic taskYaml) { // ignore: avoid_dynamic_calls stage: taskYaml['stage'] as String, requiredAgentCapabilities: capabilities as List, - isFlaky: isFlaky as bool ?? false, + isFlaky: isFlaky as bool, timeoutInMinutes: timeoutInMinutes as int, - onLuci: onLuci as bool ?? false, + onLuci: onLuci as bool, ); } @@ -161,7 +158,7 @@ List _validateAndParseCapabilities(String taskName, dynamic capabilities final dynamic capability = capabilities[i]; _checkType(capability is String, capability, 'required_agent_capabilities[$i]', 'string'); } - return (capabilitiesYaml as List).cast(); + return capabilitiesYaml.cast(); } void _checkType(bool isValid, dynamic value, String variableName, String typeName) { diff --git a/dev/devicelab/lib/framework/runner.dart b/dev/devicelab/lib/framework/runner.dart index 7a84e9fd92..d56bd00851 100644 --- a/dev/devicelab/lib/framework/runner.dart +++ b/dev/devicelab/lib/framework/runner.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:convert'; import 'dart:io'; @@ -21,13 +19,13 @@ Future runTasks( List taskNames, { bool exitOnFirstTestFailure = false, bool silent = false, - String deviceId, - String gitBranch, - String localEngine, - String localEngineSrcPath, - String luciBuilder, - String resultsPath, - List taskArgs, + String? deviceId, + String? gitBranch, + String? localEngine, + String? localEngineSrcPath, + String? luciBuilder, + String? resultsPath, + List? taskArgs, }) async { for (final String taskName in taskNames) { section('Running task "$taskName"'); @@ -44,7 +42,7 @@ Future runTasks( print(const JsonEncoder.withIndent(' ').convert(result)); section('Finished task "$taskName"'); - if (resultsPath != null) { + if (resultsPath != null && gitBranch != null) { final Cocoon cocoon = Cocoon(); await cocoon.writeTaskResultToFile( builderName: luciBuilder, @@ -76,11 +74,11 @@ Future runTasks( Future runTask( String taskName, { bool silent = false, - String localEngine, - String localEngineSrcPath, - String deviceId, - List taskArgs, - @visibleForTesting Map isolateParams, + String? localEngine, + String? localEngineSrcPath, + String? deviceId, + List ?taskArgs, + @visibleForTesting Map? isolateParams, }) async { final String taskExecutable = 'bin/tasks/$taskName.dart'; @@ -117,7 +115,7 @@ Future runTask( .transform(const LineSplitter()) .listen((String line) { if (!uri.isCompleted) { - final Uri serviceUri = parseServiceUri(line, prefix: 'Observatory listening on '); + final Uri? serviceUri = parseServiceUri(line, prefix: 'Observatory listening on '); if (serviceUri != null) uri.complete(serviceUri); } @@ -139,7 +137,7 @@ Future runTask( 'ext.cocoonRunTask', args: isolateParams, isolateId: result.isolate.id, - )).json; + )).json!; final TaskResult taskResult = TaskResult.fromJson(taskResultJson); await runner.exitCode; return taskResult; @@ -168,13 +166,13 @@ Future _connectToRunnerIsolate(Uri vmServiceUri) async { // Look up the isolate. final VmService client = await vmServiceConnectUri(url); VM vm = await client.getVM(); - while (vm.isolates.isEmpty) { + while (vm.isolates!.isEmpty) { await Future.delayed(const Duration(seconds: 1)); vm = await client.getVM(); } - final IsolateRef isolate = vm.isolates.first; + final IsolateRef isolate = vm.isolates!.first; final Response response = await client.callServiceExtension('ext.cocoonRunnerReady', isolateId: isolate.id); - if (response.json['response'] != 'ready') + if (response.json!['response'] != 'ready') throw 'not ready yet'; return ConnectionResult(client, isolate); } catch (error) { @@ -193,7 +191,7 @@ class ConnectionResult { } /// The cocoon client sends an invalid VM service response, we need to intercept it. -Future vmServiceConnectUri(String wsUri, {Log log}) async { +Future vmServiceConnectUri(String wsUri, {Log? log}) async { final WebSocket socket = await WebSocket.connect(wsUri); final StreamController controller = StreamController(); final Completer streamClosedCompleter = Completer(); @@ -207,7 +205,7 @@ Future vmServiceConnectUri(String wsUri, {Log log}) async { controller.add(data); } }, - onError: (dynamic err, StackTrace stackTrace) => controller.addError(err, stackTrace), + onError: (Object err, StackTrace stackTrace) => controller.addError(err, stackTrace), onDone: () => streamClosedCompleter.complete(), ); diff --git a/dev/devicelab/lib/framework/running_processes.dart b/dev/devicelab/lib/framework/running_processes.dart index b07f1c17dd..07a5e52739 100644 --- a/dev/devicelab/lib/framework/running_processes.dart +++ b/dev/devicelab/lib/framework/running_processes.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:io'; import 'package:meta/meta.dart'; @@ -36,7 +34,7 @@ class RunningProcessInfo { } } -Future killProcess(String pid, {ProcessManager processManager}) async { +Future killProcess(String pid, {ProcessManager? processManager}) async { assert(pid != null, 'Must specify a pid to kill'); processManager ??= const LocalProcessManager(); ProcessResult result; @@ -58,8 +56,8 @@ Future killProcess(String pid, {ProcessManager processManager}) async { } Stream getRunningProcesses({ - String processName, - ProcessManager processManager, + String? processName, + ProcessManager? processManager, }) { processManager ??= const LocalProcessManager(); if (Platform.isWindows) { @@ -69,7 +67,7 @@ Stream getRunningProcesses({ } @visibleForTesting -Stream windowsRunningProcesses(String processName) async* { +Stream windowsRunningProcesses(String? processName) async* { // PowerShell script to get the command line arguments and create time of // a process. // See: https://docs.microsoft.com/en-us/windows/desktop/cimwin32prov/win32-process @@ -107,8 +105,8 @@ Iterable processPowershellOutput(String output) sync* { const int processIdHeaderSize = 'ProcessId'.length; const int creationDateHeaderStart = processIdHeaderSize + 1; - int creationDateHeaderEnd; - int commandLineHeaderStart; + late int creationDateHeaderEnd; + late int commandLineHeaderStart; bool inTableBody = false; for (final String line in output.split('\n')) { if (line.startsWith('ProcessId')) { @@ -160,7 +158,7 @@ Iterable processPowershellOutput(String output) sync* { @visibleForTesting Stream posixRunningProcesses( - String processName, + String? processName, ProcessManager processManager, ) async* { // Cirrus is missing this in Linux for some reason. @@ -194,7 +192,7 @@ Stream posixRunningProcesses( @visibleForTesting Iterable processPsOutput( String output, - String processName, + String? processName, ) sync* { if (output == null) { return; @@ -235,7 +233,7 @@ Iterable processPsOutput( final String rawTime = line.substring(0, 24); final String year = rawTime.substring(20, 24); - final String month = months[rawTime.substring(4, 7)]; + final String month = months[rawTime.substring(4, 7)]!; final String day = rawTime.substring(8, 10).replaceFirst(' ', '0'); final String time = rawTime.substring(11, 19); diff --git a/dev/devicelab/lib/framework/task_result.dart b/dev/devicelab/lib/framework/task_result.dart index be6e4e433d..3fa821d0c3 100644 --- a/dev/devicelab/lib/framework/task_result.dart +++ b/dev/devicelab/lib/framework/task_result.dart @@ -41,7 +41,7 @@ class TaskResult { List detailFiles = const [], }) { return TaskResult.success( - json.decode(file.readAsStringSync()) as Map, + json.decode(file.readAsStringSync()) as Map?, benchmarkScoreKeys: benchmarkScoreKeys, detailFiles: detailFiles, ); @@ -53,14 +53,14 @@ class TaskResult { if (success) { final List benchmarkScoreKeys = (json['benchmarkScoreKeys'] as List? ?? []).cast(); final List detailFiles = (json['detailFiles'] as List? ?? []).cast(); - return TaskResult.success(json['data'] as Map, + return TaskResult.success(json['data'] as Map?, benchmarkScoreKeys: benchmarkScoreKeys, detailFiles: detailFiles, - message: json['reason'] as String, + message: json['reason'] as String?, ); } - return TaskResult.failure(json['reason'] as String); + return TaskResult.failure(json['reason'] as String?); } /// Constructs an unsuccessful result. @@ -88,7 +88,7 @@ class TaskResult { bool get failed => !succeeded; /// Explains the result in a human-readable format. - final String message; + final String? message; /// Serializes this task result to JSON format. /// @@ -124,7 +124,7 @@ class TaskResult { } @override - String toString() => message; + String toString() => message ?? ''; } class TaskResultCheckProcesses extends TaskResult { diff --git a/dev/devicelab/lib/framework/utils.dart b/dev/devicelab/lib/framework/utils.dart index aeb501a69d..7983e27bc0 100644 --- a/dev/devicelab/lib/framework/utils.dart +++ b/dev/devicelab/lib/framework/utils.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:convert'; import 'dart:io'; @@ -11,7 +9,6 @@ import 'dart:math' as math; import 'package:flutter_devicelab/common.dart'; import 'package:flutter_devicelab/framework/devices.dart'; -import 'package:meta/meta.dart'; import 'package:path/path.dart' as path; import 'package:process/process.dart'; import 'package:stack_trace/stack_trace.dart'; @@ -23,7 +20,7 @@ import 'task_result.dart'; String cwd = Directory.current.path; /// The local engine to use for [flutter] and [evalFlutter], if any. -String get localEngine { +String? get localEngine { // Use two distinct `defaultValue`s to determine whether a 'localEngine' // declaration exists in the environment. const bool isDefined = @@ -34,7 +31,7 @@ String get localEngine { /// The local engine source path to use if a local engine is used for [flutter] /// and [evalFlutter]. -String get localEngineSrcPath { +String? get localEngineSrcPath { // Use two distinct `defaultValue`s to determine whether a // 'localEngineSrcPath' declaration exists in the environment. const bool isDefined = @@ -70,18 +67,18 @@ class HealthCheckResult { HealthCheckResult.failure(this.details) : succeeded = false; HealthCheckResult.error(dynamic error, dynamic stackTrace) : succeeded = false, - details = 'ERROR: $error${'\n$stackTrace' ?? ''}'; + details = 'ERROR: $error${stackTrace != null ? '\n$stackTrace' : ''}'; final bool succeeded; - final String details; + final String? details; @override String toString() { final StringBuffer buf = StringBuffer(succeeded ? 'succeeded' : 'failed'); - if (details != null && details.trim().isNotEmpty) { + if (details != null && details!.trim().isNotEmpty) { buf.writeln(); // Indent details by 4 spaces - for (final String line in details.trim().split('\n')) { + for (final String line in details!.trim().split('\n')) { buf.writeln(' $line'); } } @@ -127,7 +124,7 @@ Directory dir(String path) => Directory(path); File file(String path) => File(path); -void copy(File sourceFile, Directory targetDirectory, {String name}) { +void copy(File sourceFile, Directory targetDirectory, {String? name}) { final File target = file( path.join(targetDirectory.path, name ?? path.basename(sourceFile.path))); target.writeAsBytesSync(sourceFile.readAsBytesSync()); @@ -154,7 +151,7 @@ void recursiveCopy(Directory source, Directory target) { } FileSystemEntity move(FileSystemEntity whatToMove, - {Directory to, String name}) { + {required Directory to, String? name}) { return whatToMove .renameSync(path.join(to.path, name ?? path.basename(whatToMove.path))); } @@ -225,9 +222,9 @@ Future getDartVersion() async { return version.replaceAll('"', "'"); } -Future getCurrentFlutterRepoCommit() { +Future getCurrentFlutterRepoCommit() { if (!dir('${flutterDirectory.path}/.git').existsSync()) { - return Future.value(null); + return Future.value(null); } return inDirectory(flutterDirectory, () { @@ -275,10 +272,10 @@ Future getFlutterRepoCommitTimestamp(String commit) { /// returned in the form of a [Future] that completes to a [Process] object. Future startProcess( String executable, - List arguments, { - Map environment, + List? arguments, { + Map? environment, bool isBot = true, // set to false to pretend not to be on a bot (e.g. to test user-facing outputs) - String workingDirectory, + String? workingDirectory, }) async { assert(isBot != null); final String command = '$executable ${arguments?.join(" ") ?? ""}'; @@ -288,7 +285,7 @@ Future startProcess( newEnvironment['LANG'] = 'en_US.UTF-8'; print('\nExecuting: $command in $finalWorkingDirectory with environment $newEnvironment'); final Process process = await _processManager.start( - [executable, ...arguments], + [executable, ...?arguments], environment: newEnvironment, workingDirectory: finalWorkingDirectory, ); @@ -324,9 +321,9 @@ Future forceQuitRunningProcesses() async { Future exec( String executable, List arguments, { - Map environment, + Map? environment, bool canFail = false, // as in, whether failures are ok. False means that they are fatal. - String workingDirectory, + String? workingDirectory, }) async { return _execute( executable, @@ -340,11 +337,11 @@ Future exec( Future _execute( String executable, List arguments, { - Map environment, + Map? environment, bool canFail = false, // as in, whether failures are ok. False means that they are fatal. - String workingDirectory, - StringBuffer output, // if not null, the stdout will be written here - StringBuffer stderr, // if not null, the stderr will be written here + String? workingDirectory, + StringBuffer? output, // if not null, the stdout will be written here + StringBuffer? stderr, // if not null, the stderr will be written here bool printStdout = true, bool printStderr = true, }) async { @@ -376,8 +373,8 @@ Future _execute( /// Returns a future that completes when both out and error streams a closed. Future forwardStandardStreams( Process process, { - StringBuffer output, - StringBuffer stderr, + StringBuffer? output, + StringBuffer? stderr, bool printStdout = true, bool printStderr = true, }) { @@ -414,10 +411,10 @@ Future forwardStandardStreams( Future eval( String executable, List arguments, { - Map environment, + Map? environment, bool canFail = false, // as in, whether failures are ok. False means that they are fatal. - String workingDirectory, - StringBuffer stderr, // if not null, the stderr will be written here + String? workingDirectory, + StringBuffer? stderr, // if not null, the stderr will be written here bool printStdout = true, bool printStderr = true, }) async { @@ -457,10 +454,10 @@ List flutterCommandArgs(String command, List options) { if (command == 'drive' && hostAgent.dumpDirectory != null) ...[ '--screenshot', - hostAgent.dumpDirectory.path, + hostAgent.dumpDirectory!.path, ], - if (localEngine != null) ...['--local-engine', localEngine], - if (localEngineSrcPath != null) ...['--local-engine-src-path', localEngineSrcPath], + if (localEngine != null) ...['--local-engine', localEngine!], + if (localEngineSrcPath != null) ...['--local-engine-src-path', localEngineSrcPath!], ...options, ]; } @@ -470,7 +467,7 @@ List flutterCommandArgs(String command, List options) { Future flutter(String command, { List options = const [], bool canFail = false, // as in, whether failures are ok. False means that they are fatal. - Map environment = const {}, + Map? environment, }) { final List args = flutterCommandArgs(command, options); return exec(path.join(flutterDirectory.path, 'bin', 'flutter'), args, @@ -493,8 +490,8 @@ Future startFlutter(String command, { Future evalFlutter(String command, { List options = const [], bool canFail = false, // as in, whether failures are ok. False means that they are fatal. - Map environment, - StringBuffer stderr, // if not null, the stderr will be written here. + Map? environment, + StringBuffer? stderr, // if not null, the stderr will be written here. }) { final List args = flutterCommandArgs(command, options); return eval(path.join(flutterDirectory.path, 'bin', 'flutter'), args, @@ -521,7 +518,7 @@ Future dart(List args) => exec(dartBin, ['--disable-dart-de /// Returns a future that completes with a path suitable for JAVA_HOME /// or with null, if Java cannot be found. -Future findJavaHome() async { +Future findJavaHome() async { if (_javaHome == null) { final Iterable hits = grep( 'Java binary at: ', @@ -537,7 +534,7 @@ Future findJavaHome() async { } return _javaHome; } -String _javaHome; +String? _javaHome; Future inDirectory(dynamic directory, Future Function() action) async { final String previousCwd = cwd; @@ -568,12 +565,12 @@ void cd(dynamic directory) { Directory get flutterDirectory => Directory.current.parent.parent; String requireEnvVar(String name) { - final String value = Platform.environment[name]; + final String? value = Platform.environment[name]; if (value == null) fail('$name environment variable is missing. Quitting.'); - return value; + return value!; } T requireConfigProperty(Map map, String propertyName) { @@ -637,7 +634,7 @@ void checkNotNull(Object o1, } /// Splits [from] into lines and selects those that contain [pattern]. -Iterable grep(Pattern pattern, {@required String from}) { +Iterable grep(Pattern pattern, {required String from}) { return from.split('\n').where((String line) { return line.contains(pattern); }); @@ -675,8 +672,8 @@ final RegExp _obsUriRegExp = RegExp(r'((http|//)[a-zA-Z0-9:/=_\-\.\[\]]+)'); /// /// The `prefix`, if specified, is a regular expression pattern and must not contain groups. /// `prefix` defaults to the RegExp: `An Observatory debugger .* is available at: `. -int parseServicePort(String line, { - Pattern prefix, +int? parseServicePort(String line, { + Pattern? prefix, }) { prefix ??= _obsRegExp; final Iterable matchesIter = prefix.allMatches(line); @@ -686,15 +683,15 @@ int parseServicePort(String line, { final Match prefixMatch = matchesIter.first; final List matches = _obsPortRegExp.allMatches(line, prefixMatch.end).toList(); - return matches.isEmpty ? null : int.parse(matches[0].group(2)); + return matches.isEmpty ? null : int.parse(matches[0].group(2)!); } /// Tries to extract a URL from the string. /// /// The `prefix`, if specified, is a regular expression pattern and must not contain groups. /// `prefix` defaults to the RegExp: `An Observatory debugger .* is available at: `. -Uri parseServiceUri(String line, { - Pattern prefix, +Uri? parseServiceUri(String line, { + Pattern? prefix, }) { prefix ??= _obsRegExp; final Iterable matchesIter = prefix.allMatches(line); @@ -704,7 +701,7 @@ Uri parseServiceUri(String line, { final Match prefixMatch = matchesIter.first; final List matches = _obsUriRegExp.allMatches(line, prefixMatch.end).toList(); - return matches.isEmpty ? null : Uri.parse(matches[0].group(0)); + return matches.isEmpty ? null : Uri.parse(matches[0].group(0)!); } /// Checks that the file exists, otherwise throws a [FileSystemException]. @@ -771,7 +768,7 @@ void checkFileContains(List patterns, String filePath) { /// /// Removes the directory [path], then clones the git repository /// specified by [repo] to the directory [path]. -Future gitClone({String path, String repo}) async { +Future gitClone({required String path, required String repo}) async { rmTree(Directory(path)); await Directory(path).create(recursive: true); @@ -792,7 +789,7 @@ Future gitClone({String path, String repo}) async { /// Waits a constant duration of [delayDuration] between every retry attempt. Future retry( FutureOr Function() fn, { - FutureOr Function(Exception) retryIf, + FutureOr Function(Exception)? retryIf, int maxAttempts = 5, Duration delayDuration = const Duration(seconds: 3), }) async { diff --git a/dev/devicelab/lib/microbenchmarks.dart b/dev/devicelab/lib/microbenchmarks.dart index 4a0ebf21ba..008cc60aff 100644 --- a/dev/devicelab/lib/microbenchmarks.dart +++ b/dev/devicelab/lib/microbenchmarks.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:convert'; import 'dart:io'; diff --git a/dev/devicelab/lib/tasks/analysis.dart b/dev/devicelab/lib/tasks/analysis.dart index 9bcd1a5810..30fa74e5c7 100644 --- a/dev/devicelab/lib/tasks/analysis.dart +++ b/dev/devicelab/lib/tasks/analysis.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:io'; import 'package:path/path.dart' as path; diff --git a/dev/devicelab/lib/tasks/build_test_task.dart b/dev/devicelab/lib/tasks/build_test_task.dart index 81bdf3f0c3..14840078c2 100644 --- a/dev/devicelab/lib/tasks/build_test_task.dart +++ b/dev/devicelab/lib/tasks/build_test_task.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:io'; import 'package:args/args.dart'; @@ -18,10 +16,9 @@ import '../framework/utils.dart'; abstract class BuildTestTask { BuildTestTask(this.args, {this.workingDirectory, this.runFlutterClean = true,}) { final ArgResults argResults = argParser.parse(args); - applicationBinaryPath = argResults[kApplicationBinaryPathOption] as String; + applicationBinaryPath = argResults[kApplicationBinaryPathOption] as String?; buildOnly = argResults[kBuildOnlyFlag] as bool; testOnly = argResults[kTestOnlyFlag] as bool; - } static const String kApplicationBinaryPathOption = 'application-binary-path'; @@ -48,10 +45,10 @@ abstract class BuildTestTask { /// Path to a built application to use in [test]. /// /// If not given, will default to child's expected location. - String applicationBinaryPath; + String? applicationBinaryPath; /// Where the test artifacts are stored, such as performance results. - final Directory workingDirectory; + final Directory? workingDirectory; /// Run Flutter build to create [applicationBinaryPath]. Future build() async { @@ -93,7 +90,7 @@ abstract class BuildTestTask { /// /// Tasks can override to support default values. Otherwise, it will default /// to needing to be passed as an argument in the test runner. - String getApplicationBinaryPath() => applicationBinaryPath; + String? getApplicationBinaryPath() => applicationBinaryPath; /// Run this task. /// diff --git a/dev/devicelab/lib/tasks/dart_plugin_registry_tests.dart b/dev/devicelab/lib/tasks/dart_plugin_registry_tests.dart index 253cff5c55..c3ee1a8697 100644 --- a/dev/devicelab/lib/tasks/dart_plugin_registry_tests.dart +++ b/dev/devicelab/lib/tasks/dart_plugin_registry_tests.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:convert'; import 'dart:io'; @@ -15,8 +13,8 @@ import 'package:flutter_devicelab/framework/utils.dart'; import 'package:path/path.dart' as path; TaskFunction dartPluginRegistryTest({ - String deviceIdOverride, - Map environment, + String? deviceIdOverride, + Map? environment, }) { final Directory tempDir = Directory.systemTemp .createTempSync('flutter_devicelab_dart_plugin_test.'); diff --git a/dev/devicelab/lib/tasks/gallery.dart b/dev/devicelab/lib/tasks/gallery.dart index 0be7bd45f3..08d0851972 100644 --- a/dev/devicelab/lib/tasks/gallery.dart +++ b/dev/devicelab/lib/tasks/gallery.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:convert'; import 'dart:io'; import 'dart:math' as math; @@ -55,9 +53,9 @@ class GalleryTransitionTest { final bool needFullTimeline; final String testFile; final String timelineSummaryFile; - final String timelineTraceFile; - final String transitionDurationFile; - final String driverFile; + final String? timelineTraceFile; + final String? transitionDurationFile; + final String? driverFile; Future call() async { final Device device = await devices.workingDevice; @@ -65,7 +63,7 @@ class GalleryTransitionTest { final String deviceId = device.deviceId; final Directory galleryDirectory = dir('${flutterDirectory.path}/dev/integration_tests/flutter_gallery'); await inDirectory(galleryDirectory, () async { - String applicationBinaryPath; + String? applicationBinaryPath; if (deviceOperatingSystem == DeviceOperatingSystem.android) { section('BUILDING APPLICATION'); await flutter( diff --git a/dev/devicelab/lib/tasks/hot_mode_tests.dart b/dev/devicelab/lib/tasks/hot_mode_tests.dart index ca9eb43e67..2b44b9a2c2 100644 --- a/dev/devicelab/lib/tasks/hot_mode_tests.dart +++ b/dev/devicelab/lib/tasks/hot_mode_tests.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:convert'; import 'dart:io'; @@ -20,7 +18,7 @@ final Directory flutterGalleryDir = dir(path.join(flutterDirectory.path, 'dev/in const String kSourceLine = 'fontSize: (orientation == Orientation.portrait) ? 32.0 : 24.0'; const String kReplacementLine = 'fontSize: (orientation == Orientation.portrait) ? 34.0 : 24.0'; -TaskFunction createHotModeTest({String deviceIdOverride, Map environment}) { +TaskFunction createHotModeTest({String? deviceIdOverride, Map? environment}) { // This file is modified during the test and needs to be restored at the end. final File flutterFrameworkSource = file(path.join( flutterDirectory.path, 'packages/flutter/lib/src/widgets/framework.dart', @@ -35,13 +33,13 @@ TaskFunction createHotModeTest({String deviceIdOverride, Map env final File benchmarkFile = file(path.join(_editedFlutterGalleryDir.path, 'hot_benchmark.json')); rm(benchmarkFile); final List options = [ - '--hot', '-d', deviceIdOverride, '--benchmark', '--resident', '--no-android-gradle-daemon', '--no-publish-port', '--verbose', + '--hot', '-d', deviceIdOverride!, '--benchmark', '--resident', '--no-android-gradle-daemon', '--no-publish-port', '--verbose', ]; int hotReloadCount = 0; - Map smallReloadData; - Map mediumReloadData; - Map largeReloadData; - Map freshRestartReloadsData; + late Map smallReloadData; + late Map mediumReloadData; + late Map largeReloadData; + late Map freshRestartReloadsData; await inDirectory(flutterDirectory, () async { @@ -215,9 +213,9 @@ TaskFunction createHotModeTest({String deviceIdOverride, Map env }; } -Future> captureReloadData( +Future> captureReloadData( List options, - Map environment, + Map? environment, File benchmarkFile, void Function(String, Process) onLine, ) async { @@ -247,7 +245,7 @@ Future> captureReloadData( await Future.wait(>[stdoutDone.future, stderrDone.future]); await process.exitCode; - final Map result = json.decode(benchmarkFile.readAsStringSync()) as Map; + final Map result = json.decode(benchmarkFile.readAsStringSync()) as Map; benchmarkFile.deleteSync(); return result; } diff --git a/dev/devicelab/lib/tasks/integration_tests.dart b/dev/devicelab/lib/tasks/integration_tests.dart index 7408538923..7a8f783607 100644 --- a/dev/devicelab/lib/tasks/integration_tests.dart +++ b/dev/devicelab/lib/tasks/integration_tests.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import '../framework/devices.dart'; import '../framework/framework.dart'; import '../framework/task_result.dart'; diff --git a/dev/devicelab/lib/tasks/microbenchmarks.dart b/dev/devicelab/lib/tasks/microbenchmarks.dart index 91a6a0a54b..957ab4cd8e 100644 --- a/dev/devicelab/lib/tasks/microbenchmarks.dart +++ b/dev/devicelab/lib/tasks/microbenchmarks.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:io'; diff --git a/dev/devicelab/lib/tasks/new_gallery.dart b/dev/devicelab/lib/tasks/new_gallery.dart index afe69a1752..ee53732811 100644 --- a/dev/devicelab/lib/tasks/new_gallery.dart +++ b/dev/devicelab/lib/tasks/new_gallery.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:io'; import 'package:flutter_devicelab/tasks/perf_tests.dart'; diff --git a/dev/devicelab/lib/tasks/perf_tests.dart b/dev/devicelab/lib/tasks/perf_tests.dart index e7235edbb1..7fd1840c2f 100644 --- a/dev/devicelab/lib/tasks/perf_tests.dart +++ b/dev/devicelab/lib/tasks/perf_tests.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:convert' show LineSplitter, json, utf8; import 'dart:io'; @@ -516,7 +514,7 @@ class StartupTest { final List> results = >[]; section('Building application'); - String applicationBinaryPath; + String? applicationBinaryPath; switch (deviceOperatingSystem) { case DeviceOperatingSystem.android: await flutter('build', options: [ @@ -586,7 +584,7 @@ class StartupTest { '-d', device.deviceId, '--out', - hostAgent.dumpDirectory + hostAgent.dumpDirectory! .childFile('screenshot_startup_failure_$currentFailures.png') .path, ], @@ -630,7 +628,7 @@ class DevtoolsStartupTest { final Device device = await devices.workingDevice; section('Building application'); - String applicationBinaryPath; + String? applicationBinaryPath; switch (deviceOperatingSystem) { case DeviceOperatingSystem.android: await flutter('build', options: [ @@ -733,7 +731,7 @@ class PerfTest { this.needsFullTimeline = true, this.benchmarkScoreKeys, this.dartDefine = '', - String resultFilename, + String? resultFilename, }): _resultFilename = resultFilename; const PerfTest.e2e( @@ -753,12 +751,12 @@ class PerfTest { /// The main entry-point file of the application, as run on the device. final String testTarget; // The prefix name of the filename such as `.timeline_summary.json`. - final String timelineFileName; + final String? timelineFileName; String get traceFilename => '$timelineFileName.timeline'; String get resultFilename => _resultFilename ?? '$timelineFileName.timeline_summary'; - final String _resultFilename; + final String? _resultFilename; /// The test file to run on the host. - final String testDriver; + final String? testDriver; /// Whether to collect CPU and GPU metrics. final bool measureCpuGpu; /// Whether to collect memory metrics. @@ -788,7 +786,7 @@ class PerfTest { /// if (measureCpuGpu) 'average_gpu_usage', /// ] /// ``` - final List benchmarkScoreKeys; + final List? benchmarkScoreKeys; /// Additional flags for `--dart-define` to control the test final String dartDefine; @@ -800,8 +798,8 @@ class PerfTest { @protected Future internalRun({ bool cacheSkSL = false, - String existingApp, - String writeSkslFileName, + String? existingApp, + String? writeSkslFileName, }) { return inDirectory(testDirectory, () async { final Device device = await devices.workingDevice; @@ -818,7 +816,7 @@ class PerfTest { '--trace-startup', // Enables "endless" timeline event buffering. '-t', testTarget, if (testDriver != null) - ...['--driver', testDriver], + ...['--driver', testDriver!], if (existingApp != null) ...['--use-existing-app', existingApp], if (writeSkslFileName != null) @@ -890,9 +888,9 @@ class PerfTestWithSkSL extends PerfTest { String testTarget, String timelineFileName, { bool measureCpuGpu = false, - String testDriver, + String? testDriver, bool needsFullTimeline = true, - List benchmarkScoreKeys, + List? benchmarkScoreKeys, }) : super( testDirectory, testTarget, @@ -964,7 +962,7 @@ class PerfTestWithSkSL extends PerfTest { ); } - Future _runApp({String appBinary, bool cacheSkSL = false, String skslPath}) async { + Future _runApp({String? appBinary, bool cacheSkSL = false, String? skslPath}) async { if (File(_vmserviceFileName).existsSync()) { File(_vmserviceFileName).deleteSync(); } @@ -1027,9 +1025,9 @@ class PerfTestWithSkSL extends PerfTest { }); } - String _flutterPath; - Device _device; - Process _runProcess; + late String _flutterPath; + late Device _device; + late Process _runProcess; static const String _kVmserviceOutFileName = 'vmservice.out'; } @@ -1073,12 +1071,16 @@ class WebCompileTest { /// /// Run a single web compile test for the app under [directory], and store /// its metrics with prefix [metric]. - static Future> runSingleBuildTest({String directory, String metric, bool measureBuildTime = false}) { + static Future> runSingleBuildTest({ + required String directory, + required String metric, + bool measureBuildTime = false, + }) { return inDirectory>(directory, () async { final Map metrics = {}; await flutter('packages', options: ['get']); - final Stopwatch watch = measureBuildTime ? Stopwatch() : null; + final Stopwatch? watch = measureBuildTime ? Stopwatch() : null; watch?.start(); await evalFlutter('build', options: [ 'web', @@ -1091,7 +1093,7 @@ class WebCompileTest { metrics.addAll(await getSize(outputFileName, metric: metric)); if (measureBuildTime) { - metrics['${metric}_dart2js_millis'] = watch.elapsedMilliseconds; + metrics['${metric}_dart2js_millis'] = watch!.elapsedMilliseconds; } return metrics; @@ -1099,7 +1101,7 @@ class WebCompileTest { } /// Obtains the size and gzipped size of a file given by [fileName]. - static Future> getSize(String fileName, {String metric}) async { + static Future> getSize(String fileName, {required String metric}) async { final Map sizeMetrics = {}; final ProcessResult result = await Process.run('du', ['-k', fileName]); @@ -1168,10 +1170,12 @@ class CompileTest { await flutter('build', options: options); watch.stop(); final Directory appBuildDirectory = dir(path.join(cwd, 'build/ios/Release-iphoneos')); - final Directory appBundle = appBuildDirectory + final Directory? appBundle = appBuildDirectory .listSync() - .whereType() - .singleWhere((Directory directory) => path.extension(directory.path) == '.app', orElse: () => null); + .whereType() + .singleWhere((Directory? directory) => + directory != null && path.extension(directory.path) == '.app', + orElse: () => null); if (appBundle == null) { throw 'Failed to find app bundle in ${appBuildDirectory.path}'; } @@ -1226,8 +1230,8 @@ class CompileTest { } static Future> _compileDebug({ - @required bool clean, - @required String metricKey, + required bool clean, + required String metricKey, }) async { if (clean) { await flutter('clean'); @@ -1290,9 +1294,9 @@ class CompileTest { fileToMetadata[entry.path] = entry; } - final _UnzipListEntry libflutter = fileToMetadata['lib/armeabi-v7a/libflutter.so']; - final _UnzipListEntry libapp = fileToMetadata['lib/armeabi-v7a/libapp.so']; - final _UnzipListEntry license = fileToMetadata['assets/flutter_assets/NOTICES.Z']; + final _UnzipListEntry libflutter = fileToMetadata['lib/armeabi-v7a/libflutter.so']!; + final _UnzipListEntry libapp = fileToMetadata['lib/armeabi-v7a/libapp.so']!; + final _UnzipListEntry license = fileToMetadata['assets/flutter_assets/NOTICES.Z']!; return { 'libflutter_uncompressed_bytes': libflutter.uncompressedSize, @@ -1315,9 +1319,9 @@ class MemoryTest { /// Completes when the log line specified in the last call to /// [prepareForNextMessage] is seen by `adb logcat`. - Future get receivedNextMessage => _receivedNextMessage?.future; - Completer _receivedNextMessage; - String _nextMessage; + Future? get receivedNextMessage => _receivedNextMessage?.future; + Completer? _receivedNextMessage; + String? _nextMessage; /// Prepares the [receivedNextMessage] future such that it will complete /// when `adb logcat` sees a log line with the given `message`. @@ -1328,8 +1332,8 @@ class MemoryTest { int get iterationCount => 10; - Device get device => _device; - Device _device; + Device? get device => _device; + Device? _device; Future run() { return inDirectory(project, () async { @@ -1337,13 +1341,13 @@ class MemoryTest { // device.getMemoryStats, etc, aren't implemented for iOS. _device = await devices.workingDevice; - await device.unlock(); + await device!.unlock(); await flutter('packages', options: ['get']); - final StreamSubscription adb = device.logcat.listen( + final StreamSubscription adb = device!.logcat.listen( (String data) { if (data.contains('==== MEMORY BENCHMARK ==== $_nextMessage ====')) - _receivedNextMessage.complete(); + _receivedNextMessage?.complete(); }, ); @@ -1356,12 +1360,12 @@ class MemoryTest { assert(_endMemory.length == iteration + 1); assert(_diffMemory.length == iteration + 1); print('terminating...'); - await device.stop(package); + await device!.stop(package); await Future.delayed(const Duration(milliseconds: 10)); } await adb.cancel(); - await flutter('install', options: ['--uninstall-only', '-d', device.deviceId]); + await flutter('install', options: ['--uninstall-only', '-d', device!.deviceId]); final ListStatistics startMemoryStatistics = ListStatistics(_startMemory); final ListStatistics endMemoryStatistics = ListStatistics(_endMemory); @@ -1392,7 +1396,7 @@ class MemoryTest { '--verbose', '--release', '--no-resident', - '-d', device.deviceId, + '-d', device!.deviceId, test, ]); print('awaiting "ready" message...'); @@ -1411,7 +1415,7 @@ class MemoryTest { prepareForNextMessage('DONE'); print('tapping device...'); - await device.tap(100, 100); + await device!.tap(100, 100); print('awaiting "done" message...'); await receivedNextMessage; @@ -1422,23 +1426,23 @@ class MemoryTest { final List _endMemory = []; final List _diffMemory = []; - Map _startMemoryUsage; + Map? _startMemoryUsage; @protected Future recordStart() async { assert(_startMemoryUsage == null); print('snapshotting memory usage...'); - _startMemoryUsage = await device.getMemoryStats(package); + _startMemoryUsage = await device!.getMemoryStats(package); } @protected Future recordEnd() async { assert(_startMemoryUsage != null); print('snapshotting memory usage...'); - final Map endMemoryUsage = await device.getMemoryStats(package); - _startMemory.add(_startMemoryUsage['total_kb'] as int); + final Map endMemoryUsage = await device!.getMemoryStats(package); + _startMemory.add(_startMemoryUsage!['total_kb'] as int); _endMemory.add(endMemoryUsage['total_kb'] as int); - _diffMemory.add((endMemoryUsage['total_kb'] as int) - (_startMemoryUsage['total_kb'] as int)); + _diffMemory.add((endMemoryUsage['total_kb'] as int) - (_startMemoryUsage!['total_kb'] as int)); } } @@ -1487,7 +1491,7 @@ class DevToolsMemoryTest { }); } - Device _device; + late Device _device; static const String _kJsonFileName = 'devtools_memory.json'; } @@ -1505,7 +1509,6 @@ String _reportedDurationTestToString(ReportedDurationTestFlavor flavor) { case ReportedDurationTestFlavor.release: return 'release'; } - throw ArgumentError('Unexpected value for enum $flavor'); } class ReportedDurationTest { @@ -1521,8 +1524,8 @@ class ReportedDurationTest { int get iterationCount => 10; - Device get device => _device; - Device _device; + Device? get device => _device; + Device? _device; Future run() { return inDirectory(project, () async { @@ -1530,13 +1533,13 @@ class ReportedDurationTest { // device.getMemoryStats, etc, aren't implemented for iOS. _device = await devices.workingDevice; - await device.unlock(); + await device!.unlock(); await flutter('packages', options: ['get']); - final StreamSubscription adb = device.logcat.listen( + final StreamSubscription adb = device!.logcat.listen( (String data) { if (durationPattern.hasMatch(data)) - durationCompleter.complete(int.parse(durationPattern.firstMatch(data).group(1))); + durationCompleter.complete(int.parse(durationPattern.firstMatch(data)!.group(1)!)); }, ); print('launching $project$test on device...'); @@ -1546,13 +1549,13 @@ class ReportedDurationTest { '--no-fast-start', '--${_reportedDurationTestToString(flavor)}', '--no-resident', - '-d', device.deviceId, + '-d', device!.deviceId, test, ]); final int duration = await durationCompleter.future; print('terminating...'); - await device.stop(package); + await device!.stop(package); await adb.cancel(); _device = null; @@ -1607,9 +1610,9 @@ class _UnzipListEntry { } _UnzipListEntry._({ - @required this.uncompressedSize, - @required this.compressedSize, - @required this.path, + required this.uncompressedSize, + required this.compressedSize, + required this.path, }) : assert(uncompressedSize != null), assert(compressedSize != null), assert(compressedSize <= uncompressedSize), @@ -1633,7 +1636,7 @@ Future waitForFile(String path) async { throw StateError('Did not find vmservice out file after 400 seconds'); } -String _findIosAppInBuildDirectory(String searchDirectory) { +String? _findIosAppInBuildDirectory(String searchDirectory) { for (final FileSystemEntity entity in Directory(searchDirectory).listSync()) { if (entity.path.endsWith('.app')) { return entity.path; diff --git a/dev/devicelab/lib/tasks/platform_channels_benchmarks.dart b/dev/devicelab/lib/tasks/platform_channels_benchmarks.dart index 361d0502a4..767e888d10 100644 --- a/dev/devicelab/lib/tasks/platform_channels_benchmarks.dart +++ b/dev/devicelab/lib/tasks/platform_channels_benchmarks.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:io' show Process, Directory; import 'package:flutter_devicelab/framework/devices.dart' as adb; diff --git a/dev/devicelab/lib/tasks/plugin_tests.dart b/dev/devicelab/lib/tasks/plugin_tests.dart index 47875f82fe..445b40fce1 100644 --- a/dev/devicelab/lib/tasks/plugin_tests.dart +++ b/dev/devicelab/lib/tasks/plugin_tests.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:io'; import 'package:flutter_devicelab/framework/framework.dart'; @@ -31,8 +29,8 @@ class PluginTest { final String buildTarget; final List options; - final Map pluginCreateEnvironment; - final Map appCreateEnvironment; + final Map? pluginCreateEnvironment; + final Map? appCreateEnvironment; Future call() async { final Directory tempDir = @@ -77,7 +75,7 @@ class _FlutterProject { String get rootPath => path.join(parent.path, name); - Future addPlugin(String plugin, {String pluginPath}) async { + Future addPlugin(String plugin, {String? pluginPath}) async { final File pubspec = File(path.join(rootPath, 'pubspec.yaml')); String content = await pubspec.readAsString(); final String dependency = @@ -100,9 +98,9 @@ class _FlutterProject { List options, String target, { - String name, - String template, - Map environment, + required String name, + required String template, + Map? environment, }) async { await inDirectory(directory, () async { await flutter( diff --git a/dev/devicelab/lib/tasks/web_benchmarks.dart b/dev/devicelab/lib/tasks/web_benchmarks.dart index 77af15db3d..cdafeadf42 100644 --- a/dev/devicelab/lib/tasks/web_benchmarks.dart +++ b/dev/devicelab/lib/tasks/web_benchmarks.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:convert' show json; import 'dart:io' as io; @@ -13,7 +11,6 @@ import 'package:flutter_devicelab/framework/browser.dart'; import 'package:flutter_devicelab/framework/task_result.dart'; import 'package:flutter_devicelab/framework/utils.dart'; import 'package:logging/logging.dart'; -import 'package:meta/meta.dart'; import 'package:path/path.dart' as path; import 'package:shelf/shelf.dart'; import 'package:shelf/shelf_io.dart' as shelf_io; @@ -23,7 +20,7 @@ import 'package:shelf_static/shelf_static.dart'; const int benchmarkServerPort = 9999; const int chromeDebugPort = 10000; -Future runWebBenchmark({ @required bool useCanvasKit }) async { +Future runWebBenchmark({ required bool useCanvasKit }) async { // Reduce logging level. Otherwise, package:webkit_inspection_protocol is way too spammy. Logger.root.level = Level.INFO; final String macrobenchmarksDirectory = path.join(flutterDirectory.path, 'dev', 'benchmarks', 'macrobenchmarks'); @@ -38,17 +35,17 @@ Future runWebBenchmark({ @required bool useCanvasKit }) async { ]); final Completer>> profileData = Completer>>(); final List> collectedProfiles = >[]; - List benchmarks; - Iterator benchmarkIterator; + List? benchmarks; + late Iterator benchmarkIterator; // This future fixes a race condition between the web-page loading and // asking to run a benchmark, and us connecting to Chrome's DevTools port. // Sometime one wins. Other times, the other wins. - Future whenChromeIsReady; - Chrome chrome; - io.HttpServer server; + Future? whenChromeIsReady; + Chrome? chrome; + late io.HttpServer server; Cascade cascade = Cascade(); - List> latestPerformanceTrace; + List>? latestPerformanceTrace; cascade = cascade.add((Request request) async { try { chrome ??= await whenChromeIsReady; @@ -66,7 +63,7 @@ Future runWebBenchmark({ @required bool useCanvasKit }) async { // Trace data is null when the benchmark is not frame-based, such as RawRecorder. if (latestPerformanceTrace != null) { - final BlinkTraceSummary traceSummary = BlinkTraceSummary.fromJson(latestPerformanceTrace); + final BlinkTraceSummary traceSummary = BlinkTraceSummary.fromJson(latestPerformanceTrace!)!; profile['totalUiFrame.average'] = traceSummary.averageTotalUIFrameTime.inMicroseconds; profile['scoreKeys'] ??= []; // using dynamic for consistency with JSON (profile['scoreKeys'] as List).add('totalUiFrame.average'); @@ -76,10 +73,10 @@ Future runWebBenchmark({ @required bool useCanvasKit }) async { return Response.ok('Profile received'); } else if (request.requestedUri.path.endsWith('/start-performance-tracing')) { latestPerformanceTrace = null; - await chrome.beginRecordingPerformance(request.requestedUri.queryParameters['label']); + await chrome!.beginRecordingPerformance(request.requestedUri.queryParameters['label']!); return Response.ok('Started performance tracing'); } else if (request.requestedUri.path.endsWith('/stop-performance-tracing')) { - latestPerformanceTrace = await chrome.endRecordingPerformance(); + latestPerformanceTrace = await chrome!.endRecordingPerformance(); return Response.ok('Stopped performance tracing'); } else if (request.requestedUri.path.endsWith('/on-error')) { final Map errorDetails = json.decode(await request.readAsString()) as Map; @@ -90,7 +87,7 @@ Future runWebBenchmark({ @required bool useCanvasKit }) async { } else if (request.requestedUri.path.endsWith('/next-benchmark')) { if (benchmarks == null) { benchmarks = (json.decode(await request.readAsString()) as List).cast(); - benchmarkIterator = benchmarks.iterator; + benchmarkIterator = benchmarks!.iterator; } if (benchmarkIterator.moveNext()) { final String nextBenchmark = benchmarkIterator.current; @@ -186,7 +183,7 @@ Future runWebBenchmark({ @required bool useCanvasKit }) async { } return TaskResult.success(taskResult, benchmarkScoreKeys: benchmarkScoreKeys); } finally { - unawaited(server?.close()); + unawaited(server.close()); chrome?.stop(); } }); diff --git a/dev/devicelab/lib/tasks/web_dev_mode_tests.dart b/dev/devicelab/lib/tasks/web_dev_mode_tests.dart index 6164328d16..22aa5add24 100644 --- a/dev/devicelab/lib/tasks/web_dev_mode_tests.dart +++ b/dev/devicelab/lib/tasks/web_dev_mode_tests.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 - import 'dart:async'; import 'dart:convert'; import 'dart:io';