blob: e64198f0bc4861856a272157ecc31295fa00b3fa [file] [log] [blame]
Ian Hickson449f4a62019-11-27 15:04:02 -08001// Copyright 2014 The Flutter Authors. All rights reserved.
Todd Volkert65079ad2018-05-03 07:39:41 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ian Hicksonf25b8332021-10-07 16:48:04 -07005// See also dev/automated_tests/flutter_test/flutter_gold_test.dart
6
Dan Field1747adb2021-01-27 13:09:46 -08007import 'dart:convert';
Sam Rawlins288b9412021-04-01 19:59:03 -07008import 'dart:io' hide Directory;
Todd Volkert65079ad2018-05-03 07:39:41 -07009
10import 'package:file/file.dart';
11import 'package:file/memory.dart';
Ian Hicksonf25b8332021-10-07 16:48:04 -070012import 'package:flutter/foundation.dart';
Todd Volkert65079ad2018-05-03 07:39:41 -070013import 'package:flutter_goldens/flutter_goldens.dart';
14import 'package:flutter_test/flutter_test.dart';
Todd Volkert65079ad2018-05-03 07:39:41 -070015import 'package:platform/platform.dart';
16import 'package:process/process.dart';
17
Kate Lovett7bc02032019-10-25 15:05:21 -070018import 'json_templates.dart';
19
Todd Volkert65079ad2018-05-03 07:39:41 -070020const String _kFlutterRoot = '/flutter';
Kate Lovett7bc02032019-10-25 15:05:21 -070021
22// 1x1 transparent pixel
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +020023const List<int> _kTestPngBytes = <int>[
24 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 0,
Kate Lovett7bc02032019-10-25 15:05:21 -070025 1, 0, 0, 0, 1, 8, 6, 0, 0, 0, 31, 21, 196, 137, 0, 0, 0, 11, 73, 68, 65, 84,
26 120, 1, 99, 97, 0, 2, 0, 0, 25, 0, 5, 144, 240, 54, 245, 0, 0, 0, 0, 73, 69,
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +020027 78, 68, 174, 66, 96, 130,
28];
Kate Lovett7bc02032019-10-25 15:05:21 -070029
Todd Volkert65079ad2018-05-03 07:39:41 -070030void main() {
Kate Lovettf04616f2021-01-27 19:29:04 -060031 late MemoryFileSystem fs;
32 late FakePlatform platform;
33 late FakeProcessManager process;
34 late FakeHttpClient fakeHttpClient;
Todd Volkert65079ad2018-05-03 07:39:41 -070035
Kate Lovett829bdeb2019-05-10 15:53:41 -070036 setUp(() {
Alexandre Ardhuind927c932018-09-12 08:29:29 +020037 fs = MemoryFileSystem();
Kate Lovett7bc02032019-10-25 15:05:21 -070038 platform = FakePlatform(
39 environment: <String, String>{'FLUTTER_ROOT': _kFlutterRoot},
40 operatingSystem: 'macos'
41 );
Dan Field1747adb2021-01-27 13:09:46 -080042 process = FakeProcessManager();
43 fakeHttpClient = FakeHttpClient();
Kate Lovett829bdeb2019-05-10 15:53:41 -070044 fs.directory(_kFlutterRoot).createSync(recursive: true);
Kate Lovett3a3939a2019-10-21 17:31:54 -070045 });
46
47 group('SkiaGoldClient', () {
Kate Lovettf04616f2021-01-27 19:29:04 -060048 late SkiaGoldClient skiaClient;
49 late Directory workDirectory;
Kate Lovett3a3939a2019-10-21 17:31:54 -070050
51 setUp(() {
Kate Lovett89d72a12019-12-16 12:18:03 -080052 workDirectory = fs.directory('/workDirectory')
Kate Lovett7bc02032019-10-25 15:05:21 -070053 ..createSync(recursive: true);
54 skiaClient = SkiaGoldClient(
55 workDirectory,
Kate Lovett3a3939a2019-10-21 17:31:54 -070056 fs: fs,
57 process: process,
58 platform: platform,
Dan Field1747adb2021-01-27 13:09:46 -080059 httpClient: fakeHttpClient,
Kate Lovett616794f2019-07-28 12:26:06 -070060 );
61 });
62
Yegor3fe2cba2022-04-29 11:49:05 -070063 test('web HTML test', () async {
64 platform = FakePlatform(
65 environment: <String, String>{
66 'GOLDCTL': 'goldctl',
67 'FLUTTER_ROOT': _kFlutterRoot,
68 'FLUTTER_TEST_BROWSER': 'Chrome',
69 'FLUTTER_WEB_RENDERER': 'html',
70 },
71 operatingSystem: 'macos'
72 );
73 skiaClient = SkiaGoldClient(
74 workDirectory,
75 fs: fs,
76 process: process,
77 platform: platform,
78 httpClient: fakeHttpClient,
79 );
80
81 final File goldenFile = fs.file('/workDirectory/temp/golden_file_test.png')
82 ..createSync(recursive: true);
83
84 const RunInvocation goldctlInvocation = RunInvocation(
85 <String>[
86 'goldctl',
87 'imgtest', 'add',
88 '--work-dir', '/workDirectory/temp',
89 '--test-name', 'golden_file_test',
90 '--png-file', '/workDirectory/temp/golden_file_test.png',
91 '--passfail',
92 '--add-test-optional-key', 'image_matching_algorithm:fuzzy',
93 '--add-test-optional-key', 'fuzzy_max_different_pixels:20',
94 '--add-test-optional-key', 'fuzzy_pixel_delta_threshold:4',
95 ],
96 null,
97 );
98 process.processResults[goldctlInvocation] = ProcessResult(123, 0, '', '');
99
100 expect(
101 await skiaClient.imgtestAdd('golden_file_test.png', goldenFile),
102 isTrue,
103 );
104 });
105
106 test('web CanvasKit test', () async {
107 platform = FakePlatform(
108 environment: <String, String>{
109 'GOLDCTL': 'goldctl',
110 'FLUTTER_ROOT': _kFlutterRoot,
111 'FLUTTER_TEST_BROWSER': 'Chrome',
112 'FLUTTER_WEB_RENDERER': 'canvaskit',
113 },
114 operatingSystem: 'macos'
115 );
116 skiaClient = SkiaGoldClient(
117 workDirectory,
118 fs: fs,
119 process: process,
120 platform: platform,
121 httpClient: fakeHttpClient,
122 );
123
124 final File goldenFile = fs.file('/workDirectory/temp/golden_file_test.png')
125 ..createSync(recursive: true);
126
127 const RunInvocation goldctlInvocation = RunInvocation(
128 <String>[
129 'goldctl',
130 'imgtest', 'add',
131 '--work-dir', '/workDirectory/temp',
132 '--test-name', 'golden_file_test',
133 '--png-file', '/workDirectory/temp/golden_file_test.png',
134 '--passfail',
135 ],
136 null,
137 );
138 process.processResults[goldctlInvocation] = ProcessResult(123, 0, '', '');
139
140 expect(
141 await skiaClient.imgtestAdd('golden_file_test.png', goldenFile),
142 isTrue,
143 );
144 });
145
Kate Lovett89d72a12019-12-16 12:18:03 -0800146 test('auth performs minimal work if already authorized', () async {
Kate Lovett1c15cd82020-02-05 11:03:02 -0800147 final File authFile = fs.file('/workDirectory/temp/auth_opt.json')
Kate Lovett89d72a12019-12-16 12:18:03 -0800148 ..createSync(recursive: true);
Kate Lovett1c15cd82020-02-05 11:03:02 -0800149 authFile.writeAsStringSync(authTemplate());
Dan Field1747adb2021-01-27 13:09:46 -0800150 process.fallbackProcessResult = ProcessResult(123, 0, '', '');
Kate Lovett89d72a12019-12-16 12:18:03 -0800151 await skiaClient.auth();
Kate Lovett616794f2019-07-28 12:26:06 -0700152
Dan Field1747adb2021-01-27 13:09:46 -0800153 expect(process.workingDirectories, isEmpty);
Kate Lovett89d72a12019-12-16 12:18:03 -0800154 });
155
Kate Lovett1c15cd82020-02-05 11:03:02 -0800156 test('gsutil is checked when authorization file is present', () async {
157 final File authFile = fs.file('/workDirectory/temp/auth_opt.json')
158 ..createSync(recursive: true);
159 authFile.writeAsStringSync(authTemplate(gsutil: true));
160 expect(
161 await skiaClient.clientIsAuthorized(),
162 isFalse,
163 );
164 });
165
Kate Lovett89d72a12019-12-16 12:18:03 -0800166 test('throws for error state from auth', () async {
167 platform = FakePlatform(
168 environment: <String, String>{
169 'FLUTTER_ROOT': _kFlutterRoot,
170 'GOLD_SERVICE_ACCOUNT' : 'Service Account',
171 'GOLDCTL' : 'goldctl',
172 },
173 operatingSystem: 'macos'
174 );
175
176 skiaClient = SkiaGoldClient(
177 workDirectory,
178 fs: fs,
179 process: process,
180 platform: platform,
Dan Field1747adb2021-01-27 13:09:46 -0800181 httpClient: fakeHttpClient,
Kate Lovett89d72a12019-12-16 12:18:03 -0800182 );
183
Kate Lovett895beb02021-12-10 18:54:10 -0800184 process.fallbackProcessResult = ProcessResult(123, 1, 'Fallback failure', 'Fallback failure');
Kate Lovett89d72a12019-12-16 12:18:03 -0800185
186 expect(
Dan Field1747adb2021-01-27 13:09:46 -0800187 skiaClient.auth(),
Kate Lovett89d72a12019-12-16 12:18:03 -0800188 throwsException,
189 );
190 });
191
Kate Lovett1c15cd82020-02-05 11:03:02 -0800192 test('throws for error state from init', () {
Kate Lovett89d72a12019-12-16 12:18:03 -0800193 platform = FakePlatform(
194 environment: <String, String>{
195 'FLUTTER_ROOT': _kFlutterRoot,
196 'GOLDCTL' : 'goldctl',
197 },
198 operatingSystem: 'macos'
199 );
200
201 skiaClient = SkiaGoldClient(
202 workDirectory,
203 fs: fs,
204 process: process,
205 platform: platform,
Dan Field1747adb2021-01-27 13:09:46 -0800206 httpClient: fakeHttpClient,
Kate Lovett89d72a12019-12-16 12:18:03 -0800207 );
208
Dan Field1747adb2021-01-27 13:09:46 -0800209 const RunInvocation gitInvocation = RunInvocation(
Kate Lovett89d72a12019-12-16 12:18:03 -0800210 <String>['git', 'rev-parse', 'HEAD'],
Dan Field1747adb2021-01-27 13:09:46 -0800211 '/flutter',
212 );
213 const RunInvocation goldctlInvocation = RunInvocation(
Kate Lovett89d72a12019-12-16 12:18:03 -0800214 <String>[
215 'goldctl',
216 'imgtest', 'init',
217 '--instance', 'flutter',
218 '--work-dir', '/workDirectory/temp',
219 '--commit', '12345678',
220 '--keys-file', '/workDirectory/keys.json',
221 '--failure-file', '/workDirectory/failures.json',
222 '--passfail',
223 ],
Dan Field1747adb2021-01-27 13:09:46 -0800224 null,
225 );
226 process.processResults[gitInvocation] = ProcessResult(12345678, 0, '12345678', '');
Kate Lovett895beb02021-12-10 18:54:10 -0800227 process.processResults[goldctlInvocation] = ProcessResult(123, 1, 'Expected failure', 'Expected failure');
228 process.fallbackProcessResult = ProcessResult(123, 1, 'Fallback failure', 'Fallback failure');
Kate Lovett89d72a12019-12-16 12:18:03 -0800229
230 expect(
Dan Field1747adb2021-01-27 13:09:46 -0800231 skiaClient.imgtestInit(),
Kate Lovett89d72a12019-12-16 12:18:03 -0800232 throwsException,
233 );
Kate Lovett7bc02032019-10-25 15:05:21 -0700234 });
235
Kate Lovett895beb02021-12-10 18:54:10 -0800236 test('Only calls init once', () async {
237 platform = FakePlatform(
238 environment: <String, String>{
239 'FLUTTER_ROOT': _kFlutterRoot,
240 'GOLDCTL' : 'goldctl',
241 },
242 operatingSystem: 'macos'
243 );
244
245 skiaClient = SkiaGoldClient(
246 workDirectory,
247 fs: fs,
248 process: process,
249 platform: platform,
250 httpClient: fakeHttpClient,
251 );
252
253 const RunInvocation gitInvocation = RunInvocation(
254 <String>['git', 'rev-parse', 'HEAD'],
255 '/flutter',
256 );
257 const RunInvocation goldctlInvocation = RunInvocation(
258 <String>[
259 'goldctl',
260 'imgtest', 'init',
261 '--instance', 'flutter',
262 '--work-dir', '/workDirectory/temp',
263 '--commit', '1234',
264 '--keys-file', '/workDirectory/keys.json',
265 '--failure-file', '/workDirectory/failures.json',
Kate Lovett8e7b3612022-03-22 16:00:20 -0500266 '--passfail',
Kate Lovett895beb02021-12-10 18:54:10 -0800267 ],
268 null,
269 );
270 process.processResults[gitInvocation] = ProcessResult(1234, 0, '1234', '');
271 process.processResults[goldctlInvocation] = ProcessResult(5678, 0, '5678', '');
272 process.fallbackProcessResult = ProcessResult(123, 1, 'Fallback failure', 'Fallback failure');
273
274 // First call
275 await skiaClient.imgtestInit();
276
277 // Remove fake process result.
278 // If the init call is executed again, the fallback process will throw.
279 process.processResults.remove(goldctlInvocation);
280
281 // Second call
282 await skiaClient.imgtestInit();
283 });
284
285 test('Only calls tryjob init once', () async {
286 platform = FakePlatform(
287 environment: <String, String>{
288 'FLUTTER_ROOT': _kFlutterRoot,
289 'GOLDCTL' : 'goldctl',
290 'SWARMING_TASK_ID' : '4ae997b50dfd4d11',
291 'LOGDOG_STREAM_PREFIX' : 'buildbucket/cr-buildbucket.appspot.com/8885996262141582672',
292 'GOLD_TRYJOB' : 'refs/pull/49815/head',
293 },
294 operatingSystem: 'macos'
295 );
296
297 skiaClient = SkiaGoldClient(
298 workDirectory,
299 fs: fs,
300 process: process,
301 platform: platform,
302 httpClient: fakeHttpClient,
303 );
304
305 const RunInvocation gitInvocation = RunInvocation(
306 <String>['git', 'rev-parse', 'HEAD'],
307 '/flutter',
308 );
309 const RunInvocation goldctlInvocation = RunInvocation(
310 <String>[
311 'goldctl',
312 'imgtest', 'init',
313 '--instance', 'flutter',
314 '--work-dir', '/workDirectory/temp',
315 '--commit', '1234',
316 '--keys-file', '/workDirectory/keys.json',
317 '--failure-file', '/workDirectory/failures.json',
318 '--passfail',
319 '--crs', 'github',
320 '--patchset_id', '1234',
321 '--changelist', '49815',
322 '--cis', 'buildbucket',
323 '--jobid', '8885996262141582672',
324 ],
325 null,
326 );
327 process.processResults[gitInvocation] = ProcessResult(1234, 0, '1234', '');
328 process.processResults[goldctlInvocation] = ProcessResult(5678, 0, '5678', '');
329 process.fallbackProcessResult = ProcessResult(123, 1, 'Fallback failure', 'Fallback failure');
330
331 // First call
332 await skiaClient.tryjobInit();
333
334 // Remove fake process result.
335 // If the init call is executed again, the fallback process will throw.
336 process.processResults.remove(goldctlInvocation);
337
338 // Second call
339 await skiaClient.tryjobInit();
340 });
341
Kate Lovett324e6d92022-04-07 17:36:09 -0500342 test('throws for error state from imgtestAdd', () {
343 final File goldenFile = fs.file('/workDirectory/temp/golden_file_test.png')
344 ..createSync(recursive: true);
345 platform = FakePlatform(
346 environment: <String, String>{
347 'FLUTTER_ROOT': _kFlutterRoot,
348 'GOLDCTL' : 'goldctl',
349 },
350 operatingSystem: 'macos'
351 );
352
353 skiaClient = SkiaGoldClient(
354 workDirectory,
355 fs: fs,
356 process: process,
357 platform: platform,
358 httpClient: fakeHttpClient,
359 );
360
361 const RunInvocation goldctlInvocation = RunInvocation(
362 <String>[
363 'goldctl',
364 'imgtest', 'add',
365 '--work-dir', '/workDirectory/temp',
366 '--test-name', 'golden_file_test',
367 '--png-file', '/workDirectory/temp/golden_file_test.png',
368 '--passfail',
369 ],
370 null,
371 );
372 process.processResults[goldctlInvocation] = ProcessResult(123, 1, 'Expected failure', 'Expected failure');
373 process.fallbackProcessResult = ProcessResult(123, 1, 'Fallback failure', 'Fallback failure');
374
375 expect(
376 skiaClient.imgtestAdd('golden_file_test', goldenFile),
377 throwsException,
378 );
379 });
Kate Lovettea520132021-11-15 14:40:32 -0600380
Kate Lovettea67a652020-03-18 12:56:02 -0700381 test('correctly inits tryjob for luci', () async {
382 platform = FakePlatform(
383 environment: <String, String>{
384 'FLUTTER_ROOT': _kFlutterRoot,
385 'GOLDCTL' : 'goldctl',
386 'SWARMING_TASK_ID' : '4ae997b50dfd4d11',
387 'LOGDOG_STREAM_PREFIX' : 'buildbucket/cr-buildbucket.appspot.com/8885996262141582672',
388 'GOLD_TRYJOB' : 'refs/pull/49815/head',
389 },
390 operatingSystem: 'macos'
391 );
392
393 skiaClient = SkiaGoldClient(
394 workDirectory,
395 fs: fs,
396 process: process,
397 platform: platform,
Dan Field1747adb2021-01-27 13:09:46 -0800398 httpClient: fakeHttpClient,
Kate Lovettea67a652020-03-18 12:56:02 -0700399 );
400
401 final List<String> ciArguments = skiaClient.getCIArguments();
402
403 expect(
404 ciArguments,
405 equals(
406 <String>[
407 '--changelist', '49815',
408 '--cis', 'buildbucket',
409 '--jobid', '8885996262141582672',
410 ],
411 ),
412 );
413 });
414
Kate Lovett8587b602021-09-14 14:53:33 -0500415 test('Creates traceID correctly', () async {
Kate Lovettee69eeb2020-09-02 16:35:06 -0700416 String traceID;
Kate Lovettee69eeb2020-09-02 16:35:06 -0700417 platform = FakePlatform(
418 environment: <String, String>{
419 'FLUTTER_ROOT': _kFlutterRoot,
420 'GOLDCTL' : 'goldctl',
421 'SWARMING_TASK_ID' : '4ae997b50dfd4d11',
422 'LOGDOG_STREAM_PREFIX' : 'buildbucket/cr-buildbucket.appspot.com/8885996262141582672',
423 'GOLD_TRYJOB' : 'refs/pull/49815/head',
424 },
425 operatingSystem: 'linux'
426 );
427
428 skiaClient = SkiaGoldClient(
429 workDirectory,
430 fs: fs,
431 process: process,
432 platform: platform,
Dan Field1747adb2021-01-27 13:09:46 -0800433 httpClient: fakeHttpClient,
Kate Lovettee69eeb2020-09-02 16:35:06 -0700434 );
435
Kate Lovett65d8dd92021-09-15 19:42:05 -0500436 traceID = skiaClient.getTraceID('flutter.golden.1');
Kate Lovettee69eeb2020-09-02 16:35:06 -0700437 expect(
438 traceID,
Kate Lovett65d8dd92021-09-15 19:42:05 -0500439 equals('ae18c7a6aa48e0685525dfe8fdf79003'),
Kate Lovettee69eeb2020-09-02 16:35:06 -0700440 );
441
442 // Browser
443 platform = FakePlatform(
444 environment: <String, String>{
445 'FLUTTER_ROOT': _kFlutterRoot,
446 'GOLDCTL' : 'goldctl',
447 'SWARMING_TASK_ID' : '4ae997b50dfd4d11',
448 'LOGDOG_STREAM_PREFIX' : 'buildbucket/cr-buildbucket.appspot.com/8885996262141582672',
449 'GOLD_TRYJOB' : 'refs/pull/49815/head',
450 'FLUTTER_TEST_BROWSER' : 'chrome',
451 },
452 operatingSystem: 'linux'
453 );
454
455 skiaClient = SkiaGoldClient(
456 workDirectory,
457 fs: fs,
458 process: process,
459 platform: platform,
Dan Field1747adb2021-01-27 13:09:46 -0800460 httpClient: fakeHttpClient,
Kate Lovettee69eeb2020-09-02 16:35:06 -0700461 );
Kate Lovett65d8dd92021-09-15 19:42:05 -0500462
463 traceID = skiaClient.getTraceID('flutter.golden.1');
Kate Lovettee69eeb2020-09-02 16:35:06 -0700464 expect(
465 traceID,
Kate Lovett65d8dd92021-09-15 19:42:05 -0500466 equals('e9d5c296c48e7126808520e9cc191243'),
Kate Lovettee69eeb2020-09-02 16:35:06 -0700467 );
468
469 // Locally - should defer to luci traceID
470 platform = FakePlatform(
471 environment: <String, String>{
472 'FLUTTER_ROOT': _kFlutterRoot,
473 },
474 operatingSystem: 'macos'
475 );
476
477 skiaClient = SkiaGoldClient(
478 workDirectory,
479 fs: fs,
480 process: process,
481 platform: platform,
Dan Field1747adb2021-01-27 13:09:46 -0800482 httpClient: fakeHttpClient,
Kate Lovettee69eeb2020-09-02 16:35:06 -0700483 );
Kate Lovett65d8dd92021-09-15 19:42:05 -0500484
485 traceID = skiaClient.getTraceID('flutter.golden.1');
Kate Lovettee69eeb2020-09-02 16:35:06 -0700486 expect(
487 traceID,
Kate Lovett65d8dd92021-09-15 19:42:05 -0500488 equals('9968695b9ae78cdb77cbb2be621ca2d6'),
Kate Lovettee69eeb2020-09-02 16:35:06 -0700489 );
490 });
491
Kate Lovettabbc0be2022-08-03 19:11:23 -0500492 test('throws for error state from imgtestAdd', () {
493 final File goldenFile = fs.file('/workDirectory/temp/golden_file_test.png')
494 ..createSync(recursive: true);
495 platform = FakePlatform(
496 environment: <String, String>{
497 'FLUTTER_ROOT': _kFlutterRoot,
498 'GOLDCTL' : 'goldctl',
499 },
500 operatingSystem: 'macos'
501 );
502
503 skiaClient = SkiaGoldClient(
504 workDirectory,
505 fs: fs,
506 process: process,
507 platform: platform,
508 httpClient: fakeHttpClient,
509 );
510
511 const RunInvocation goldctlInvocation = RunInvocation(
512 <String>[
513 'goldctl',
514 'imgtest', 'add',
515 '--work-dir', '/workDirectory/temp',
516 '--test-name', 'golden_file_test',
517 '--png-file', '/workDirectory/temp/golden_file_test.png',
518 '--passfail',
519 ],
520 null,
521 );
522 process.processResults[goldctlInvocation] = ProcessResult(123, 1, 'Expected failure', 'Expected failure');
523 process.fallbackProcessResult = ProcessResult(123, 1, 'Fallback failure', 'Fallback failure');
524
525 expect(
526 skiaClient.imgtestAdd('golden_file_test', goldenFile),
527 throwsA(
528 isA<SkiaException>().having((SkiaException error) => error.message,
529 'message',
530 contains('result-state.json'),
531 ),
532 ),
533 );
534 });
535
536 test('throws for error state from tryjobAdd', () {
537 final File goldenFile = fs.file('/workDirectory/temp/golden_file_test.png')
538 ..createSync(recursive: true);
539 platform = FakePlatform(
540 environment: <String, String>{
541 'FLUTTER_ROOT': _kFlutterRoot,
542 'GOLDCTL' : 'goldctl',
543 },
544 operatingSystem: 'macos'
545 );
546
547 skiaClient = SkiaGoldClient(
548 workDirectory,
549 fs: fs,
550 process: process,
551 platform: platform,
552 httpClient: fakeHttpClient,
553 );
554
555 const RunInvocation goldctlInvocation = RunInvocation(
556 <String>[
557 'goldctl',
558 'imgtest', 'add',
559 '--work-dir', '/workDirectory/temp',
560 '--test-name', 'golden_file_test',
561 '--png-file', '/workDirectory/temp/golden_file_test.png',
562 '--passfail',
563 ],
564 null,
565 );
566 process.processResults[goldctlInvocation] = ProcessResult(123, 1, 'Expected failure', 'Expected failure');
567 process.fallbackProcessResult = ProcessResult(123, 1, 'Fallback failure', 'Fallback failure');
568
569 expect(
570 skiaClient.tryjobAdd('golden_file_test', goldenFile),
571 throwsA(
572 isA<SkiaException>().having((SkiaException error) => error.message,
573 'message',
574 contains('result-state.json'),
575 ),
576 ),
577 );
578 });
579
Kate Lovett7bc02032019-10-25 15:05:21 -0700580 group('Request Handling', () {
Kate Lovettf04616f2021-01-27 19:29:04 -0600581 const String expectation = '55109a4bed52acc780530f7a9aeff6c0';
Kate Lovett7bc02032019-10-25 15:05:21 -0700582
583 test('image bytes are processed properly', () async {
584 final Uri imageUrl = Uri.parse(
585 'https://flutter-gold.skia.org/img/images/$expectation.png'
586 );
Dan Field1747adb2021-01-27 13:09:46 -0800587 final FakeHttpClientRequest fakeImageRequest = FakeHttpClientRequest();
588 final FakeHttpImageResponse fakeImageResponse = FakeHttpImageResponse(
Kate Lovett7bc02032019-10-25 15:05:21 -0700589 imageResponseTemplate()
590 );
Dan Field1747adb2021-01-27 13:09:46 -0800591
592 fakeHttpClient.request = fakeImageRequest;
593 fakeImageRequest.response = fakeImageResponse;
Kate Lovett7bc02032019-10-25 15:05:21 -0700594
595 final List<int> masterBytes = await skiaClient.getImageBytes(expectation);
596
Dan Field1747adb2021-01-27 13:09:46 -0800597 expect(fakeHttpClient.lastUri, imageUrl);
Kate Lovett7bc02032019-10-25 15:05:21 -0700598 expect(masterBytes, equals(_kTestPngBytes));
599 });
Kate Lovett616794f2019-07-28 12:26:06 -0700600 });
601 });
602
Todd Volkert65079ad2018-05-03 07:39:41 -0700603 group('FlutterGoldenFileComparator', () {
Kate Lovett895beb02021-12-10 18:54:10 -0800604 late FlutterGoldenFileComparator comparator;
Kate Lovett616794f2019-07-28 12:26:06 -0700605
606 setUp(() {
Kate Lovett7bc02032019-10-25 15:05:21 -0700607 final Directory basedir = fs.directory('flutter/test/library/')
608 ..createSync(recursive: true);
Kate Lovettea67a652020-03-18 12:56:02 -0700609 comparator = FlutterPostSubmitFileComparator(
Kate Lovett7bc02032019-10-25 15:05:21 -0700610 basedir.uri,
Dan Field1747adb2021-01-27 13:09:46 -0800611 FakeSkiaGoldClient(),
Kate Lovett616794f2019-07-28 12:26:06 -0700612 fs: fs,
613 platform: platform,
614 );
615 });
616
Kate Lovett1c15cd82020-02-05 11:03:02 -0800617 test('calculates the basedir correctly from defaultComparator for local testing', () async {
Dan Field1747adb2021-01-27 13:09:46 -0800618 final FakeLocalFileComparator defaultComparator = FakeLocalFileComparator();
Kate Lovett7bc02032019-10-25 15:05:21 -0700619 final Directory flutterRoot = fs.directory(platform.environment['FLUTTER_ROOT'])
620 ..createSync(recursive: true);
Dan Field1747adb2021-01-27 13:09:46 -0800621 defaultComparator.basedir = flutterRoot.childDirectory('baz').uri;
Kate Lovett7bc02032019-10-25 15:05:21 -0700622
623 final Directory basedir = FlutterGoldenFileComparator.getBaseDirectory(
624 defaultComparator,
625 platform,
626 );
627 expect(
628 basedir.uri,
629 fs.directory('/flutter/bin/cache/pkg/skia_goldens/baz').uri,
630 );
631 });
632
633 test('ignores version number', () {
634 final Uri key = comparator.getTestUri(Uri.parse('foo.png'), 1);
635 expect(key, Uri.parse('foo.png'));
636 });
637
Michael Goderbauer00f3f2b2022-03-02 16:41:21 -0800638 test('adds namePrefix', () async {
639 const String libraryName = 'sidedishes';
640 const String namePrefix = 'tomatosalad';
641 const String fileName = 'lettuce.png';
642 final FakeSkiaGoldClient fakeSkiaClient = FakeSkiaGoldClient();
643 final Directory basedir = fs.directory('flutter/test/$libraryName/')
644 ..createSync(recursive: true);
645 final FlutterGoldenFileComparator comparator = FlutterPostSubmitFileComparator(
646 basedir.uri,
647 fakeSkiaClient,
648 fs: fs,
649 platform: platform,
650 namePrefix: namePrefix,
651 );
652 await comparator.compare(
653 Uint8List.fromList(_kTestPngBytes),
654 Uri.parse(fileName),
655 );
656 expect(fakeSkiaClient.testNames.single, '$namePrefix.$libraryName.$fileName');
657 });
658
Kate Lovett7bc02032019-10-25 15:05:21 -0700659 group('Post-Submit', () {
Kate Lovett895beb02021-12-10 18:54:10 -0800660 late FakeSkiaGoldClient fakeSkiaClient;
Kate Lovett7bc02032019-10-25 15:05:21 -0700661
662 setUp(() {
Kate Lovett895beb02021-12-10 18:54:10 -0800663 fakeSkiaClient = FakeSkiaGoldClient();
Kate Lovett7bc02032019-10-25 15:05:21 -0700664 final Directory basedir = fs.directory('flutter/test/library/')
665 ..createSync(recursive: true);
Kate Lovettea67a652020-03-18 12:56:02 -0700666 comparator = FlutterPostSubmitFileComparator(
Kate Lovett7bc02032019-10-25 15:05:21 -0700667 basedir.uri,
Dan Field1747adb2021-01-27 13:09:46 -0800668 fakeSkiaClient,
Kate Lovett7bc02032019-10-25 15:05:21 -0700669 fs: fs,
670 platform: platform,
671 );
672 });
673
Kate Lovetta288bd52022-02-24 23:06:19 -0600674 test('asserts .png format', () async {
675 await expectLater(
676 () async {
677 return comparator.compare(
678 Uint8List.fromList(_kTestPngBytes),
679 Uri.parse('flutter.golden_test.1'),
680 );
681 },
682 throwsA(
683 isA<AssertionError>().having((AssertionError error) => error.toString(),
684 'description',
685 contains(
686 'Golden files in the Flutter framework must end with the file '
687 'extension .png.'
688 ),
689 ),
690 ),
691 );
692 });
693
Kate Lovett895beb02021-12-10 18:54:10 -0800694 test('calls init during compare', () {
695 expect(fakeSkiaClient.initCalls, 0);
696 comparator.compare(
697 Uint8List.fromList(_kTestPngBytes),
698 Uri.parse('flutter.golden_test.1.png'),
699 );
700 expect(fakeSkiaClient.initCalls, 1);
701 });
702
703 test('does not call init in during construction', () {
704 expect(fakeSkiaClient.initCalls, 0);
705 FlutterPostSubmitFileComparator.fromDefaultComparator(
706 platform,
707 goldens: fakeSkiaClient,
708 );
709 expect(fakeSkiaClient.initCalls, 0);
710 });
711
Kate Lovett26d09f12019-10-31 11:44:07 -0700712 group('correctly determines testing environment', () {
Kate Lovett72696f72020-10-08 12:19:42 -0700713 test('returns true for configured Luci', () {
Kate Lovettea67a652020-03-18 12:56:02 -0700714 platform = FakePlatform(
715 environment: <String, String>{
716 'FLUTTER_ROOT': _kFlutterRoot,
717 'SWARMING_TASK_ID' : '12345678990',
718 'GOLDCTL' : 'goldctl',
719 },
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200720 operatingSystem: 'macos',
Kate Lovettea67a652020-03-18 12:56:02 -0700721 );
722 expect(
723 FlutterPostSubmitFileComparator.isAvailableForEnvironment(platform),
724 isTrue,
725 );
726 });
727
Kate Lovett72696f72020-10-08 12:19:42 -0700728 test('returns false - GOLDCTL not present', () {
Kate Lovett26d09f12019-10-31 11:44:07 -0700729 platform = FakePlatform(
730 environment: <String, String>{
731 'FLUTTER_ROOT': _kFlutterRoot,
Kate Lovett72696f72020-10-08 12:19:42 -0700732 'SWARMING_TASK_ID' : '12345678990',
Kate Lovett26d09f12019-10-31 11:44:07 -0700733 },
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200734 operatingSystem: 'macos',
Kate Lovett26d09f12019-10-31 11:44:07 -0700735 );
736 expect(
Kate Lovettea67a652020-03-18 12:56:02 -0700737 FlutterPostSubmitFileComparator.isAvailableForEnvironment(platform),
Kate Lovett26d09f12019-10-31 11:44:07 -0700738 isFalse,
739 );
740 });
741
Kate Lovett72696f72020-10-08 12:19:42 -0700742 test('returns false - GOLD_TRYJOB active', () {
743 platform = FakePlatform(
744 environment: <String, String>{
745 'FLUTTER_ROOT': _kFlutterRoot,
746 'SWARMING_TASK_ID' : '12345678990',
747 'GOLDCTL' : 'goldctl',
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200748 'GOLD_TRYJOB' : 'git/ref/12345/head',
Kate Lovett72696f72020-10-08 12:19:42 -0700749 },
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200750 operatingSystem: 'macos',
Kate Lovett72696f72020-10-08 12:19:42 -0700751 );
752 expect(
753 FlutterPostSubmitFileComparator.isAvailableForEnvironment(platform),
754 isFalse,
755 );
756 });
757
758 test('returns false - on Cirrus', () {
Kate Lovett26d09f12019-10-31 11:44:07 -0700759 platform = FakePlatform(
760 environment: <String, String>{
761 'FLUTTER_ROOT': _kFlutterRoot,
762 'CIRRUS_CI': 'true',
763 'CIRRUS_PR': '',
764 'CIRRUS_BRANCH': 'master',
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200765 'GOLD_SERVICE_ACCOUNT': 'service account...',
Kate Lovett26d09f12019-10-31 11:44:07 -0700766 },
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200767 operatingSystem: 'macos',
Kate Lovett26d09f12019-10-31 11:44:07 -0700768 );
769 expect(
Kate Lovettea67a652020-03-18 12:56:02 -0700770 FlutterPostSubmitFileComparator.isAvailableForEnvironment(platform),
Kate Lovett26d09f12019-10-31 11:44:07 -0700771 isFalse,
772 );
773 });
Kate Lovett7bc02032019-10-25 15:05:21 -0700774 });
775 });
776
777 group('Pre-Submit', () {
Kate Lovett895beb02021-12-10 18:54:10 -0800778 late FakeSkiaGoldClient fakeSkiaClient;
779
780 setUp(() {
781 fakeSkiaClient = FakeSkiaGoldClient();
782 final Directory basedir = fs.directory('flutter/test/library/')
783 ..createSync(recursive: true);
784 comparator = FlutterPreSubmitFileComparator(
785 basedir.uri,
786 fakeSkiaClient,
787 fs: fs,
788 platform: platform,
789 );
790 });
791
Kate Lovetta288bd52022-02-24 23:06:19 -0600792 test('asserts .png format', () async {
793 await expectLater(
794 () async {
795 return comparator.compare(
796 Uint8List.fromList(_kTestPngBytes),
797 Uri.parse('flutter.golden_test.1'),
798 );
799 },
800 throwsA(
801 isA<AssertionError>().having((AssertionError error) => error.toString(),
802 'description',
803 contains(
804 'Golden files in the Flutter framework must end with the file '
805 'extension .png.'
806 ),
807 ),
808 ),
809 );
810 });
811
Kate Lovett895beb02021-12-10 18:54:10 -0800812 test('calls init during compare', () {
813 expect(fakeSkiaClient.tryInitCalls, 0);
814 comparator.compare(
815 Uint8List.fromList(_kTestPngBytes),
816 Uri.parse('flutter.golden_test.1.png'),
817 );
818 expect(fakeSkiaClient.tryInitCalls, 1);
819 });
820
821 test('does not call init in during construction', () {
822 expect(fakeSkiaClient.tryInitCalls, 0);
823 FlutterPostSubmitFileComparator.fromDefaultComparator(
824 platform,
825 goldens: fakeSkiaClient,
826 );
827 expect(fakeSkiaClient.tryInitCalls, 0);
828 });
829
Kate Lovett26d09f12019-10-31 11:44:07 -0700830 group('correctly determines testing environment', () {
Kate Lovettea67a652020-03-18 12:56:02 -0700831 test('returns true for Luci', () {
832 platform = FakePlatform(
833 environment: <String, String>{
834 'FLUTTER_ROOT': _kFlutterRoot,
835 'SWARMING_TASK_ID' : '12345678990',
836 'GOLDCTL' : 'goldctl',
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200837 'GOLD_TRYJOB' : 'git/ref/12345/head',
Kate Lovettea67a652020-03-18 12:56:02 -0700838 },
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200839 operatingSystem: 'macos',
Kate Lovettea67a652020-03-18 12:56:02 -0700840 );
841 expect(
842 FlutterPreSubmitFileComparator.isAvailableForEnvironment(platform),
843 isTrue,
844 );
845 });
846
Kate Lovett72696f72020-10-08 12:19:42 -0700847 test('returns false - not on Luci', () {
848 platform = FakePlatform(
849 environment: <String, String>{
850 'FLUTTER_ROOT': _kFlutterRoot,
851 },
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200852 operatingSystem: 'macos',
Kate Lovett72696f72020-10-08 12:19:42 -0700853 );
854 expect(
855 FlutterPreSubmitFileComparator.isAvailableForEnvironment(platform),
856 isFalse,
857 );
858 });
859
860 test('returns false - GOLDCTL missing', () {
861 platform = FakePlatform(
862 environment: <String, String>{
863 'FLUTTER_ROOT': _kFlutterRoot,
864 'SWARMING_TASK_ID' : '12345678990',
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200865 'GOLD_TRYJOB' : 'git/ref/12345/head',
Kate Lovett72696f72020-10-08 12:19:42 -0700866 },
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200867 operatingSystem: 'macos',
Kate Lovett72696f72020-10-08 12:19:42 -0700868 );
869 expect(
870 FlutterPreSubmitFileComparator.isAvailableForEnvironment(platform),
871 isFalse,
872 );
873 });
874
875 test('returns false - GOLD_TRYJOB missing', () {
876 platform = FakePlatform(
877 environment: <String, String>{
878 'FLUTTER_ROOT': _kFlutterRoot,
879 'SWARMING_TASK_ID' : '12345678990',
880 'GOLDCTL' : 'goldctl',
881 },
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200882 operatingSystem: 'macos',
Kate Lovett72696f72020-10-08 12:19:42 -0700883 );
884 expect(
885 FlutterPreSubmitFileComparator.isAvailableForEnvironment(platform),
886 isFalse,
887 );
888 });
889
890 test('returns false - on Cirrus', () {
Kate Lovett26d09f12019-10-31 11:44:07 -0700891 platform = FakePlatform(
892 environment: <String, String>{
893 'FLUTTER_ROOT': _kFlutterRoot,
894 'CIRRUS_CI': 'true',
895 'CIRRUS_PR': '',
Kate Lovett72696f72020-10-08 12:19:42 -0700896 'CIRRUS_BRANCH': 'master',
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200897 'GOLD_SERVICE_ACCOUNT': 'service account...',
Kate Lovett26d09f12019-10-31 11:44:07 -0700898 },
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200899 operatingSystem: 'macos',
Kate Lovett26d09f12019-10-31 11:44:07 -0700900 );
901 expect(
Kate Lovett72696f72020-10-08 12:19:42 -0700902 FlutterPostSubmitFileComparator.isAvailableForEnvironment(platform),
Kate Lovett26d09f12019-10-31 11:44:07 -0700903 isFalse,
904 );
905 });
Kate Lovett7bc02032019-10-25 15:05:21 -0700906 });
Kate Lovett7bc02032019-10-25 15:05:21 -0700907 });
908
Kate Lovett26d09f12019-10-31 11:44:07 -0700909 group('Skipping', () {
910 group('correctly determines testing environment', () {
Kate Lovett72696f72020-10-08 12:19:42 -0700911 test('returns true on Cirrus builds', () {
Kate Lovett26d09f12019-10-31 11:44:07 -0700912 platform = FakePlatform(
913 environment: <String, String>{
914 'FLUTTER_ROOT': _kFlutterRoot,
915 'CIRRUS_CI' : 'yep',
916 },
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200917 operatingSystem: 'macos',
Kate Lovett26d09f12019-10-31 11:44:07 -0700918 );
919 expect(
Kate Lovettea67a652020-03-18 12:56:02 -0700920 FlutterSkippingFileComparator.isAvailableForEnvironment(platform),
Kate Lovett26d09f12019-10-31 11:44:07 -0700921 isTrue,
922 );
923 });
Kate Lovettea67a652020-03-18 12:56:02 -0700924
Kate Lovett72696f72020-10-08 12:19:42 -0700925 test('returns true on irrelevant LUCI builds', () {
926 platform = FakePlatform(
927 environment: <String, String>{
928 'FLUTTER_ROOT': _kFlutterRoot,
929 'SWARMING_TASK_ID' : '1234567890',
930 },
931 operatingSystem: 'macos'
932 );
933 expect(
934 FlutterSkippingFileComparator.isAvailableForEnvironment(platform),
935 isTrue,
936 );
937 });
938
Kate Lovettceab1242019-12-11 11:03:21 -0800939 test('returns false - no CI', () {
Kate Lovett26d09f12019-10-31 11:44:07 -0700940 platform = FakePlatform(
941 environment: <String, String>{
942 'FLUTTER_ROOT': _kFlutterRoot,
943 },
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200944 operatingSystem: 'macos',
Kate Lovett26d09f12019-10-31 11:44:07 -0700945 );
946 expect(
Kate Lovettea67a652020-03-18 12:56:02 -0700947 FlutterSkippingFileComparator.isAvailableForEnvironment(
Kate Lovett26d09f12019-10-31 11:44:07 -0700948 platform),
949 isFalse,
950 );
951 });
952 });
953 });
954
Kate Lovett7bc02032019-10-25 15:05:21 -0700955 group('Local', () {
Kate Lovettf04616f2021-01-27 19:29:04 -0600956 late FlutterLocalFileComparator comparator;
Dan Field1747adb2021-01-27 13:09:46 -0800957 final FakeSkiaGoldClient fakeSkiaClient = FakeSkiaGoldClient();
Kate Lovett7bc02032019-10-25 15:05:21 -0700958
959 setUp(() async {
960 final Directory basedir = fs.directory('flutter/test/library/')
961 ..createSync(recursive: true);
962 comparator = FlutterLocalFileComparator(
963 basedir.uri,
Dan Field1747adb2021-01-27 13:09:46 -0800964 fakeSkiaClient,
Kate Lovett7bc02032019-10-25 15:05:21 -0700965 fs: fs,
966 platform: FakePlatform(
967 environment: <String, String>{'FLUTTER_ROOT': _kFlutterRoot},
Alexandre Ardhuin07f1c202022-04-27 09:15:35 +0200968 operatingSystem: 'macos',
Kate Lovett7bc02032019-10-25 15:05:21 -0700969 ),
970 );
971
Dan Field1747adb2021-01-27 13:09:46 -0800972 const String hash = '55109a4bed52acc780530f7a9aeff6c0';
973 fakeSkiaClient.expectationForTestValues['flutter.golden_test.1'] = hash;
Dan Field1747adb2021-01-27 13:09:46 -0800974 fakeSkiaClient.imageBytesValues[hash] =_kTestPngBytes;
975 fakeSkiaClient.cleanTestNameValues['library.flutter.golden_test.1.png'] = 'flutter.golden_test.1';
Kate Lovett7bc02032019-10-25 15:05:21 -0700976 });
977
Kate Lovetta288bd52022-02-24 23:06:19 -0600978 test('asserts .png format', () async {
979 await expectLater(
980 () async {
981 return comparator.compare(
982 Uint8List.fromList(_kTestPngBytes),
983 Uri.parse('flutter.golden_test.1'),
984 );
985 },
986 throwsA(
987 isA<AssertionError>().having((AssertionError error) => error.toString(),
988 'description',
989 contains(
990 'Golden files in the Flutter framework must end with the file '
991 'extension .png.'
992 ),
993 ),
994 ),
995 );
996 });
997
Kate Lovett7bc02032019-10-25 15:05:21 -0700998 test('passes when bytes match', () async {
999 expect(
1000 await comparator.compare(
1001 Uint8List.fromList(_kTestPngBytes),
1002 Uri.parse('flutter.golden_test.1.png'),
1003 ),
1004 isTrue,
1005 );
1006 });
1007
Kate Lovettb1ca7f42019-11-15 13:04:59 -08001008 test('returns FlutterSkippingGoldenFileComparator when network connection is unavailable', () async {
Dan Field1747adb2021-01-27 13:09:46 -08001009 final FakeDirectory fakeDirectory = FakeDirectory();
1010 fakeDirectory.existsSyncValue = true;
1011 fakeDirectory.uri = Uri.parse('/flutter');
Kate Lovett6397c022020-01-10 14:43:01 -08001012
Dan Field1747adb2021-01-27 13:09:46 -08001013 fakeSkiaClient.getExpectationForTestThrowable = const OSError("Can't reach Gold");
1014
Kate Lovett6397c022020-01-10 14:43:01 -08001015 FlutterGoldenFileComparator comparator = await FlutterLocalFileComparator.fromDefaultComparator(
1016 platform,
Dan Field1747adb2021-01-27 13:09:46 -08001017 goldens: fakeSkiaClient,
1018 baseDirectory: fakeDirectory,
Kate Lovett6397c022020-01-10 14:43:01 -08001019 );
Kate Lovettea67a652020-03-18 12:56:02 -07001020 expect(comparator.runtimeType, FlutterSkippingFileComparator);
Kate Lovett6397c022020-01-10 14:43:01 -08001021
Dan Field1747adb2021-01-27 13:09:46 -08001022 fakeSkiaClient.getExpectationForTestThrowable = const SocketException("Can't reach Gold");
1023
Kate Lovett6397c022020-01-10 14:43:01 -08001024 comparator = await FlutterLocalFileComparator.fromDefaultComparator(
Kate Lovettb1ca7f42019-11-15 13:04:59 -08001025 platform,
Dan Field1747adb2021-01-27 13:09:46 -08001026 goldens: fakeSkiaClient,
1027 baseDirectory: fakeDirectory,
Kate Lovettb1ca7f42019-11-15 13:04:59 -08001028 );
Kate Lovettea67a652020-03-18 12:56:02 -07001029 expect(comparator.runtimeType, FlutterSkippingFileComparator);
Alexander Dahlbergf0916542021-11-11 21:44:32 +01001030 // reset property or it will carry on to other tests
1031 fakeSkiaClient.getExpectationForTestThrowable = null;
Kate Lovettb1ca7f42019-11-15 13:04:59 -08001032 });
Kate Lovett7bc02032019-10-25 15:05:21 -07001033 });
Todd Volkert65079ad2018-05-03 07:39:41 -07001034 });
1035}
1036
Dan Field1747adb2021-01-27 13:09:46 -08001037@immutable
1038class RunInvocation {
1039 const RunInvocation(this.command, this.workingDirectory);
Kate Lovett7bc02032019-10-25 15:05:21 -07001040
Dan Field1747adb2021-01-27 13:09:46 -08001041 final List<String> command;
Kate Lovettf04616f2021-01-27 19:29:04 -06001042 final String? workingDirectory;
Kate Lovett7bc02032019-10-25 15:05:21 -07001043
Dan Field1747adb2021-01-27 13:09:46 -08001044 @override
Viren Khatri671aa9e2022-03-05 02:26:21 +05301045 int get hashCode => Object.hash(Object.hashAll(command), workingDirectory);
Kate Lovett7bc02032019-10-25 15:05:21 -07001046
Dan Field1747adb2021-01-27 13:09:46 -08001047 bool _commandEquals(List<String> other) {
1048 if (other == command) {
1049 return true;
1050 }
1051 if (other.length != command.length) {
1052 return false;
1053 }
1054 for (int index = 0; index < other.length; index += 1) {
1055 if (other[index] != command[index]) {
1056 return false;
1057 }
1058 }
1059 return true;
1060 }
Kate Lovettb1ca7f42019-11-15 13:04:59 -08001061
Dan Field1747adb2021-01-27 13:09:46 -08001062 @override
1063 bool operator ==(Object other) {
1064 if (other.runtimeType != runtimeType) {
1065 return false;
1066 }
1067 return other is RunInvocation
1068 && _commandEquals(other.command)
1069 && other.workingDirectory == workingDirectory;
1070 }
Kate Lovett7bc02032019-10-25 15:05:21 -07001071
Dan Field1747adb2021-01-27 13:09:46 -08001072 @override
1073 String toString() => '$command ($workingDirectory)';
1074}
Kate Lovett7bc02032019-10-25 15:05:21 -07001075
Dan Field1747adb2021-01-27 13:09:46 -08001076class FakeProcessManager extends Fake implements ProcessManager {
1077 Map<RunInvocation, ProcessResult> processResults = <RunInvocation, ProcessResult>{};
1078
Kate Lovettf04616f2021-01-27 19:29:04 -06001079 /// Used if [processResults] does not contain a matching invocation.
1080 ProcessResult? fallbackProcessResult;
Dan Field1747adb2021-01-27 13:09:46 -08001081
Jonah Williams7088c5b2021-02-16 15:29:12 -08001082 final List<String?> workingDirectories = <String?>[];
Dan Field1747adb2021-01-27 13:09:46 -08001083
1084 @override
1085 Future<ProcessResult> run(
Jonah Williams7088c5b2021-02-16 15:29:12 -08001086 List<Object> command, {
1087 String? workingDirectory,
1088 Map<String, String>? environment,
Dan Field1747adb2021-01-27 13:09:46 -08001089 bool includeParentEnvironment = true,
1090 bool runInShell = false,
Chris Wong7ef52262021-12-01 12:14:07 +11001091 Encoding? stdoutEncoding = systemEncoding,
1092 Encoding? stderrEncoding = systemEncoding,
Dan Field1747adb2021-01-27 13:09:46 -08001093 }) async {
1094 workingDirectories.add(workingDirectory);
Kate Lovettf04616f2021-01-27 19:29:04 -06001095 final ProcessResult? result = processResults[RunInvocation(command.cast<String>(), workingDirectory)];
Dan Field1747adb2021-01-27 13:09:46 -08001096 if (result == null && fallbackProcessResult == null) {
Ian Hicksonf25b8332021-10-07 16:48:04 -07001097 printOnFailure('ProcessManager.run was called with $command ($workingDirectory) unexpectedly - $processResults.');
Kate Lovettf04616f2021-01-27 19:29:04 -06001098 fail('See above.');
Dan Field1747adb2021-01-27 13:09:46 -08001099 }
Kate Lovettf04616f2021-01-27 19:29:04 -06001100 return result ?? fallbackProcessResult!;
Dan Field1747adb2021-01-27 13:09:46 -08001101 }
1102}
1103
Ian Hicksonf25b8332021-10-07 16:48:04 -07001104// See also dev/automated_tests/flutter_test/flutter_gold_test.dart
Dan Field1747adb2021-01-27 13:09:46 -08001105class FakeSkiaGoldClient extends Fake implements SkiaGoldClient {
1106 Map<String, String> expectationForTestValues = <String, String>{};
Ian Hickson94216272021-10-11 14:13:03 -07001107 Exception? getExpectationForTestThrowable;
Dan Field1747adb2021-01-27 13:09:46 -08001108 @override
1109 Future<String> getExpectationForTest(String testName) async {
1110 if (getExpectationForTestThrowable != null) {
Kate Lovettf04616f2021-01-27 19:29:04 -06001111 throw getExpectationForTestThrowable!;
Dan Field1747adb2021-01-27 13:09:46 -08001112 }
Kate Lovettf04616f2021-01-27 19:29:04 -06001113 return expectationForTestValues[testName] ?? '';
Dan Field1747adb2021-01-27 13:09:46 -08001114 }
1115
Kate Lovett895beb02021-12-10 18:54:10 -08001116 @override
1117 Future<void> auth() async {}
1118
Michael Goderbauer00f3f2b2022-03-02 16:41:21 -08001119 final List<String> testNames = <String>[];
1120
Kate Lovett895beb02021-12-10 18:54:10 -08001121 int initCalls = 0;
1122 @override
1123 Future<void> imgtestInit() async => initCalls += 1;
1124 @override
Michael Goderbauer00f3f2b2022-03-02 16:41:21 -08001125 Future<bool> imgtestAdd(String testName, File goldenFile) async {
1126 testNames.add(testName);
1127 return true;
1128 }
Kate Lovett895beb02021-12-10 18:54:10 -08001129
1130 int tryInitCalls = 0;
1131 @override
1132 Future<void> tryjobInit() async => tryInitCalls += 1;
1133 @override
1134 Future<bool> tryjobAdd(String testName, File goldenFile) async => true;
1135
Dan Field1747adb2021-01-27 13:09:46 -08001136 Map<String, List<int>> imageBytesValues = <String, List<int>>{};
1137 @override
Kate Lovettf04616f2021-01-27 19:29:04 -06001138 Future<List<int>> getImageBytes(String imageHash) async => imageBytesValues[imageHash]!;
Dan Field1747adb2021-01-27 13:09:46 -08001139
1140 Map<String, String> cleanTestNameValues = <String, String>{};
1141 @override
Kate Lovettf04616f2021-01-27 19:29:04 -06001142 String cleanTestName(String fileName) => cleanTestNameValues[fileName] ?? '';
Dan Field1747adb2021-01-27 13:09:46 -08001143}
1144
1145class FakeLocalFileComparator extends Fake implements LocalFileComparator {
1146 @override
Kate Lovettf04616f2021-01-27 19:29:04 -06001147 late Uri basedir;
Dan Field1747adb2021-01-27 13:09:46 -08001148}
1149
1150class FakeDirectory extends Fake implements Directory {
Kate Lovettf04616f2021-01-27 19:29:04 -06001151 late bool existsSyncValue;
Dan Field1747adb2021-01-27 13:09:46 -08001152 @override
1153 bool existsSync() => existsSyncValue;
1154
1155 @override
Kate Lovettf04616f2021-01-27 19:29:04 -06001156 late Uri uri;
Dan Field1747adb2021-01-27 13:09:46 -08001157}
1158
1159class FakeHttpClient extends Fake implements HttpClient {
Kate Lovettf04616f2021-01-27 19:29:04 -06001160 late Uri lastUri;
1161 late FakeHttpClientRequest request;
Dan Field1747adb2021-01-27 13:09:46 -08001162
1163 @override
1164 Future<HttpClientRequest> getUrl(Uri url) async {
1165 lastUri = url;
1166 return request;
1167 }
1168}
1169
1170class FakeHttpClientRequest extends Fake implements HttpClientRequest {
Kate Lovettf04616f2021-01-27 19:29:04 -06001171 late FakeHttpImageResponse response;
Dan Field1747adb2021-01-27 13:09:46 -08001172
1173 @override
1174 Future<HttpClientResponse> close() async {
1175 return response;
1176 }
1177}
1178
Dan Field1747adb2021-01-27 13:09:46 -08001179class FakeHttpImageResponse extends Fake implements HttpClientResponse {
1180 FakeHttpImageResponse(this.response);
Kate Lovett7bc02032019-10-25 15:05:21 -07001181
1182 final List<List<int>> response;
1183
1184 @override
Michael Goderbauer7b251f52021-03-04 08:59:17 -08001185 Future<void> forEach(void Function(List<int> element) action) async {
Kate Lovett7bc02032019-10-25 15:05:21 -07001186 response.forEach(action);
1187 }
1188}