diff --git a/packages/flutter_goldens/lib/flutter_goldens.dart b/packages/flutter_goldens/lib/flutter_goldens.dart index 739d6d94bc..c6b63eecb9 100644 --- a/packages/flutter_goldens/lib/flutter_goldens.dart +++ b/packages/flutter_goldens/lib/flutter_goldens.dart @@ -103,10 +103,7 @@ abstract class FlutterGoldenFileComparator extends GoldenFileComparator { this.skiaClient, { this.fs = const LocalFileSystem(), this.platform = const LocalPlatform(), - }) : assert(basedir != null), - assert(skiaClient != null), - assert(fs != null), - assert(platform != null); + }); /// The directory to which golden file URIs will be resolved in [compare] and /// [update], cannot be null. @@ -132,7 +129,7 @@ abstract class FlutterGoldenFileComparator extends GoldenFileComparator { } @override - Uri getTestUri(Uri key, int version) => key; + Uri getTestUri(Uri key, int? version) => key; /// Calculate the appropriate basedir for the current test context. /// @@ -231,8 +228,8 @@ class FlutterPostSubmitFileComparator extends FlutterGoldenFileComparator { /// purposes only. static Future fromDefaultComparator( final Platform platform, { - SkiaGoldClient goldens, - LocalFileComparator defaultComparator, + SkiaGoldClient? goldens, + LocalFileComparator? defaultComparator, }) async { defaultComparator ??= goldenFileComparator as LocalFileComparator; @@ -326,9 +323,9 @@ class FlutterPreSubmitFileComparator extends FlutterGoldenFileComparator { /// purposes only. static Future fromDefaultComparator( final Platform platform, { - SkiaGoldClient goldens, - LocalFileComparator defaultComparator, - final Directory testBasedir, + SkiaGoldClient? goldens, + LocalFileComparator? defaultComparator, + Directory? testBasedir, }) async { defaultComparator ??= goldenFileComparator as LocalFileComparator; @@ -353,7 +350,7 @@ class FlutterPreSubmitFileComparator extends FlutterGoldenFileComparator { // Some contributors may not have permission on Cirrus to decrypt the // service account. onCirrusWithPermission = - !platform.environment['GOLD_SERVICE_ACCOUNT'].startsWith('ENCRYPTED'); + !platform.environment['GOLD_SERVICE_ACCOUNT']!.startsWith('ENCRYPTED'); } final bool onLuci = platform.environment.containsKey('SWARMING_TASK_ID'); if (onCirrusWithPermission || onLuci) { @@ -457,7 +454,7 @@ class _UnauthorizedFlutterPreSubmitComparator extends FlutterPreSubmitFileCompar // low. skiaClient.getExpectations(); final String testName = skiaClient.cleanTestName(golden.path); - final List testExpectations = skiaClient.expectations[testName]; + final List? testExpectations = skiaClient.expectations[testName]; if (testExpectations == null) { // This is a new test. print('No expectations provided by Skia Gold for test: $golden. ' @@ -502,8 +499,7 @@ class FlutterSkippingFileComparator extends FlutterGoldenFileComparator { final Uri basedir, final SkiaGoldClient skiaClient, this.reason, - ) : assert(reason != null), - super(basedir, skiaClient); + ) : super(basedir, skiaClient); /// Describes the reason for using the [FlutterSkippingFileComparator]. /// @@ -514,12 +510,12 @@ class FlutterSkippingFileComparator extends FlutterGoldenFileComparator { /// relative path resolution of the default [goldenFileComparator]. static FlutterSkippingFileComparator fromDefaultComparator( String reason, { - LocalFileComparator defaultComparator, + LocalFileComparator? defaultComparator, }) { defaultComparator ??= goldenFileComparator as LocalFileComparator; const FileSystem fs = LocalFileSystem(); final Uri basedir = defaultComparator.basedir; - final SkiaGoldClient skiaClient = SkiaGoldClient(fs.directory(basedir)); + final SkiaGoldClient skiaClient = SkiaGoldClient(fs.directory(basedir), ci: ContinuousIntegrationEnvironment.none); return FlutterSkippingFileComparator(basedir, skiaClient, reason); } @@ -532,7 +528,7 @@ class FlutterSkippingFileComparator extends FlutterGoldenFileComparator { } @override - Future update(Uri golden, Uint8List imageBytes) => null; + Future update(Uri golden, Uint8List imageBytes) async {} /// Decides, based on the current environment, if this comparator should be /// used. @@ -596,9 +592,9 @@ class FlutterLocalFileComparator extends FlutterGoldenFileComparator with LocalC /// visible for testing purposes only. static Future fromDefaultComparator( final Platform platform, { - SkiaGoldClient goldens, - LocalFileComparator defaultComparator, - Directory baseDirectory, + SkiaGoldClient? goldens, + LocalFileComparator? defaultComparator, + Directory? baseDirectory, }) async { defaultComparator ??= goldenFileComparator as LocalFileComparator; baseDirectory ??= FlutterGoldenFileComparator.getBaseDirectory( @@ -611,7 +607,7 @@ class FlutterLocalFileComparator extends FlutterGoldenFileComparator with LocalC baseDirectory.createSync(recursive: true); } - goldens ??= SkiaGoldClient(baseDirectory); + goldens ??= SkiaGoldClient(baseDirectory, ci: ContinuousIntegrationEnvironment.none); try { await goldens.getExpectations(); @@ -638,7 +634,7 @@ class FlutterLocalFileComparator extends FlutterGoldenFileComparator with LocalC Future compare(Uint8List imageBytes, Uri golden) async { golden = _addPrefix(golden); final String testName = skiaClient.cleanTestName(golden.path); - final List testExpectations = skiaClient.expectations[testName]; + final List? testExpectations = skiaClient.expectations[testName]; if (testExpectations == null) { // There is no baseline for this test print('No expectations provided by Skia Gold for test: $golden. ' diff --git a/packages/flutter_goldens/pubspec.yaml b/packages/flutter_goldens/pubspec.yaml index 351cb09393..7abdec0dad 100644 --- a/packages/flutter_goldens/pubspec.yaml +++ b/packages/flutter_goldens/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_goldens environment: # The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite. - sdk: ">=2.0.0-dev.68.0 <3.0.0" + sdk: ">=2.10.0-4.0.dev <2.10.0" dependencies: # To update these, use "flutter update-packages --force-upgrade". diff --git a/packages/flutter_goldens/test/flutter_goldens_test.dart b/packages/flutter_goldens/test/flutter_goldens_test.dart index 5045a095b3..1177b87767 100644 --- a/packages/flutter_goldens/test/flutter_goldens_test.dart +++ b/packages/flutter_goldens/test/flutter_goldens_test.dart @@ -2,6 +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:async'; import 'dart:convert'; import 'dart:core'; @@ -75,6 +76,7 @@ void main() { process: process, platform: platform, httpClient: mockHttpClient, + ci: ContinuousIntegrationEnvironment.luci, ); }); @@ -148,6 +150,7 @@ void main() { process: process, platform: platform, httpClient: mockHttpClient, + ci: ContinuousIntegrationEnvironment.luci ); when(process.run( diff --git a/packages/flutter_goldens_client/lib/skia_client.dart b/packages/flutter_goldens_client/lib/skia_client.dart index 0710eeb7e5..251707c25b 100644 --- a/packages/flutter_goldens_client/lib/skia_client.dart +++ b/packages/flutter_goldens_client/lib/skia_client.dart @@ -25,6 +25,7 @@ const String _kTestBrowserKey = 'FLUTTER_TEST_BROWSER'; enum ContinuousIntegrationEnvironment { luci, cirrus, + none, } /// A client for uploading image tests and making baseline requests to the @@ -35,13 +36,9 @@ class SkiaGoldClient { this.fs = const LocalFileSystem(), this.process = const LocalProcessManager(), this.platform = const LocalPlatform(), - this.ci, - io.HttpClient httpClient, - }) : assert(workDirectory != null), - assert(fs != null), - assert(process != null), - assert(platform != null), - httpClient = httpClient ?? io.HttpClient(); + required this.ci, + io.HttpClient? httpClient, + }) : httpClient = httpClient ?? io.HttpClient(); /// The file system to use for storing the local clone of the repository. /// @@ -83,7 +80,7 @@ class SkiaGoldClient { /// [_UnauthorizedFlutterPreSubmitComparator] to test against golden masters /// maintained in the Flutter Gold dashboard. Map> get expectations => _expectations; - Map> _expectations; + late Map> _expectations; /// The local [Directory] where the Flutter repository is hosted. /// @@ -93,13 +90,13 @@ class SkiaGoldClient { /// The path to the local [Directory] where the goldctl tool is hosted. /// /// Uses the [platform] environment in this implementation. - String/*!*/ get _goldctl => platform.environment[_kGoldctlKey]; + String get _goldctl => platform.environment[_kGoldctlKey]!; /// The path to the local [Directory] where the service account key is /// hosted. /// /// Uses the [platform] environment in this implementation. - String/*!*/ get _serviceAccount => platform.environment[_kServiceAccountKey]; + String get _serviceAccount => platform.environment[_kServiceAccountKey]!; /// Prepares the local work space for golden file testing and calls the /// goldctl `auth` command. @@ -116,9 +113,9 @@ class SkiaGoldClient { return; List authArguments; - /*late*/ String failureContext; + String failureContext; - switch (ci/*!*/) { + switch (ci) { case ContinuousIntegrationEnvironment.luci: authArguments = [ 'auth', @@ -154,6 +151,8 @@ class SkiaGoldClient { 'Cirrus, if the debug information below contains ENCRYPTED, the wrong ' 'comparator was chosen for the test case.'; break; + case ContinuousIntegrationEnvironment.none: + return; } final io.ProcessResult result = await io.Process.run( @@ -267,9 +266,6 @@ class SkiaGoldClient { /// The [testName] and [goldenFile] parameters reference the current /// comparison being evaluated by the [FlutterPostSubmitFileComparator]. Future imgtestAdd(String testName, File goldenFile) async { - assert(testName != null); - assert(goldenFile != null); - final List imgtestArguments = [ 'imgtest', 'add', '--work-dir', workDirectory @@ -361,9 +357,6 @@ class SkiaGoldClient { /// The [testName] and [goldenFile] parameters reference the current /// comparison being evaluated by the [_AuthorizedFlutterPreSubmitComparator]. Future tryjobAdd(String testName, File goldenFile) async { - assert(testName != null); - assert(goldenFile != null); - final List imgtestArguments = [ 'imgtest', 'add', '--work-dir', workDirectory @@ -410,9 +403,6 @@ class SkiaGoldClient { /// comparison being evaluated by the /// [_UnauthorizedFlutterPreSubmitComparator]. Future imgtestCheck(String testName, File goldenFile) async { - assert(testName != null); - assert(goldenFile != null); - final List imgtestArguments = [ 'imgtest', 'check', '--work-dir', workDirectory @@ -440,7 +430,7 @@ class SkiaGoldClient { ); const String mainKey = 'master'; const String temporaryKey = 'master_str'; - String rawResponse; + late String rawResponse; try { final io.HttpClientRequest request = await httpClient.getUrl(requestForExpectations); final io.HttpClientResponse response = await request.close(); @@ -448,7 +438,7 @@ class SkiaGoldClient { final dynamic jsonResponse = json.decode(rawResponse); if (jsonResponse is! Map) throw const FormatException('Skia gold expectations do not match expected format.'); - final Map skiaJson = (jsonResponse[mainKey] ?? jsonResponse[temporaryKey]) as Map; + final Map? skiaJson = (jsonResponse[mainKey] ?? jsonResponse[temporaryKey]) as Map?; if (skiaJson == null) throw FormatException('Skia gold expectations are missing the "$mainKey" key (and also doesn\'t have "$temporaryKey")! Available keys: ${jsonResponse.keys.join(", ")}'); skiaJson.forEach((String key, dynamic value) { @@ -506,7 +496,7 @@ class SkiaGoldClient { Future testIsIgnoredForPullRequest(String pullRequest, String testName) async { bool ignoreIsActive = false; testName = cleanTestName(testName); - String rawResponse; + late String rawResponse; await io.HttpOverrides.runWithHttpOverrides>(() async { final Uri requestForIgnores = Uri.parse( 'https://flutter-gold.skia.org/json/ignores' @@ -565,7 +555,7 @@ class SkiaGoldClient { Future isValidDigestForExpectation(String expectation, String testName) async { bool isValid = false; testName = cleanTestName(testName); - String rawResponse; + late String rawResponse; await io.HttpOverrides.runWithHttpOverrides>(() async { final Uri requestForDigest = Uri.parse( 'https://flutter-gold.skia.org/json/details?test=$testName&digest=$expectation' @@ -653,22 +643,24 @@ class SkiaGoldClient { /// Returns a list of arguments for initializing a tryjob based on the testing /// environment. List getCIArguments() { - /*late*/ String/*!*/ pullRequest; - /*late*/ String/*!*/ jobId; - /*late*/ String cis; + String pullRequest; + String jobId; + String cis; - switch (ci/*!*/) { + switch (ci) { case ContinuousIntegrationEnvironment.luci: - jobId = platform.environment['LOGDOG_STREAM_PREFIX'].split('/').last; - final List refs = platform.environment['GOLD_TRYJOB'].split('/'); + jobId = platform.environment['LOGDOG_STREAM_PREFIX']!.split('/').last; + final List refs = platform.environment['GOLD_TRYJOB']!.split('/'); pullRequest = refs[refs.length - 2]; cis = 'buildbucket'; break; case ContinuousIntegrationEnvironment.cirrus: - pullRequest = platform.environment['CIRRUS_PR']; - jobId = platform.environment['CIRRUS_TASK_ID']; + pullRequest = platform.environment['CIRRUS_PR']!; + jobId = platform.environment['CIRRUS_TASK_ID']!; cis = 'cirrus'; break; + case ContinuousIntegrationEnvironment.none: + return []; } return [ @@ -685,17 +677,17 @@ class SkiaGoldHttpOverrides extends io.HttpOverrides {} /// A digest returned from a request to the Flutter Gold dashboard. class SkiaGoldDigest { const SkiaGoldDigest({ - this.imageHash, - this.paramSet, - this.testName, - this.status, + required this.imageHash, + required this.paramSet, + required this.testName, + required this.status, }); /// Create a digest from requested JSON. factory SkiaGoldDigest.fromJson(Map json) { return SkiaGoldDigest( imageHash: json['digest'] as String, - paramSet: Map.from(json['paramset'] as Map ?? + paramSet: Map.from(json['paramset'] as Map? ?? >{ 'Platform': [], 'Browser' : [], @@ -706,16 +698,16 @@ class SkiaGoldDigest { } /// Unique identifier for the image associated with the digest. - final String/*!*/ imageHash; + final String imageHash; /// Parameter set for the given test, e.g. Platform : Windows. - final Map/*!*/ paramSet; + final Map paramSet; /// Test name associated with the digest, e.g. positive or un-triaged. - final String/*!*/ testName; + final String testName; /// Status of the given digest, e.g. positive or un-triaged. - final String/*!*/ status; + final String status; /// Validates a given digest against the current testing conditions. bool isValid(Platform platform, String name, String expectation) { diff --git a/packages/flutter_goldens_client/pubspec.yaml b/packages/flutter_goldens_client/pubspec.yaml index 872aaaf397..32bc7f97f3 100644 --- a/packages/flutter_goldens_client/pubspec.yaml +++ b/packages/flutter_goldens_client/pubspec.yaml @@ -2,7 +2,7 @@ name: flutter_goldens_client environment: # The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite. - sdk: ">=2.0.0-dev.68.0 <3.0.0" + sdk: ">=2.10.0-4.0.dev <2.10.0 <3.0.0" dependencies: # To update these, use "flutter update-packages --force-upgrade". diff --git a/packages/flutter_test/lib/src/_goldens_io.dart b/packages/flutter_test/lib/src/_goldens_io.dart index 5db2baf25a..531fead90b 100644 --- a/packages/flutter_test/lib/src/_goldens_io.dart +++ b/packages/flutter_test/lib/src/_goldens_io.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// @dart = 2.10 import 'dart:async'; import 'dart:io'; import 'dart:math' as math; @@ -61,15 +62,15 @@ class LocalFileComparator extends GoldenFileComparator with LocalComparisonOutpu /// directory in which [testFile] resides. /// /// The [testFile] URL must represent a file. - LocalFileComparator(Uri testFile, {path.Style pathStyle}) + LocalFileComparator(Uri testFile, {path.Style? pathStyle}) : basedir = _getBasedir(testFile, pathStyle), _path = _getPath(pathStyle); - static path.Context _getPath(path.Style style) { + static path.Context _getPath(path.Style? style) { return path.Context(style: style ?? path.Style.platform); } - static Uri _getBasedir(Uri testFile, path.Style pathStyle) { + static Uri _getBasedir(Uri testFile, path.Style? pathStyle) { final path.Context context = _getPath(pathStyle); final String testFilePath = context.fromUri(testFile); final String testDirectoryPath = context.dirname(testFilePath); @@ -135,7 +136,7 @@ class LocalComparisonOutput { if (result.diffs != null) { additionalFeedback = '\nFailure feedback can be found at ' '${path.join(basedir.path, 'failures')}'; - final Map diffs = result.diffs.cast(); + final Map diffs = result.diffs!.cast(); for (final MapEntry entry in diffs.entries) { final File output = getFailureFile( key.isEmpty ? entry.key : entry.key + '_' + key, @@ -143,9 +144,9 @@ class LocalComparisonOutput { basedir, ); output.parent.createSync(recursive: true); - final ByteData pngBytes = + final ByteData? pngBytes = await entry.value.toByteData(format: ImageByteFormat.png); - output.writeAsBytesSync(pngBytes.buffer.asUint8List()); + output.writeAsBytesSync(pngBytes!.buffer.asUint8List()); } } throw test_package.TestFailure( @@ -169,7 +170,7 @@ class LocalComparisonOutput { /// Returns a [ComparisonResult] to describe the pixel differential of the /// [test] and [master] image bytes provided. -Future compareLists(List test, List master) async { +Future compareLists(List? test, List? master) async { if (identical(test, master)) return ComparisonResult(passed: true); @@ -183,15 +184,12 @@ Future compareLists(List test, List master) async { final Codec testImageCodec = await instantiateImageCodec(Uint8List.fromList(test)); final Image testImage = (await testImageCodec.getNextFrame()).image; - final ByteData testImageRgba = await testImage.toByteData(); + final ByteData? testImageRgba = await testImage.toByteData(); final Codec masterImageCodec = await instantiateImageCodec(Uint8List.fromList(master)); final Image masterImage = (await masterImageCodec.getNextFrame()).image; - final ByteData masterImageRgba = await masterImage.toByteData(); - - assert(testImage != null); - assert(masterImage != null); + final ByteData? masterImageRgba = await masterImage.toByteData(); final int width = testImage.width; final int height = testImage.height; @@ -207,10 +205,10 @@ Future compareLists(List test, List master) async { int pixelDiffCount = 0; final int totalPixels = width * height; - final ByteData invertedMasterRgba = _invert(masterImageRgba); - final ByteData invertedTestRgba = _invert(testImageRgba); + final ByteData invertedMasterRgba = _invert(masterImageRgba!); + final ByteData invertedTestRgba = _invert(testImageRgba!); - final Uint8List testImageBytes = (await testImage.toByteData()).buffer.asUint8List(); + final Uint8List testImageBytes = (await testImage.toByteData())!.buffer.asUint8List(); final ByteData maskedDiffRgba = ByteData(testImageBytes.length); maskedDiffRgba.buffer.asUint8List().setRange(0, testImageBytes.length, testImageBytes); final ByteData isolatedDiffRgba = ByteData(width * height * 4); diff --git a/packages/flutter_test/lib/src/_goldens_web.dart b/packages/flutter_test/lib/src/_goldens_web.dart index 75c0931331..68dc03e6ab 100644 --- a/packages/flutter_test/lib/src/_goldens_web.dart +++ b/packages/flutter_test/lib/src/_goldens_web.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// @dart = 2.10 import 'dart:convert'; import 'dart:html' as html; import 'dart:typed_data'; diff --git a/packages/flutter_test/lib/src/goldens.dart b/packages/flutter_test/lib/src/goldens.dart index 26af731cbe..3f83f14f45 100644 --- a/packages/flutter_test/lib/src/goldens.dart +++ b/packages/flutter_test/lib/src/goldens.dart @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// @dart = 2.10 import 'dart:async'; import 'dart:typed_data'; -import 'package:meta/meta.dart'; import 'package:path/path.dart' as path; import '_goldens_io.dart' if (dart.library.html) '_goldens_web.dart' as _goldens; @@ -82,7 +82,7 @@ abstract class GoldenFileComparator { /// /// Version numbers are used in golden file tests for package:flutter. You can /// learn more about these tests [here](https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter). - Uri getTestUri(Uri key, int version) { + Uri getTestUri(Uri key, int? version) { if (version == null) return key; final String keyString = key.toString(); @@ -130,7 +130,6 @@ abstract class GoldenFileComparator { GoldenFileComparator get goldenFileComparator => _goldenFileComparator; GoldenFileComparator _goldenFileComparator = const TrivialComparator._(); set goldenFileComparator(GoldenFileComparator value) { - assert(value != null); _goldenFileComparator = value; } @@ -194,7 +193,7 @@ abstract class WebGoldenComparator { /// /// Version numbers are used in golden file tests for package:flutter. You can /// learn more about these tests [here](https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter). - Uri getTestUri(Uri key, int version) { + Uri getTestUri(Uri key, int? version) { if (version == null) return key; final String keyString = key.toString(); @@ -239,7 +238,6 @@ abstract class WebGoldenComparator { WebGoldenComparator get webGoldenComparator => _webGoldenComparator; WebGoldenComparator _webGoldenComparator = const _TrivialWebGoldenComparator._(); set webGoldenComparator(WebGoldenComparator value) { - assert(value != null); _webGoldenComparator = value; } @@ -289,7 +287,7 @@ class TrivialComparator implements GoldenFileComparator { } @override - Uri getTestUri(Uri key, int version) { + Uri getTestUri(Uri key, int? version) { return key; } } @@ -309,7 +307,7 @@ class _TrivialWebGoldenComparator implements WebGoldenComparator { } @override - Uri getTestUri(Uri key, int version) { + Uri getTestUri(Uri key, int? version) { return key; } } @@ -322,10 +320,10 @@ class _TrivialWebGoldenComparator implements WebGoldenComparator { class ComparisonResult { /// Creates a new [ComparisonResult] for the current test. ComparisonResult({ - @required this.passed, + required this.passed, this.error, this.diffs, - }) : assert(passed != null); + }); /// Indicates whether or not a pixel comparison test has failed. /// @@ -333,10 +331,10 @@ class ComparisonResult { final bool passed; /// Error message used to describe the cause of the pixel comparison failure. - final String error; + final String? error; /// Map containing differential images to illustrate found variants in pixel /// values in the execution of the pixel test. // TODO(jonahwilliams): fix type signature when image is updated to support web. - final Map diffs; + final Map? diffs; }