Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit b7103bc

Browse files
authored
Added tool to easily check golden diffs locally. (#50654)
This addresses the problem where people feel like they have to upload a PR to get diffs from Skia Gold. This should work for most workflows. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent e5a4847 commit b7103bc

File tree

6 files changed

+141
-0
lines changed

6 files changed

+141
-0
lines changed

tools/compare_goldens/README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Compare Goldens
2+
3+
This is a script that will let you check golden image diffs locally.
4+
5+
The directories are scanned for png files that match in name, then the diff
6+
is written to `diff_<name of file>` in the CWD. This allows you to get
7+
results quicker than having to upload to skia gold. By default it uses fuzzy
8+
RMSE to compare.
9+
10+
## Usage
11+
12+
```sh
13+
dart run compare_goldens <dir path> <dir path>
14+
```
15+
16+
Here's the steps for using this with something like impeller golden tests:
17+
18+
1) Checkout a base revision
19+
2) Build impeller_golden_tests
20+
3) Execute `impeller_golden_tests --working_dir=\<path a\>
21+
4) Checkout test revision
22+
5) Build impeller_golden_tests
23+
6) Execute `impeller_golden_tests --working_dir=\<path b\>
24+
7) Execute `compare_goldens \<path a\> \<path b\>
25+
26+
## Requirements
27+
28+
- ImageMagick is installed on $PATH
29+
30+
## Testing
31+
32+
To run the tests:
33+
34+
```sh
35+
dart pub get
36+
find . -name "*_test.dart" | xargs -n 1 dart --enable-asserts
37+
```
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:io' show exitCode;
6+
import 'package:compare_goldens/compare_goldens.dart' as compare_goldens;
7+
8+
void main(List<String> args) {
9+
exitCode = compare_goldens.run(args);
10+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:io';
6+
7+
bool _hasCommandOnPath(String name) {
8+
final ProcessResult result = Process.runSync('which', <String>[name]);
9+
return result.exitCode == 0;
10+
}
11+
12+
List<String> _findPairs(Set<String> as, Set<String> bs) {
13+
final List<String> result = <String>[];
14+
for (final String a in as) {
15+
if (bs.contains(a)) {
16+
result.add(a);
17+
} else {
18+
print('Mix match file $a.');
19+
}
20+
}
21+
for (final String b in bs) {
22+
if (!as.contains(b)) {
23+
print('Mix match file $b.');
24+
}
25+
}
26+
return result;
27+
}
28+
29+
String _basename(String path) {
30+
return path.split(Platform.pathSeparator).last;
31+
}
32+
33+
Set<String> _grabPngFilenames(Directory dir) {
34+
return dir.listSync()
35+
.map((FileSystemEntity e) => _basename(e.path))
36+
.where((String e) => e.endsWith('.png'))
37+
.toSet();
38+
}
39+
40+
/// The main entry point to the tool, execute it like `main`. Returns the
41+
/// `exitCode`.
42+
int run(List<String> args) {
43+
int returnCode = 0;
44+
if (!_hasCommandOnPath('compare')) {
45+
throw Exception(r'Could not find `compare` from ImageMagick on $PATH.');
46+
}
47+
if (args.length != 2) {
48+
throw Exception('Usage: compare_goldens.dart <dir path> <dir path>');
49+
}
50+
51+
final Directory dirA = Directory(args[0]);
52+
if (!dirA.existsSync()) {
53+
throw Exception('Unable to find $dirA');
54+
}
55+
final Directory dirB = Directory(args[1]);
56+
if (!dirB.existsSync()) {
57+
throw Exception('Unable to find $dirB');
58+
}
59+
60+
final Set<String> filesA = _grabPngFilenames(dirA);
61+
final Set<String> filesB = _grabPngFilenames(dirB);
62+
final List<String> pairs = _findPairs(filesA, filesB);
63+
64+
if (filesA.length != pairs.length || filesB.length != pairs.length) {
65+
returnCode = 1;
66+
}
67+
68+
int count = 0;
69+
for (final String name in pairs) {
70+
count += 1;
71+
final String pathA = <String>[dirA.path, name].join(Platform.pathSeparator);
72+
final String pathB = <String>[dirB.path, name].join(Platform.pathSeparator);
73+
final String output = 'diff_$name';
74+
print('compare ($count / ${pairs.length}) $name');
75+
final ProcessResult result = Process.runSync('compare',
76+
<String>['-metric', 'RMSE', '-fuzz', '5%', pathA, pathB, output]);
77+
if (result.exitCode != 0) {
78+
print('DIFF FOUND: saved to $output');
79+
returnCode = 1;
80+
} else {
81+
File(output).deleteSync();
82+
}
83+
}
84+
return returnCode;
85+
}

tools/compare_goldens/pubspec.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
name: compare_goldens
2+
environment:
3+
sdk: '>=3.2.0-0 <4.0.0'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
void main() {}

tools/pub_get_offline.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
os.path.join(ENGINE_DIR, 'tools', 'api_check'),
3535
os.path.join(ENGINE_DIR, 'tools', 'build_bucket_golden_scraper'),
3636
os.path.join(ENGINE_DIR, 'tools', 'clang_tidy'),
37+
os.path.join(ENGINE_DIR, 'tools', 'compare_goldens'),
3738
os.path.join(ENGINE_DIR, 'tools', 'const_finder'),
3839
os.path.join(ENGINE_DIR, 'tools', 'engine_tool'),
3940
os.path.join(ENGINE_DIR, 'tools', 'gen_web_locale_keymap'),

0 commit comments

Comments
 (0)