OLD | NEW |
| (Empty) |
1 #!/usr/bin/python | |
2 | |
3 """ | |
4 Copyright 2014 Google Inc. | |
5 | |
6 Use of this source code is governed by a BSD-style license that can be | |
7 found in the LICENSE file. | |
8 | |
9 Test the render_pictures binary. | |
10 """ | |
11 | |
12 # System-level imports | |
13 import copy | |
14 import json | |
15 import os | |
16 import shutil | |
17 import tempfile | |
18 | |
19 # Must fix up PYTHONPATH before importing from within Skia | |
20 import fix_pythonpath # pylint: disable=W0611 | |
21 | |
22 # Imports from within Skia | |
23 import base_unittest | |
24 import find_run_binary | |
25 | |
26 # Maximum length of text diffs to show when tests fail | |
27 MAX_DIFF_LENGTH = 30000 | |
28 | |
29 EXPECTED_HEADER_CONTENTS = { | |
30 "type" : "ChecksummedImages", | |
31 "revision" : 1, | |
32 } | |
33 | |
34 # Manually verified: 640x400 red rectangle with black border | |
35 # Standard expectations will be set up in such a way that this image fails | |
36 # the comparison. | |
37 RED_WHOLEIMAGE = { | |
38 "checksumAlgorithm" : "bitmap-64bitMD5", | |
39 "checksumValue" : 2853310525600416231, | |
40 "comparisonResult" : "failed", | |
41 "filepath" : "red_skp.png", | |
42 } | |
43 | |
44 # Manually verified: 640x400 green rectangle with black border | |
45 # Standard expectations will be set up in such a way that this image passes | |
46 # the comparison. | |
47 GREEN_WHOLEIMAGE = { | |
48 "checksumAlgorithm" : "bitmap-64bitMD5", | |
49 "checksumValue" : 11143979097452425335, | |
50 "comparisonResult" : "succeeded", | |
51 "filepath" : "green_skp.png", | |
52 } | |
53 | |
54 # Manually verified these 6 images, all 256x256 tiles, | |
55 # consistent with a tiled version of the 640x400 red rect | |
56 # with black borders. | |
57 # Standard expectations will be set up in such a way that these images fail | |
58 # the comparison. | |
59 RED_TILES = [{ | |
60 "checksumAlgorithm" : "bitmap-64bitMD5", | |
61 "checksumValue" : 5815827069051002745, | |
62 "comparisonResult" : "failed", | |
63 "filepath" : "red_skp-tile0.png", | |
64 },{ | |
65 "checksumAlgorithm" : "bitmap-64bitMD5", | |
66 "checksumValue" : 9323613075234140270, | |
67 "comparisonResult" : "failed", | |
68 "filepath" : "red_skp-tile1.png", | |
69 }, { | |
70 "checksumAlgorithm" : "bitmap-64bitMD5", | |
71 "checksumValue" : 15939355025996362179, | |
72 "comparisonResult" : "failed", | |
73 "filepath" : "red_skp-tile2.png", | |
74 }, { | |
75 "checksumAlgorithm" : "bitmap-64bitMD5", | |
76 "checksumValue" : 649771916797529222, | |
77 "comparisonResult" : "failed", | |
78 "filepath" : "red_skp-tile3.png", | |
79 }, { | |
80 "checksumAlgorithm" : "bitmap-64bitMD5", | |
81 "checksumValue" : 8132820002266077288, | |
82 "comparisonResult" : "failed", | |
83 "filepath" : "red_skp-tile4.png", | |
84 }, { | |
85 "checksumAlgorithm" : "bitmap-64bitMD5", | |
86 "checksumValue" : 2406160701181324581, | |
87 "comparisonResult" : "failed", | |
88 "filepath" : "red_skp-tile5.png", | |
89 }] | |
90 | |
91 # Manually verified these 6 images, all 256x256 tiles, | |
92 # consistent with a tiled version of the 640x400 green rect | |
93 # with black borders. | |
94 # Standard expectations will be set up in such a way that these images pass | |
95 # the comparison. | |
96 GREEN_TILES = [{ | |
97 "checksumAlgorithm" : "bitmap-64bitMD5", | |
98 "checksumValue" : 12587324416545178013, | |
99 "comparisonResult" : "succeeded", | |
100 "filepath" : "green_skp-tile0.png", | |
101 }, { | |
102 "checksumAlgorithm" : "bitmap-64bitMD5", | |
103 "checksumValue" : 7624374914829746293, | |
104 "comparisonResult" : "succeeded", | |
105 "filepath" : "green_skp-tile1.png", | |
106 }, { | |
107 "checksumAlgorithm" : "bitmap-64bitMD5", | |
108 "checksumValue" : 11866144860997809880, | |
109 "comparisonResult" : "succeeded", | |
110 "filepath" : "green_skp-tile2.png", | |
111 }, { | |
112 "checksumAlgorithm" : "bitmap-64bitMD5", | |
113 "checksumValue" : 3893392565127823822, | |
114 "comparisonResult" : "succeeded", | |
115 "filepath" : "green_skp-tile3.png", | |
116 }, { | |
117 "checksumAlgorithm" : "bitmap-64bitMD5", | |
118 "checksumValue" : 2083084978343901738, | |
119 "comparisonResult" : "succeeded", | |
120 "filepath" : "green_skp-tile4.png", | |
121 }, { | |
122 "checksumAlgorithm" : "bitmap-64bitMD5", | |
123 "checksumValue" : 89620927366502076, | |
124 "comparisonResult" : "succeeded", | |
125 "filepath" : "green_skp-tile5.png", | |
126 }] | |
127 | |
128 | |
129 def modified_dict(input_dict, modification_dict): | |
130 """Returns a dict, with some modifications applied to it. | |
131 | |
132 Args: | |
133 input_dict: a dictionary (which will be copied, not modified in place) | |
134 modification_dict: a set of key/value pairs to overwrite in the dict | |
135 """ | |
136 output_dict = input_dict.copy() | |
137 output_dict.update(modification_dict) | |
138 return output_dict | |
139 | |
140 | |
141 def modified_list_of_dicts(input_list, modification_dict): | |
142 """Returns a list of dicts, with some modifications applied to each dict. | |
143 | |
144 Args: | |
145 input_list: a list of dictionaries; these dicts will be copied, not | |
146 modified in place | |
147 modification_dict: a set of key/value pairs to overwrite in each dict | |
148 within input_list | |
149 """ | |
150 output_list = [] | |
151 for input_dict in input_list: | |
152 output_dict = modified_dict(input_dict, modification_dict) | |
153 output_list.append(output_dict) | |
154 return output_list | |
155 | |
156 | |
157 class RenderPicturesTest(base_unittest.TestCase): | |
158 | |
159 def setUp(self): | |
160 self.maxDiff = MAX_DIFF_LENGTH | |
161 self._expectations_dir = tempfile.mkdtemp() | |
162 self._input_skp_dir = tempfile.mkdtemp() | |
163 # All output of render_pictures binary will go into this directory. | |
164 self._output_dir = tempfile.mkdtemp() | |
165 | |
166 def tearDown(self): | |
167 shutil.rmtree(self._expectations_dir) | |
168 shutil.rmtree(self._input_skp_dir) | |
169 shutil.rmtree(self._output_dir) | |
170 | |
171 def test_tiled_whole_image(self): | |
172 """Run render_pictures with tiles and --writeWholeImage flag. | |
173 | |
174 TODO(epoger): This test generates undesired results! The JSON summary | |
175 includes both whole-image and tiled-images (as it should), but only | |
176 whole-images are written out to disk. See http://skbug.com/2463 | |
177 Once I fix that, I should add a similar test that exercises mismatchPath. | |
178 | |
179 TODO(epoger): I noticed that when this is run without --writePath being | |
180 specified, this test writes red_skp.png and green_skp.png to the current | |
181 directory. We should fix that... if --writePath is not specified, this | |
182 probably shouldn't write out red_skp.png and green_skp.png at all! | |
183 See http://skbug.com/2464 | |
184 """ | |
185 output_json_path = os.path.join(self._output_dir, 'actuals.json') | |
186 write_path_dir = self.create_empty_dir( | |
187 path=os.path.join(self._output_dir, 'writePath')) | |
188 self._generate_skps() | |
189 expectations_path = self._create_expectations() | |
190 self._run_render_pictures([ | |
191 '-r', self._input_skp_dir, | |
192 '--bbh', 'grid', '256', '256', | |
193 '--mode', 'tile', '256', '256', | |
194 '--readJsonSummaryPath', expectations_path, | |
195 '--writeJsonSummaryPath', output_json_path, | |
196 '--writePath', write_path_dir, | |
197 '--writeWholeImage']) | |
198 expected_summary_dict = { | |
199 "header" : EXPECTED_HEADER_CONTENTS, | |
200 "image-base-gs-url" : None, | |
201 "descriptions" : None, | |
202 "actual-results" : { | |
203 "red.skp": { | |
204 "tiled-images": RED_TILES, | |
205 "whole-image": RED_WHOLEIMAGE, | |
206 }, | |
207 "green.skp": { | |
208 "tiled-images": GREEN_TILES, | |
209 "whole-image": GREEN_WHOLEIMAGE, | |
210 } | |
211 } | |
212 } | |
213 self._assert_json_contents(output_json_path, expected_summary_dict) | |
214 self._assert_directory_contents( | |
215 write_path_dir, ['red_skp.png', 'green_skp.png']) | |
216 | |
217 def test_ignore_some_failures(self): | |
218 """test_tiled_whole_image, but ignoring some failed tests. | |
219 """ | |
220 output_json_path = os.path.join(self._output_dir, 'actuals.json') | |
221 write_path_dir = self.create_empty_dir( | |
222 path=os.path.join(self._output_dir, 'writePath')) | |
223 self._generate_skps() | |
224 expectations_path = self._create_expectations(ignore_some_failures=True) | |
225 self._run_render_pictures([ | |
226 '-r', self._input_skp_dir, | |
227 '--bbh', 'grid', '256', '256', | |
228 '--mode', 'tile', '256', '256', | |
229 '--readJsonSummaryPath', expectations_path, | |
230 '--writeJsonSummaryPath', output_json_path, | |
231 '--writePath', write_path_dir, | |
232 '--writeWholeImage']) | |
233 modified_red_tiles = copy.deepcopy(RED_TILES) | |
234 modified_red_tiles[5]['comparisonResult'] = 'failure-ignored' | |
235 expected_summary_dict = { | |
236 "header" : EXPECTED_HEADER_CONTENTS, | |
237 "image-base-gs-url" : None, | |
238 "descriptions" : None, | |
239 "actual-results" : { | |
240 "red.skp": { | |
241 "tiled-images": modified_red_tiles, | |
242 "whole-image": modified_dict( | |
243 RED_WHOLEIMAGE, {"comparisonResult" : "failure-ignored"}), | |
244 }, | |
245 "green.skp": { | |
246 "tiled-images": GREEN_TILES, | |
247 "whole-image": GREEN_WHOLEIMAGE, | |
248 } | |
249 } | |
250 } | |
251 self._assert_json_contents(output_json_path, expected_summary_dict) | |
252 self._assert_directory_contents( | |
253 write_path_dir, ['red_skp.png', 'green_skp.png']) | |
254 | |
255 def test_missing_tile_and_whole_image(self): | |
256 """test_tiled_whole_image, but missing expectations for some images. | |
257 """ | |
258 output_json_path = os.path.join(self._output_dir, 'actuals.json') | |
259 write_path_dir = self.create_empty_dir( | |
260 path=os.path.join(self._output_dir, 'writePath')) | |
261 self._generate_skps() | |
262 expectations_path = self._create_expectations(missing_some_images=True) | |
263 self._run_render_pictures([ | |
264 '-r', self._input_skp_dir, | |
265 '--bbh', 'grid', '256', '256', | |
266 '--mode', 'tile', '256', '256', | |
267 '--readJsonSummaryPath', expectations_path, | |
268 '--writeJsonSummaryPath', output_json_path, | |
269 '--writePath', write_path_dir, | |
270 '--writeWholeImage']) | |
271 modified_red_tiles = copy.deepcopy(RED_TILES) | |
272 modified_red_tiles[5]['comparisonResult'] = 'no-comparison' | |
273 expected_summary_dict = { | |
274 "header" : EXPECTED_HEADER_CONTENTS, | |
275 "image-base-gs-url" : None, | |
276 "descriptions" : None, | |
277 "actual-results" : { | |
278 "red.skp": { | |
279 "tiled-images": modified_red_tiles, | |
280 "whole-image": modified_dict( | |
281 RED_WHOLEIMAGE, {"comparisonResult" : "no-comparison"}), | |
282 }, | |
283 "green.skp": { | |
284 "tiled-images": GREEN_TILES, | |
285 "whole-image": GREEN_WHOLEIMAGE, | |
286 } | |
287 } | |
288 } | |
289 self._assert_json_contents(output_json_path, expected_summary_dict) | |
290 | |
291 def _test_untiled(self, expectations_path=None, expected_summary_dict=None, | |
292 additional_args=None): | |
293 """Base for multiple tests without tiles. | |
294 | |
295 Args: | |
296 expectations_path: path we should pass using --readJsonSummaryPath, or | |
297 None if we should create the default expectations file | |
298 expected_summary_dict: dict we should compare against the output actual | |
299 results summary, or None if we should use a default comparison dict | |
300 additional_args: array of command-line args to add when we run | |
301 render_pictures | |
302 """ | |
303 output_json_path = os.path.join(self._output_dir, 'actuals.json') | |
304 write_path_dir = self.create_empty_dir( | |
305 path=os.path.join(self._output_dir, 'writePath')) | |
306 self._generate_skps() | |
307 if expectations_path == None: | |
308 expectations_path = self._create_expectations() | |
309 args = [ | |
310 '-r', self._input_skp_dir, | |
311 '--readJsonSummaryPath', expectations_path, | |
312 '--writePath', write_path_dir, | |
313 '--writeJsonSummaryPath', output_json_path, | |
314 ] | |
315 if additional_args: | |
316 args.extend(additional_args) | |
317 self._run_render_pictures(args) | |
318 if expected_summary_dict == None: | |
319 expected_summary_dict = { | |
320 "header" : EXPECTED_HEADER_CONTENTS, | |
321 "image-base-gs-url" : None, | |
322 "descriptions" : None, | |
323 "actual-results" : { | |
324 "red.skp": { | |
325 "whole-image": RED_WHOLEIMAGE, | |
326 }, | |
327 "green.skp": { | |
328 "whole-image": GREEN_WHOLEIMAGE, | |
329 } | |
330 } | |
331 } | |
332 self._assert_json_contents(output_json_path, expected_summary_dict) | |
333 self._assert_directory_contents( | |
334 write_path_dir, ['red_skp.png', 'green_skp.png']) | |
335 | |
336 def test_untiled(self): | |
337 """Basic test without tiles.""" | |
338 self._test_untiled() | |
339 | |
340 def test_untiled_empty_expectations_file(self): | |
341 """Same as test_untiled, but with an empty expectations file.""" | |
342 expectations_path = os.path.join(self._expectations_dir, 'empty') | |
343 with open(expectations_path, 'w'): | |
344 pass | |
345 expected_summary_dict = { | |
346 "header" : EXPECTED_HEADER_CONTENTS, | |
347 "image-base-gs-url" : None, | |
348 "descriptions" : None, | |
349 "actual-results" : { | |
350 "red.skp": { | |
351 "whole-image": modified_dict( | |
352 RED_WHOLEIMAGE, {"comparisonResult" : "no-comparison"}), | |
353 }, | |
354 "green.skp": { | |
355 "whole-image": modified_dict( | |
356 GREEN_WHOLEIMAGE, {"comparisonResult" : "no-comparison"}), | |
357 } | |
358 } | |
359 } | |
360 self._test_untiled(expectations_path=expectations_path, | |
361 expected_summary_dict=expected_summary_dict) | |
362 | |
363 def test_untiled_writeChecksumBasedFilenames(self): | |
364 """Same as test_untiled, but with --writeChecksumBasedFilenames.""" | |
365 output_json_path = os.path.join(self._output_dir, 'actuals.json') | |
366 write_path_dir = self.create_empty_dir( | |
367 path=os.path.join(self._output_dir, 'writePath')) | |
368 self._generate_skps() | |
369 self._run_render_pictures([ | |
370 '-r', self._input_skp_dir, | |
371 '--descriptions', 'builder=builderName', 'renderMode=renderModeName', | |
372 '--writeChecksumBasedFilenames', | |
373 '--writePath', write_path_dir, | |
374 '--writeJsonSummaryPath', output_json_path, | |
375 ]) | |
376 expected_summary_dict = { | |
377 "header" : EXPECTED_HEADER_CONTENTS, | |
378 "image-base-gs-url" : None, | |
379 "descriptions" : { | |
380 "builder": "builderName", | |
381 "renderMode": "renderModeName", | |
382 }, | |
383 "actual-results" : { | |
384 "red.skp": { | |
385 # Manually verified: 640x400 red rectangle with black border | |
386 "whole-image": { | |
387 "checksumAlgorithm" : "bitmap-64bitMD5", | |
388 "checksumValue" : 2853310525600416231, | |
389 "comparisonResult" : "no-comparison", | |
390 "filepath" : | |
391 "red_skp/bitmap-64bitMD5_2853310525600416231.png", | |
392 }, | |
393 }, | |
394 "green.skp": { | |
395 # Manually verified: 640x400 green rectangle with black border | |
396 "whole-image": { | |
397 "checksumAlgorithm" : "bitmap-64bitMD5", | |
398 "checksumValue" : 11143979097452425335, | |
399 "comparisonResult" : "no-comparison", | |
400 "filepath" : | |
401 "green_skp/bitmap-64bitMD5_11143979097452425335.png", | |
402 }, | |
403 } | |
404 } | |
405 } | |
406 self._assert_json_contents(output_json_path, expected_summary_dict) | |
407 self._assert_directory_contents(write_path_dir, ['red_skp', 'green_skp']) | |
408 self._assert_directory_contents( | |
409 os.path.join(write_path_dir, 'red_skp'), | |
410 ['bitmap-64bitMD5_2853310525600416231.png']) | |
411 self._assert_directory_contents( | |
412 os.path.join(write_path_dir, 'green_skp'), | |
413 ['bitmap-64bitMD5_11143979097452425335.png']) | |
414 | |
415 def test_untiled_validate(self): | |
416 """Same as test_untiled, but with --validate.""" | |
417 self._test_untiled(additional_args=['--validate']) | |
418 | |
419 def test_untiled_without_writePath(self): | |
420 """Same as test_untiled, but without --writePath.""" | |
421 output_json_path = os.path.join(self._output_dir, 'actuals.json') | |
422 self._generate_skps() | |
423 expectations_path = self._create_expectations() | |
424 self._run_render_pictures([ | |
425 '-r', self._input_skp_dir, | |
426 '--readJsonSummaryPath', expectations_path, | |
427 '--writeJsonSummaryPath', output_json_path]) | |
428 expected_summary_dict = { | |
429 "header" : EXPECTED_HEADER_CONTENTS, | |
430 "image-base-gs-url" : None, | |
431 "descriptions" : None, | |
432 "actual-results" : { | |
433 "red.skp": { | |
434 "whole-image": RED_WHOLEIMAGE, | |
435 }, | |
436 "green.skp": { | |
437 "whole-image": GREEN_WHOLEIMAGE, | |
438 } | |
439 } | |
440 } | |
441 self._assert_json_contents(output_json_path, expected_summary_dict) | |
442 | |
443 def test_tiled(self): | |
444 """Generate individual tiles.""" | |
445 output_json_path = os.path.join(self._output_dir, 'actuals.json') | |
446 write_path_dir = self.create_empty_dir( | |
447 path=os.path.join(self._output_dir, 'writePath')) | |
448 self._generate_skps() | |
449 expectations_path = self._create_expectations() | |
450 self._run_render_pictures([ | |
451 '-r', self._input_skp_dir, | |
452 '--bbh', 'grid', '256', '256', | |
453 '--mode', 'tile', '256', '256', | |
454 '--readJsonSummaryPath', expectations_path, | |
455 '--writePath', write_path_dir, | |
456 '--writeJsonSummaryPath', output_json_path]) | |
457 expected_summary_dict = { | |
458 "header" : EXPECTED_HEADER_CONTENTS, | |
459 "image-base-gs-url" : None, | |
460 "descriptions" : None, | |
461 "actual-results" : { | |
462 "red.skp": { | |
463 "tiled-images": RED_TILES, | |
464 }, | |
465 "green.skp": { | |
466 "tiled-images": GREEN_TILES, | |
467 } | |
468 } | |
469 } | |
470 self._assert_json_contents(output_json_path, expected_summary_dict) | |
471 self._assert_directory_contents( | |
472 write_path_dir, | |
473 ['red_skp-tile0.png', 'red_skp-tile1.png', 'red_skp-tile2.png', | |
474 'red_skp-tile3.png', 'red_skp-tile4.png', 'red_skp-tile5.png', | |
475 'green_skp-tile0.png', 'green_skp-tile1.png', 'green_skp-tile2.png', | |
476 'green_skp-tile3.png', 'green_skp-tile4.png', 'green_skp-tile5.png', | |
477 ]) | |
478 | |
479 def test_tiled_mismatches(self): | |
480 """Same as test_tiled, but only write out mismatching images.""" | |
481 output_json_path = os.path.join(self._output_dir, 'actuals.json') | |
482 mismatch_path_dir = self.create_empty_dir( | |
483 path=os.path.join(self._output_dir, 'mismatchPath')) | |
484 self._generate_skps() | |
485 expectations_path = self._create_expectations() | |
486 self._run_render_pictures([ | |
487 '-r', self._input_skp_dir, | |
488 '--bbh', 'grid', '256', '256', | |
489 '--mode', 'tile', '256', '256', | |
490 '--readJsonSummaryPath', expectations_path, | |
491 '--mismatchPath', mismatch_path_dir, | |
492 '--writeJsonSummaryPath', output_json_path]) | |
493 expected_summary_dict = { | |
494 "header" : EXPECTED_HEADER_CONTENTS, | |
495 "image-base-gs-url" : None, | |
496 "descriptions" : None, | |
497 "actual-results" : { | |
498 "red.skp": { | |
499 "tiled-images": RED_TILES, | |
500 }, | |
501 "green.skp": { | |
502 "tiled-images": GREEN_TILES, | |
503 } | |
504 } | |
505 } | |
506 self._assert_json_contents(output_json_path, expected_summary_dict) | |
507 self._assert_directory_contents( | |
508 mismatch_path_dir, | |
509 ['red_skp-tile0.png', 'red_skp-tile1.png', 'red_skp-tile2.png', | |
510 'red_skp-tile3.png', 'red_skp-tile4.png', 'red_skp-tile5.png', | |
511 ]) | |
512 | |
513 def test_tiled_writeChecksumBasedFilenames(self): | |
514 """Same as test_tiled, but with --writeChecksumBasedFilenames.""" | |
515 output_json_path = os.path.join(self._output_dir, 'actuals.json') | |
516 write_path_dir = self.create_empty_dir( | |
517 path=os.path.join(self._output_dir, 'writePath')) | |
518 self._generate_skps() | |
519 self._run_render_pictures(['-r', self._input_skp_dir, | |
520 '--bbh', 'grid', '256', '256', | |
521 '--mode', 'tile', '256', '256', | |
522 '--writeChecksumBasedFilenames', | |
523 '--writePath', write_path_dir, | |
524 '--writeJsonSummaryPath', output_json_path]) | |
525 expected_summary_dict = { | |
526 "header" : EXPECTED_HEADER_CONTENTS, | |
527 "image-base-gs-url" : None, | |
528 "descriptions" : None, | |
529 "actual-results" : { | |
530 "red.skp": { | |
531 # Manually verified these 6 images, all 256x256 tiles, | |
532 # consistent with a tiled version of the 640x400 red rect | |
533 # with black borders. | |
534 "tiled-images": [{ | |
535 "checksumAlgorithm" : "bitmap-64bitMD5", | |
536 "checksumValue" : 5815827069051002745, | |
537 "comparisonResult" : "no-comparison", | |
538 "filepath" : | |
539 "red_skp/bitmap-64bitMD5_5815827069051002745.png", | |
540 }, { | |
541 "checksumAlgorithm" : "bitmap-64bitMD5", | |
542 "checksumValue" : 9323613075234140270, | |
543 "comparisonResult" : "no-comparison", | |
544 "filepath" : | |
545 "red_skp/bitmap-64bitMD5_9323613075234140270.png", | |
546 }, { | |
547 "checksumAlgorithm" : "bitmap-64bitMD5", | |
548 "checksumValue" : 15939355025996362179, | |
549 "comparisonResult" : "no-comparison", | |
550 "filepath" : | |
551 "red_skp/bitmap-64bitMD5_15939355025996362179.png", | |
552 }, { | |
553 "checksumAlgorithm" : "bitmap-64bitMD5", | |
554 "checksumValue" : 649771916797529222, | |
555 "comparisonResult" : "no-comparison", | |
556 "filepath" : | |
557 "red_skp/bitmap-64bitMD5_649771916797529222.png", | |
558 }, { | |
559 "checksumAlgorithm" : "bitmap-64bitMD5", | |
560 "checksumValue" : 8132820002266077288, | |
561 "comparisonResult" : "no-comparison", | |
562 "filepath" : | |
563 "red_skp/bitmap-64bitMD5_8132820002266077288.png", | |
564 }, { | |
565 "checksumAlgorithm" : "bitmap-64bitMD5", | |
566 "checksumValue" : 2406160701181324581, | |
567 "comparisonResult" : "no-comparison", | |
568 "filepath" : | |
569 "red_skp/bitmap-64bitMD5_2406160701181324581.png", | |
570 }], | |
571 }, | |
572 "green.skp": { | |
573 # Manually verified these 6 images, all 256x256 tiles, | |
574 # consistent with a tiled version of the 640x400 green rect | |
575 # with black borders. | |
576 "tiled-images": [{ | |
577 "checksumAlgorithm" : "bitmap-64bitMD5", | |
578 "checksumValue" : 12587324416545178013, | |
579 "comparisonResult" : "no-comparison", | |
580 "filepath" : | |
581 "green_skp/bitmap-64bitMD5_12587324416545178013.png", | |
582 }, { | |
583 "checksumAlgorithm" : "bitmap-64bitMD5", | |
584 "checksumValue" : 7624374914829746293, | |
585 "comparisonResult" : "no-comparison", | |
586 "filepath" : | |
587 "green_skp/bitmap-64bitMD5_7624374914829746293.png", | |
588 }, { | |
589 "checksumAlgorithm" : "bitmap-64bitMD5", | |
590 "checksumValue" : 11866144860997809880, | |
591 "comparisonResult" : "no-comparison", | |
592 "filepath" : | |
593 "green_skp/bitmap-64bitMD5_11866144860997809880.png", | |
594 }, { | |
595 "checksumAlgorithm" : "bitmap-64bitMD5", | |
596 "checksumValue" : 3893392565127823822, | |
597 "comparisonResult" : "no-comparison", | |
598 "filepath" : | |
599 "green_skp/bitmap-64bitMD5_3893392565127823822.png", | |
600 }, { | |
601 "checksumAlgorithm" : "bitmap-64bitMD5", | |
602 "checksumValue" : 2083084978343901738, | |
603 "comparisonResult" : "no-comparison", | |
604 "filepath" : | |
605 "green_skp/bitmap-64bitMD5_2083084978343901738.png", | |
606 }, { | |
607 "checksumAlgorithm" : "bitmap-64bitMD5", | |
608 "checksumValue" : 89620927366502076, | |
609 "comparisonResult" : "no-comparison", | |
610 "filepath" : | |
611 "green_skp/bitmap-64bitMD5_89620927366502076.png", | |
612 }], | |
613 } | |
614 } | |
615 } | |
616 self._assert_json_contents(output_json_path, expected_summary_dict) | |
617 self._assert_directory_contents(write_path_dir, ['red_skp', 'green_skp']) | |
618 self._assert_directory_contents( | |
619 os.path.join(write_path_dir, 'red_skp'), | |
620 ['bitmap-64bitMD5_5815827069051002745.png', | |
621 'bitmap-64bitMD5_9323613075234140270.png', | |
622 'bitmap-64bitMD5_15939355025996362179.png', | |
623 'bitmap-64bitMD5_649771916797529222.png', | |
624 'bitmap-64bitMD5_8132820002266077288.png', | |
625 'bitmap-64bitMD5_2406160701181324581.png']) | |
626 self._assert_directory_contents( | |
627 os.path.join(write_path_dir, 'green_skp'), | |
628 ['bitmap-64bitMD5_12587324416545178013.png', | |
629 'bitmap-64bitMD5_7624374914829746293.png', | |
630 'bitmap-64bitMD5_11866144860997809880.png', | |
631 'bitmap-64bitMD5_3893392565127823822.png', | |
632 'bitmap-64bitMD5_2083084978343901738.png', | |
633 'bitmap-64bitMD5_89620927366502076.png']) | |
634 | |
635 def _run_render_pictures(self, args): | |
636 binary = find_run_binary.find_path_to_program('render_pictures') | |
637 return find_run_binary.run_command( | |
638 [binary, '--config', '8888'] + args) | |
639 | |
640 def _create_expectations(self, missing_some_images=False, | |
641 ignore_some_failures=False, | |
642 rel_path='expectations.json'): | |
643 """Creates expectations JSON file within self._expectations_dir . | |
644 | |
645 Args: | |
646 missing_some_images: (bool) whether to remove expectations for a subset | |
647 of the images | |
648 ignore_some_failures: (bool) whether to ignore some failing tests | |
649 rel_path: (string) relative path within self._expectations_dir to write | |
650 the expectations into | |
651 | |
652 Returns: full path to the expectations file created. | |
653 """ | |
654 expectations_dict = { | |
655 "header" : EXPECTED_HEADER_CONTENTS, | |
656 "descriptions" : None, | |
657 "expected-results" : { | |
658 # red.skp: these should fail the comparison | |
659 "red.skp": { | |
660 "tiled-images": modified_list_of_dicts( | |
661 RED_TILES, {'checksumValue': 11111}), | |
662 "whole-image": modified_dict( | |
663 RED_WHOLEIMAGE, {'checksumValue': 22222}), | |
664 }, | |
665 # green.skp: these should pass the comparison | |
666 "green.skp": { | |
667 "tiled-images": GREEN_TILES, | |
668 "whole-image": GREEN_WHOLEIMAGE, | |
669 } | |
670 } | |
671 } | |
672 if missing_some_images: | |
673 red_subdict = expectations_dict['expected-results']['red.skp'] | |
674 del red_subdict['whole-image'] | |
675 del red_subdict['tiled-images'][-1] | |
676 elif ignore_some_failures: | |
677 red_subdict = expectations_dict['expected-results']['red.skp'] | |
678 red_subdict['whole-image']['ignoreFailure'] = True | |
679 red_subdict['tiled-images'][-1]['ignoreFailure'] = True | |
680 path = os.path.join(self._expectations_dir, rel_path) | |
681 with open(path, 'w') as fh: | |
682 json.dump(expectations_dict, fh) | |
683 return path | |
684 | |
685 def _generate_skps(self): | |
686 """Runs the skpmaker binary to generate files in self._input_skp_dir.""" | |
687 self._run_skpmaker( | |
688 output_path=os.path.join(self._input_skp_dir, 'red.skp'), red=255) | |
689 self._run_skpmaker( | |
690 output_path=os.path.join(self._input_skp_dir, 'green.skp'), green=255) | |
691 | |
692 def _run_skpmaker(self, output_path, red=0, green=0, blue=0, | |
693 width=640, height=400): | |
694 """Runs the skpmaker binary to generate SKP with known characteristics. | |
695 | |
696 Args: | |
697 output_path: Filepath to write the SKP into. | |
698 red: Value of red color channel in image, 0-255. | |
699 green: Value of green color channel in image, 0-255. | |
700 blue: Value of blue color channel in image, 0-255. | |
701 width: Width of canvas to create. | |
702 height: Height of canvas to create. | |
703 """ | |
704 binary = find_run_binary.find_path_to_program('skpmaker') | |
705 return find_run_binary.run_command([ | |
706 binary, | |
707 '--red', str(red), | |
708 '--green', str(green), | |
709 '--blue', str(blue), | |
710 '--width', str(width), | |
711 '--height', str(height), | |
712 '--writePath', str(output_path), | |
713 ]) | |
714 | |
715 def _assert_directory_contents(self, dir_path, expected_filenames): | |
716 """Asserts that files found in a dir are identical to expected_filenames. | |
717 | |
718 Args: | |
719 dir_path: Path to a directory on local disk. | |
720 expected_filenames: Set containing the expected filenames within the dir. | |
721 | |
722 Raises: | |
723 AssertionError: contents of the directory are not identical to | |
724 expected_filenames. | |
725 """ | |
726 self.assertEqual(set(os.listdir(dir_path)), set(expected_filenames)) | |
727 | |
728 def _assert_json_contents(self, json_path, expected_dict): | |
729 """Asserts that contents of a JSON file are identical to expected_dict. | |
730 | |
731 Args: | |
732 json_path: Path to a JSON file. | |
733 expected_dict: Dictionary indicating the expected contents of the JSON | |
734 file. | |
735 | |
736 Raises: | |
737 AssertionError: contents of the JSON file are not identical to | |
738 expected_dict. | |
739 """ | |
740 prettyprinted_expected_dict = json.dumps(expected_dict, sort_keys=True, | |
741 indent=2) | |
742 with open(json_path, 'r') as fh: | |
743 prettyprinted_json_dict = json.dumps(json.load(fh), sort_keys=True, | |
744 indent=2) | |
745 self.assertMultiLineEqual(prettyprinted_expected_dict, | |
746 prettyprinted_json_dict) | |
747 | |
748 | |
749 def main(): | |
750 base_unittest.main(RenderPicturesTest) | |
751 | |
752 | |
753 if __name__ == '__main__': | |
754 main() | |
OLD | NEW |