From 0ae618e8c24e1cbe35bec587e4d9c2a60fd68ed8 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 14 Feb 2024 10:30:10 -0800 Subject: [PATCH 1/6] Added tool to easily check golden diffs locally. --- testing/compare_goldens.dart | 100 +++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 testing/compare_goldens.dart diff --git a/testing/compare_goldens.dart b/testing/compare_goldens.dart new file mode 100644 index 0000000000000..80d997af53bea --- /dev/null +++ b/testing/compare_goldens.dart @@ -0,0 +1,100 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ############################################################################# +// This is a script that will let you check golden image diffs locally. +// +// Usage: compare_goldens.dart +// +// The directories are scanned for png files that match in name, then the diff +// is written to `diff_` in the CWD. This allows you to get +// results quicker than having to upload to skia gold. By default it uses fuzzy +// RMSE to compare. +// +// Here's the steps for using this with something like impeller golden tests: +// 1) Checkout a base revision +// 2) Build impeller_golden_tests +// 3) Execute `impeller_golden_tests --working_dir= +// 4) Checkout test revision +// 5) Build impeller_golden_tests +// 6) Execute `impeller_golden_tests --working_dir= +// 7) Execute `compare_goldens.dart +// +// Requirements: ImageMagick is installed on $PATH +// ############################################################################# + +import 'dart:io'; + +bool hasCommandOnPath(String name) { + final ProcessResult result = Process.runSync('which', [name]); + return result.exitCode == 0; +} + +List findPairs(Set as, Set bs) { + final List result = []; + for (final String a in as) { + if (bs.contains(a)) { + result.add(a); + } else { + print('Mix match file $a.'); + exitCode = 1; + } + } + for (final String b in bs) { + if (!as.contains(b)) { + print('Mix match file $b.'); + exitCode = 1; + } + } + return result; +} + +String basename(String path) { + return path.split(Platform.pathSeparator).last; +} + +Set grabPngFilenames(Directory dir) { + return dir.listSync() + .map((e) => basename(e.path)) + .where((e) => e.endsWith('.png')) + .toSet(); +} + +void main(List args) { + if (!hasCommandOnPath('compare')) { + throw Exception(r'Could not find `compare` from ImageMagick on $PATH.'); + } + if (args.length != 2) { + throw Exception('Usage: compare_goldens.dart '); + } + + final Directory dirA = Directory(args[0]); + if (!dirA.existsSync()) { + throw Exception('Unable to find $dirA'); + } + final Directory dirB = Directory(args[1]); + if (!dirB.existsSync()) { + throw Exception('Unable to find $dirB'); + } + + final Set filesA = grabPngFilenames(dirA); + final Set filesB = grabPngFilenames(dirB); + final List pairs = findPairs(filesA, filesB); + + int count = 0; + for (final String name in pairs) { + count += 1; + final String pathA = [dirA.path, name].join(Platform.pathSeparator); + final String pathB = [dirB.path, name].join(Platform.pathSeparator); + final String output = 'diff_$name'; + print('compare ($count / ${pairs.length}) $name'); + final ProcessResult result = Process.runSync('compare', ['-metric', 'RMSE', '-fuzz', '5%', pathA, pathB, output]); + if (result.exitCode != 0) { + print('DIFF FOUND: saved to $output'); + exitCode = 1; + } else { + File(output).deleteSync(); + } + } +} From bab1944c05e67079c10d1728ff4f0eb218f80d5c Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 14 Feb 2024 15:05:00 -0800 Subject: [PATCH 2/6] moved to tools --- tools/compare_goldens/README.md | 28 +++++++++++++ .../compare_goldens/bin/compare_goldens.dart | 9 ++++ .../compare_goldens/lib}/compare_goldens.dart | 42 +++++-------------- tools/compare_goldens/pubspec.yaml | 3 ++ .../test/compare_goldens_test.dart | 5 +++ 5 files changed, 55 insertions(+), 32 deletions(-) create mode 100644 tools/compare_goldens/README.md create mode 100644 tools/compare_goldens/bin/compare_goldens.dart rename {testing => tools/compare_goldens/lib}/compare_goldens.dart (55%) create mode 100644 tools/compare_goldens/pubspec.yaml create mode 100644 tools/compare_goldens/test/compare_goldens_test.dart diff --git a/tools/compare_goldens/README.md b/tools/compare_goldens/README.md new file mode 100644 index 0000000000000..d7a9e0db3acb0 --- /dev/null +++ b/tools/compare_goldens/README.md @@ -0,0 +1,28 @@ +# Compare Goldens + +This is a script that will let you check golden image diffs locally. + +The directories are scanned for png files that match in name, then the diff +is written to `diff_` in the CWD. This allows you to get +results quicker than having to upload to skia gold. By default it uses fuzzy +RMSE to compare. + +## Usage + +```sh +dart run compare_goldens +``` + +Here's the steps for using this with something like impeller golden tests: + +1) Checkout a base revision +2) Build impeller_golden_tests +3) Execute `impeller_golden_tests --working_dir=\ +4) Checkout test revision +5) Build impeller_golden_tests +6) Execute `impeller_golden_tests --working_dir=\ +7) Execute `compare_goldens \ \ + +## Requirements + +- ImageMagick is installed on $PATH diff --git a/tools/compare_goldens/bin/compare_goldens.dart b/tools/compare_goldens/bin/compare_goldens.dart new file mode 100644 index 0000000000000..20abc4ee167cf --- /dev/null +++ b/tools/compare_goldens/bin/compare_goldens.dart @@ -0,0 +1,9 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:compare_goldens/compare_goldens.dart' as compare_goldens; + +void main(List args) { + compare_goldens.run(args); +} diff --git a/testing/compare_goldens.dart b/tools/compare_goldens/lib/compare_goldens.dart similarity index 55% rename from testing/compare_goldens.dart rename to tools/compare_goldens/lib/compare_goldens.dart index 80d997af53bea..1aa6de1100643 100644 --- a/testing/compare_goldens.dart +++ b/tools/compare_goldens/lib/compare_goldens.dart @@ -2,36 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// ############################################################################# -// This is a script that will let you check golden image diffs locally. -// -// Usage: compare_goldens.dart -// -// The directories are scanned for png files that match in name, then the diff -// is written to `diff_` in the CWD. This allows you to get -// results quicker than having to upload to skia gold. By default it uses fuzzy -// RMSE to compare. -// -// Here's the steps for using this with something like impeller golden tests: -// 1) Checkout a base revision -// 2) Build impeller_golden_tests -// 3) Execute `impeller_golden_tests --working_dir= -// 4) Checkout test revision -// 5) Build impeller_golden_tests -// 6) Execute `impeller_golden_tests --working_dir= -// 7) Execute `compare_goldens.dart -// -// Requirements: ImageMagick is installed on $PATH -// ############################################################################# - import 'dart:io'; -bool hasCommandOnPath(String name) { +bool _hasCommandOnPath(String name) { final ProcessResult result = Process.runSync('which', [name]); return result.exitCode == 0; } -List findPairs(Set as, Set bs) { +List _findPairs(Set as, Set bs) { final List result = []; for (final String a in as) { if (bs.contains(a)) { @@ -50,19 +28,19 @@ List findPairs(Set as, Set bs) { return result; } -String basename(String path) { +String _basename(String path) { return path.split(Platform.pathSeparator).last; } -Set grabPngFilenames(Directory dir) { +Set _grabPngFilenames(Directory dir) { return dir.listSync() - .map((e) => basename(e.path)) + .map((e) => _basename(e.path)) .where((e) => e.endsWith('.png')) .toSet(); } -void main(List args) { - if (!hasCommandOnPath('compare')) { +void run(List args) { + if (!_hasCommandOnPath('compare')) { throw Exception(r'Could not find `compare` from ImageMagick on $PATH.'); } if (args.length != 2) { @@ -78,9 +56,9 @@ void main(List args) { throw Exception('Unable to find $dirB'); } - final Set filesA = grabPngFilenames(dirA); - final Set filesB = grabPngFilenames(dirB); - final List pairs = findPairs(filesA, filesB); + final Set filesA = _grabPngFilenames(dirA); + final Set filesB = _grabPngFilenames(dirB); + final List pairs = _findPairs(filesA, filesB); int count = 0; for (final String name in pairs) { diff --git a/tools/compare_goldens/pubspec.yaml b/tools/compare_goldens/pubspec.yaml new file mode 100644 index 0000000000000..95f0bc5ed0583 --- /dev/null +++ b/tools/compare_goldens/pubspec.yaml @@ -0,0 +1,3 @@ +name: compare_goldens +environment: + sdk: '^3.0.0' diff --git a/tools/compare_goldens/test/compare_goldens_test.dart b/tools/compare_goldens/test/compare_goldens_test.dart new file mode 100644 index 0000000000000..f9b0dd79fed95 --- /dev/null +++ b/tools/compare_goldens/test/compare_goldens_test.dart @@ -0,0 +1,5 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +void main() {} From 5c8788cdff53bb12ccd88f3ce4e2acfe0dbe1ad3 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 14 Feb 2024 15:37:24 -0800 Subject: [PATCH 3/6] added testing setup --- tools/compare_goldens/README.md | 9 +++++++++ tools/compare_goldens/bin/compare_goldens.dart | 3 ++- tools/compare_goldens/lib/compare_goldens.dart | 12 ++++++++---- tools/compare_goldens/pubspec.yaml | 18 +++++++++++++++++- .../test/compare_goldens_test.dart | 3 +++ 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/tools/compare_goldens/README.md b/tools/compare_goldens/README.md index d7a9e0db3acb0..4c9b1fdf04302 100644 --- a/tools/compare_goldens/README.md +++ b/tools/compare_goldens/README.md @@ -26,3 +26,12 @@ Here's the steps for using this with something like impeller golden tests: ## Requirements - ImageMagick is installed on $PATH + +## Testing + +To run the tests: + +```sh +dart pub get +find . -name "*_test.dart" | xargs -n 1 dart --enable-asserts +``` diff --git a/tools/compare_goldens/bin/compare_goldens.dart b/tools/compare_goldens/bin/compare_goldens.dart index 20abc4ee167cf..f5f2d5a1709d5 100644 --- a/tools/compare_goldens/bin/compare_goldens.dart +++ b/tools/compare_goldens/bin/compare_goldens.dart @@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:io' show exitCode; import 'package:compare_goldens/compare_goldens.dart' as compare_goldens; void main(List args) { - compare_goldens.run(args); + exitCode = compare_goldens.run(args); } diff --git a/tools/compare_goldens/lib/compare_goldens.dart b/tools/compare_goldens/lib/compare_goldens.dart index 1aa6de1100643..4b2b0b4b401b5 100644 --- a/tools/compare_goldens/lib/compare_goldens.dart +++ b/tools/compare_goldens/lib/compare_goldens.dart @@ -16,13 +16,11 @@ List _findPairs(Set as, Set bs) { result.add(a); } else { print('Mix match file $a.'); - exitCode = 1; } } for (final String b in bs) { if (!as.contains(b)) { print('Mix match file $b.'); - exitCode = 1; } } return result; @@ -39,7 +37,8 @@ Set _grabPngFilenames(Directory dir) { .toSet(); } -void run(List args) { +int run(List args) { + int returnCode = 0; if (!_hasCommandOnPath('compare')) { throw Exception(r'Could not find `compare` from ImageMagick on $PATH.'); } @@ -60,6 +59,10 @@ void run(List args) { final Set filesB = _grabPngFilenames(dirB); final List pairs = _findPairs(filesA, filesB); + if (filesA.length != pairs.length || filesB.length != pairs.length) { + returnCode = 1; + } + int count = 0; for (final String name in pairs) { count += 1; @@ -70,9 +73,10 @@ void run(List args) { final ProcessResult result = Process.runSync('compare', ['-metric', 'RMSE', '-fuzz', '5%', pathA, pathB, output]); if (result.exitCode != 0) { print('DIFF FOUND: saved to $output'); - exitCode = 1; + returnCode = 1; } else { File(output).deleteSync(); } } + return returnCode; } diff --git a/tools/compare_goldens/pubspec.yaml b/tools/compare_goldens/pubspec.yaml index 95f0bc5ed0583..cfc2af420cd19 100644 --- a/tools/compare_goldens/pubspec.yaml +++ b/tools/compare_goldens/pubspec.yaml @@ -1,3 +1,19 @@ name: compare_goldens environment: - sdk: '^3.0.0' + sdk: '>=3.2.0-0 <4.0.0' + +dev_dependencies: + async_helper: any + expect: any + litetest: any + smith: any + +dependency_overrides: + async_helper: + path: ../../../third_party/dart/pkg/async_helper + expect: + path: ../../../third_party/dart/pkg/expect + litetest: + path: ../../testing/litetest + smith: + path: ../../../third_party/dart/pkg/smith diff --git a/tools/compare_goldens/test/compare_goldens_test.dart b/tools/compare_goldens/test/compare_goldens_test.dart index f9b0dd79fed95..2e88ef69c5335 100644 --- a/tools/compare_goldens/test/compare_goldens_test.dart +++ b/tools/compare_goldens/test/compare_goldens_test.dart @@ -2,4 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// import 'package:compare_goldens/compare_goldens.dart' as compare_goldens; +// import 'package:litetest/litetest.dart'; + void main() {} From 6e83066cca828fc740f7b96280f603d8f5f333fd Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 14 Feb 2024 15:40:26 -0800 Subject: [PATCH 4/6] ++ --- tools/pub_get_offline.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/pub_get_offline.py b/tools/pub_get_offline.py index ee42941cc5bf2..e436dcad216f8 100644 --- a/tools/pub_get_offline.py +++ b/tools/pub_get_offline.py @@ -34,6 +34,7 @@ os.path.join(ENGINE_DIR, 'tools', 'api_check'), os.path.join(ENGINE_DIR, 'tools', 'build_bucket_golden_scraper'), os.path.join(ENGINE_DIR, 'tools', 'clang_tidy'), + os.path.join(ENGINE_DIR, 'tools', 'compare_goldens'), os.path.join(ENGINE_DIR, 'tools', 'const_finder'), os.path.join(ENGINE_DIR, 'tools', 'engine_tool'), os.path.join(ENGINE_DIR, 'tools', 'gen_web_locale_keymap'), From 7a3686eb06c78172073067b673f02b6056542564 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Thu, 15 Feb 2024 08:20:31 -0800 Subject: [PATCH 5/6] linter --- tools/compare_goldens/lib/compare_goldens.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/compare_goldens/lib/compare_goldens.dart b/tools/compare_goldens/lib/compare_goldens.dart index 4b2b0b4b401b5..8a865e5b7eca2 100644 --- a/tools/compare_goldens/lib/compare_goldens.dart +++ b/tools/compare_goldens/lib/compare_goldens.dart @@ -32,11 +32,13 @@ String _basename(String path) { Set _grabPngFilenames(Directory dir) { return dir.listSync() - .map((e) => _basename(e.path)) - .where((e) => e.endsWith('.png')) + .map((FileSystemEntity e) => _basename(e.path)) + .where((String e) => e.endsWith('.png')) .toSet(); } +/// The main entry point to the tool, execute it like `main`. Returns the +/// `exitCode`. int run(List args) { int returnCode = 0; if (!_hasCommandOnPath('compare')) { @@ -70,7 +72,8 @@ int run(List args) { final String pathB = [dirB.path, name].join(Platform.pathSeparator); final String output = 'diff_$name'; print('compare ($count / ${pairs.length}) $name'); - final ProcessResult result = Process.runSync('compare', ['-metric', 'RMSE', '-fuzz', '5%', pathA, pathB, output]); + final ProcessResult result = Process.runSync('compare', + ['-metric', 'RMSE', '-fuzz', '5%', pathA, pathB, output]); if (result.exitCode != 0) { print('DIFF FOUND: saved to $output'); returnCode = 1; From a70292f90331efc20e58ae67638ba9b4cde2c543 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Thu, 15 Feb 2024 08:52:40 -0800 Subject: [PATCH 6/6] removed testing dependencies --- tools/compare_goldens/pubspec.yaml | 16 ---------------- .../test/compare_goldens_test.dart | 3 --- 2 files changed, 19 deletions(-) diff --git a/tools/compare_goldens/pubspec.yaml b/tools/compare_goldens/pubspec.yaml index cfc2af420cd19..c93e9a825fee6 100644 --- a/tools/compare_goldens/pubspec.yaml +++ b/tools/compare_goldens/pubspec.yaml @@ -1,19 +1,3 @@ name: compare_goldens environment: sdk: '>=3.2.0-0 <4.0.0' - -dev_dependencies: - async_helper: any - expect: any - litetest: any - smith: any - -dependency_overrides: - async_helper: - path: ../../../third_party/dart/pkg/async_helper - expect: - path: ../../../third_party/dart/pkg/expect - litetest: - path: ../../testing/litetest - smith: - path: ../../../third_party/dart/pkg/smith diff --git a/tools/compare_goldens/test/compare_goldens_test.dart b/tools/compare_goldens/test/compare_goldens_test.dart index 2e88ef69c5335..f9b0dd79fed95 100644 --- a/tools/compare_goldens/test/compare_goldens_test.dart +++ b/tools/compare_goldens/test/compare_goldens_test.dart @@ -2,7 +2,4 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// import 'package:compare_goldens/compare_goldens.dart' as compare_goldens; -// import 'package:litetest/litetest.dart'; - void main() {}