Skip to content

Commit 1cf6dd8

Browse files
committed
Added golden image test.
1 parent 4063f54 commit 1cf6dd8

File tree

3 files changed

+73
-1
lines changed

3 files changed

+73
-1
lines changed

testing/dart/canvas_test.dart

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
import 'dart:typed_data';
66
import 'dart:ui';
7+
import 'dart:io';
8+
import 'package:image/image.dart' as dart_image;
79

10+
import 'package:path/path.dart' as path;
811
import 'package:test/test.dart';
912

1013
typedef CanvasCallback = void Function(Canvas canvas);
@@ -15,7 +18,7 @@ void testCanvas(CanvasCallback callback) {
1518
} catch (error) { } // ignore: empty_catches
1619
}
1720

18-
void main() {
21+
void testNoCrashes() {
1922
test('canvas APIs should not crash', () async {
2023
final Paint paint = Paint();
2124
const Rect rect = Rect.fromLTRB(double.nan, double.nan, double.nan, double.nan);
@@ -81,3 +84,71 @@ void main() {
8184
testCanvas((Canvas canvas) => canvas.translate(double.nan, double.nan));
8285
});
8386
}
87+
88+
/// @returns true When the images are resonably similar.
89+
/// @todo Make the search actually fuzzy to a certain degree.
90+
Future<bool> fuzzyCompareImages(Image golden, Image img) async {
91+
if (golden.width != img.width || golden.height != img.height) {
92+
return false;
93+
}
94+
int getPixel(ByteData data, int x, int y) => data.getUint32((x + y * golden.width) * 4);
95+
final ByteData goldenData = await golden.toByteData();
96+
final ByteData imgData = await img.toByteData();
97+
for (int y = 0; y < golden.height; y++) {
98+
for (int x = 0; x < golden.width; x++) {
99+
if (getPixel(goldenData, x, y) != getPixel(imgData, x, y)) {
100+
return false;
101+
}
102+
}
103+
}
104+
return true;
105+
}
106+
107+
/// @returns true When the images are resonably similar.
108+
Future<bool> fuzzyGoldenImageCompare(
109+
Image image, String goldenImageName) async {
110+
final String imagesPath = path.join('flutter', 'testing', 'resources');
111+
final File file = File(path.join(imagesPath, goldenImageName));
112+
final Uint8List goldenData = await file.readAsBytes();
113+
114+
final Codec codec = await instantiateImageCodec(goldenData);
115+
final FrameInfo frame = await codec.getNextFrame();
116+
expect(frame.image.height, equals(image.width));
117+
expect(frame.image.width, equals(image.height));
118+
119+
final bool areEqual = await fuzzyCompareImages(frame.image, image);
120+
if (!areEqual) {
121+
final ByteData pngData = await image.toByteData();
122+
final ByteBuffer buffer = pngData.buffer;
123+
final dart_image.Image png = dart_image.Image.fromBytes(
124+
image.width, image.height, buffer.asUint8List());
125+
final String outPath = path.join(imagesPath, 'found_' + goldenImageName);
126+
File(outPath)..writeAsBytesSync(dart_image.encodePng(png));
127+
print('wrote: ' + outPath);
128+
}
129+
return areEqual;
130+
}
131+
132+
void main() {
133+
testNoCrashes();
134+
135+
test('Simple .toImage', () async {
136+
final PictureRecorder recorder = PictureRecorder();
137+
final Canvas canvas = Canvas(recorder);
138+
final Path circlePath = Path()
139+
..addOval(
140+
Rect.fromCircle(center: const Offset(40.0, 40.0), radius: 20.0));
141+
final Paint paint = Paint()
142+
..isAntiAlias = false
143+
..style = PaintingStyle.fill;
144+
canvas.drawPath(circlePath, paint);
145+
final Picture picture = recorder.endRecording();
146+
final Image image = await picture.toImage(100, 100);
147+
expect(image.width, equals(100));
148+
expect(image.height, equals(100));
149+
150+
final bool areEqual =
151+
await fuzzyGoldenImageCompare(image, 'canvas_test_toImage.png');
152+
expect(areEqual, true);
153+
});
154+
}

testing/dart/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ name: engine_tests
22
dependencies:
33
test: 1.3.0
44
path: 1.6.2
5+
image: ^2.1.4
56

67
dependency_overrides:
78
sky_engine:
488 Bytes
Loading

0 commit comments

Comments
 (0)