Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 | 2 |
| 3 """ | 3 """ |
| 4 Copyright 2014 Google Inc. | 4 Copyright 2014 Google Inc. |
| 5 | 5 |
| 6 Use of this source code is governed by a BSD-style license that can be | 6 Use of this source code is governed by a BSD-style license that can be |
| 7 found in the LICENSE file. | 7 found in the LICENSE file. |
| 8 | 8 |
| 9 Test the render_pictures binary. | 9 Test the render_pictures binary. |
| 10 """ | 10 """ |
| 11 | 11 |
| 12 # System-level imports | 12 # System-level imports |
| 13 import json | 13 import json |
| 14 import os | 14 import os |
| 15 import shutil | 15 import shutil |
| 16 import tempfile | 16 import tempfile |
| 17 | 17 |
| 18 # Imports from within Skia | 18 # Imports from within Skia |
| 19 import base_unittest | 19 import base_unittest |
| 20 | 20 |
| 21 # Maximum length of text diffs to show when tests fail | 21 # Maximum length of text diffs to show when tests fail |
| 22 MAX_DIFF_LENGTH = 30000 | 22 MAX_DIFF_LENGTH = 30000 |
| 23 | 23 |
| 24 | 24 |
| 25 class RenderPicturesTest(base_unittest.TestCase): | 25 class RenderPicturesTest(base_unittest.TestCase): |
| 26 | 26 |
| 27 def setUp(self): | 27 def setUp(self): |
| 28 self._input_skp_dir = tempfile.mkdtemp() | |
| 28 self._temp_dir = tempfile.mkdtemp() | 29 self._temp_dir = tempfile.mkdtemp() |
| 29 self.maxDiff = MAX_DIFF_LENGTH | 30 self.maxDiff = MAX_DIFF_LENGTH |
| 30 | 31 |
| 31 def tearDown(self): | 32 def tearDown(self): |
| 33 shutil.rmtree(self._input_skp_dir) | |
| 32 shutil.rmtree(self._temp_dir) | 34 shutil.rmtree(self._temp_dir) |
| 33 | 35 |
| 34 def test_tiled_whole_image_no_comparison(self): | 36 def test_tiled_whole_image(self): |
| 35 """Run render_pictures with tiles and --writeWholeImage flag.""" | 37 """Run render_pictures with tiles and --writeWholeImage flag.""" |
| 36 input_skp_path = os.path.join(self._temp_dir, 'input.skp') | |
| 37 output_json_path = os.path.join(self._temp_dir, 'output.json') | 38 output_json_path = os.path.join(self._temp_dir, 'output.json') |
| 38 self._run_skpmaker(['--writePath', input_skp_path]) | 39 self._generate_skps() |
| 39 self._run_render_pictures(['-r', input_skp_path, | 40 self._run_render_pictures(['-r', self._input_skp_dir, |
| 40 '--bbh', 'grid', '256', '256', | 41 '--bbh', 'grid', '256', '256', |
| 41 '--mode', 'tile', '256', '256', | 42 '--mode', 'tile', '256', '256', |
| 42 '--writeJsonSummaryPath', output_json_path, | 43 '--writeJsonSummaryPath', output_json_path, |
| 43 '--writeWholeImage']) | 44 '--writeWholeImage']) |
| 44 expected_summary_dict = { | 45 expected_summary_dict = { |
| 45 "actual-results" : { | 46 "actual-results" : { |
| 46 "no-comparison" : { | 47 "no-comparison" : { |
| 47 # Manually verified: 640x400 red rectangle with black border | 48 # Manually verified: 640x400 red rectangle with black border |
| 48 "input.png" : [ "bitmap-64bitMD5", 11092453015575919668 ] | 49 "red.png" : [ "bitmap-64bitMD5", 11092453015575919668 ], |
| 50 # Manually verified: 640x400 green rectangle with black border | |
| 51 "green.png" : [ "bitmap-64bitMD5", 8891695120562235492 ], | |
| 49 } | 52 } |
| 50 } | 53 } |
| 51 } | 54 } |
| 52 self._assert_json_contents(output_json_path, expected_summary_dict) | 55 self._assert_json_contents(output_json_path, expected_summary_dict) |
| 53 | 56 |
| 54 def test_untiled_no_comparison(self): | 57 def test_untiled(self): |
| 55 """Run without tiles.""" | 58 """Run without tiles.""" |
| 56 input_skp_path = os.path.join(self._temp_dir, 'input.skp') | |
| 57 output_json_path = os.path.join(self._temp_dir, 'output.json') | 59 output_json_path = os.path.join(self._temp_dir, 'output.json') |
| 58 self._run_skpmaker(['--writePath', input_skp_path]) | 60 self._generate_skps() |
| 59 self._run_render_pictures(['-r', input_skp_path, | 61 self._run_render_pictures(['-r', self._input_skp_dir, |
| 60 '--writePath', self._temp_dir, | 62 '--writePath', self._temp_dir, |
| 61 '--writeJsonSummaryPath', output_json_path]) | 63 '--writeJsonSummaryPath', output_json_path]) |
| 62 expected_summary_dict = { | 64 expected_summary_dict = { |
| 63 "actual-results" : { | 65 "actual-results" : { |
| 64 "no-comparison" : { | 66 "no-comparison" : { |
| 65 # Manually verified: 640x400 red rectangle with black border | 67 # Manually verified: 640x400 red rectangle with black border |
| 66 "input.png" : ["bitmap-64bitMD5", 11092453015575919668], | 68 "red.png" : ["bitmap-64bitMD5", 11092453015575919668], |
| 69 # Manually verified: 640x400 green rectangle with black border | |
| 70 "green.png" : ["bitmap-64bitMD5", 8891695120562235492], | |
| 67 } | 71 } |
| 68 } | 72 } |
| 69 } | 73 } |
| 70 self._assert_json_contents(output_json_path, expected_summary_dict) | 74 self._assert_json_contents(output_json_path, expected_summary_dict) |
| 71 | 75 |
| 72 def test_validate(self): | 76 def test_untiled_validate(self): |
| 73 """Same as test_untiled_no_comparison, but with --validate. | 77 """Same as test_untiled, but with --validate. |
| 74 | 78 |
| 75 TODO(epoger): This test generates undesired results! The call | 79 TODO(epoger): This test generates undesired results! The call |
| 76 to render_pictures should succeed, and generate the same output as | 80 to render_pictures should succeed, and generate the same output as |
| 77 test_untiled_no_comparison. | 81 test_untiled. |
| 78 See https://code.google.com/p/skia/issues/detail?id=2044 ('render_pictures: | 82 See https://code.google.com/p/skia/issues/detail?id=2044 ('render_pictures: |
| 79 --validate fails') | 83 --validate fails') |
| 80 """ | 84 """ |
| 81 input_skp_path = os.path.join(self._temp_dir, 'input.skp') | |
| 82 output_json_path = os.path.join(self._temp_dir, 'output.json') | 85 output_json_path = os.path.join(self._temp_dir, 'output.json') |
| 83 self._run_skpmaker(['--writePath', input_skp_path]) | 86 self._generate_skps() |
| 84 with self.assertRaises(Exception): | 87 with self.assertRaises(Exception): |
| 85 self._run_render_pictures(['-r', input_skp_path, | 88 self._run_render_pictures(['-r', self._input_skp_dir, |
| 86 '--validate', | 89 '--validate', |
| 87 '--writePath', self._temp_dir, | 90 '--writePath', self._temp_dir, |
| 88 '--writeJsonSummaryPath', output_json_path]) | 91 '--writeJsonSummaryPath', output_json_path]) |
| 89 | 92 |
| 90 def test_without_writePath(self): | 93 def test_untiled_without_writePath(self): |
| 91 """Same as test_untiled_no_comparison, but without --writePath. | 94 """Same as test_untiled, but without --writePath. |
| 92 | 95 |
| 93 TODO(epoger): This test generates undesired results! | 96 TODO(epoger): This test generates undesired results! |
| 94 See https://code.google.com/p/skia/issues/detail?id=2043 ('render_pictures: | 97 See https://code.google.com/p/skia/issues/detail?id=2043 ('render_pictures: |
| 95 --writeJsonSummaryPath fails unless --writePath is specified') | 98 --writeJsonSummaryPath fails unless --writePath is specified') |
| 96 """ | 99 """ |
| 97 input_skp_path = os.path.join(self._temp_dir, 'input.skp') | |
| 98 output_json_path = os.path.join(self._temp_dir, 'output.json') | 100 output_json_path = os.path.join(self._temp_dir, 'output.json') |
| 99 self._run_skpmaker(['--writePath', input_skp_path]) | 101 self._generate_skps() |
| 100 self._run_render_pictures(['-r', input_skp_path, | 102 self._run_render_pictures(['-r', self._input_skp_dir, |
| 101 '--writeJsonSummaryPath', output_json_path]) | 103 '--writeJsonSummaryPath', output_json_path]) |
| 102 expected_summary_dict = { | 104 expected_summary_dict = { |
| 103 "actual-results" : { | 105 "actual-results" : { |
| 104 "no-comparison" : None, | 106 "no-comparison" : None, |
| 105 } | 107 } |
| 106 } | 108 } |
| 107 self._assert_json_contents(output_json_path, expected_summary_dict) | 109 self._assert_json_contents(output_json_path, expected_summary_dict) |
| 108 | 110 |
| 109 def test_tiled_no_comparison(self): | 111 def test_tiled(self): |
| 110 """Generate individual tiles.""" | 112 """Generate individual tiles.""" |
| 111 input_skp_path = os.path.join(self._temp_dir, 'input.skp') | |
| 112 output_json_path = os.path.join(self._temp_dir, 'output.json') | 113 output_json_path = os.path.join(self._temp_dir, 'output.json') |
| 113 self._run_skpmaker(['--writePath', input_skp_path]) | 114 self._generate_skps() |
| 114 self._run_render_pictures(['-r', input_skp_path, | 115 self._run_render_pictures(['-r', self._input_skp_dir, |
| 115 '--bbh', 'grid', '256', '256', | 116 '--bbh', 'grid', '256', '256', |
| 116 '--mode', 'tile', '256', '256', | 117 '--mode', 'tile', '256', '256', |
| 117 '--writePath', self._temp_dir, | 118 '--writePath', self._temp_dir, |
| 118 '--writeJsonSummaryPath', output_json_path]) | 119 '--writeJsonSummaryPath', output_json_path]) |
| 119 expected_summary_dict = { | 120 expected_summary_dict = { |
| 120 "actual-results" : { | 121 "actual-results" : { |
| 121 "no-comparison" : { | 122 "no-comparison" : { |
| 122 # Manually verified these 6 images, all 256x256 tiles, | 123 # Manually verified these 6 images, all 256x256 tiles, |
| 123 # consistent with a tiled version of the 640x400 red rect | 124 # consistent with a tiled version of the 640x400 red rect |
| 124 # with black borders. | 125 # with black borders. |
| 125 "input0.png" : ["bitmap-64bitMD5", 5815827069051002745], | 126 "red0.png" : ["bitmap-64bitMD5", 5815827069051002745], |
| 126 "input1.png" : ["bitmap-64bitMD5", 9323613075234140270], | 127 "red1.png" : ["bitmap-64bitMD5", 9323613075234140270], |
| 127 "input2.png" : ["bitmap-64bitMD5", 16670399404877552232], | 128 "red2.png" : ["bitmap-64bitMD5", 16670399404877552232], |
| 128 "input3.png" : ["bitmap-64bitMD5", 2507897274083364964], | 129 "red3.png" : ["bitmap-64bitMD5", 2507897274083364964], |
| 129 "input4.png" : ["bitmap-64bitMD5", 7325267995523877959], | 130 "red4.png" : ["bitmap-64bitMD5", 7325267995523877959], |
| 130 "input5.png" : ["bitmap-64bitMD5", 2181381724594493116], | 131 "red5.png" : ["bitmap-64bitMD5", 2181381724594493116], |
| 132 # Manually verified these 6 images, all 256x256 tiles, | |
| 133 # consistent with a tiled version of the 640x400 green rect | |
| 134 # with black borders. | |
| 135 "green0.png" : ["bitmap-64bitMD5", 12587324416545178013], | |
| 136 "green1.png" : ["bitmap-64bitMD5", 7624374914829746293], | |
| 137 "green2.png" : ["bitmap-64bitMD5", 5686489729535631913], | |
| 138 "green3.png" : ["bitmap-64bitMD5", 7980646035555096146], | |
| 139 "green4.png" : ["bitmap-64bitMD5", 17817086664365875131], | |
| 140 "green5.png" : ["bitmap-64bitMD5", 10673669813016809363], | |
| 131 } | 141 } |
| 132 } | 142 } |
| 133 } | 143 } |
| 134 self._assert_json_contents(output_json_path, expected_summary_dict) | 144 self._assert_json_contents(output_json_path, expected_summary_dict) |
| 135 | 145 |
| 136 def _run_render_pictures(self, args): | 146 def _run_render_pictures(self, args): |
| 137 binary = self.find_path_to_program('render_pictures') | 147 binary = self.find_path_to_program('render_pictures') |
| 138 return self.run_command([binary, | 148 return self.run_command([binary, |
| 139 '--clone', '1', | 149 '--clone', '1', |
| 140 '--config', '8888', | 150 '--config', '8888', |
| 141 ] + args) | 151 ] + args) |
| 142 | 152 |
| 143 def _run_skpmaker(self, args): | 153 def _generate_skps(self): |
| 154 """Runs the skpmaker binary to generate files in self._input_skp_dir.""" | |
| 155 self._run_skpmaker( | |
| 156 output_path=os.path.join(self._input_skp_dir, 'red.skp'), red=255) | |
|
borenet
2014/03/12 14:03:50
Nit: shouldn't address a positional parameter by n
epoger
2014/03/12 18:05:30
Is that in the style guide? I prefer to *always*
borenet
2014/03/12 18:38:52
I think I share that preference, but I've been tol
| |
| 157 self._run_skpmaker( | |
| 158 output_path=os.path.join(self._input_skp_dir, 'green.skp'), green=255) | |
| 159 | |
| 160 def _run_skpmaker(self, output_path, red=0, green=0, blue=0, | |
| 161 width=640, height=400): | |
| 162 """Runs the skpmaker binary to generate SKP with known characteristics. | |
| 163 | |
| 164 Args: | |
| 165 output_path: Filepath to write the SKP into. | |
| 166 red: Value of red color channel in image, 0-255. | |
| 167 green: Value of green color channel in image, 0-255. | |
| 168 blue: Value of blue color channel in image, 0-255. | |
| 169 width: Width of canvas to create. | |
| 170 height: Height of canvas to create. | |
| 171 """ | |
| 144 binary = self.find_path_to_program('skpmaker') | 172 binary = self.find_path_to_program('skpmaker') |
| 145 return self.run_command([binary, | 173 return self.run_command([binary, |
| 146 '--red', '255', | 174 '--red', str(red), |
| 147 '--green', '0', | 175 '--green', str(green), |
| 148 '--blue', '0', | 176 '--blue', str(blue), |
| 149 '--width', '640', | 177 '--width', str(width), |
| 150 '--height', '400', | 178 '--height', str(height), |
| 151 ] + args) | 179 '--writePath', str(output_path), |
| 180 ]) | |
| 152 | 181 |
| 153 def _assert_json_contents(self, json_path, expected_dict): | 182 def _assert_json_contents(self, json_path, expected_dict): |
| 154 """Asserts that contents of a JSON file are identical to expected_dict. | 183 """Asserts that contents of a JSON file are identical to expected_dict. |
| 155 | 184 |
| 156 Args: | 185 Args: |
| 157 json_path: Path to a JSON file. | 186 json_path: Path to a JSON file. |
| 158 expected_dict: Dictionary indicating the expected contents of the JSON | 187 expected_dict: Dictionary indicating the expected contents of the JSON |
| 159 file. | 188 file. |
| 160 | 189 |
| 161 Raises: | 190 Raises: |
| 162 AssertionError: contents of the JSON file are not identical to | 191 AssertionError: contents of the JSON file are not identical to |
| 163 expected_dict. | 192 expected_dict. |
| 164 """ | 193 """ |
| 165 file_contents = open(json_path, 'r').read() | 194 file_contents = open(json_path, 'r').read() |
| 166 actual_dict = json.loads(file_contents) | 195 actual_dict = json.loads(file_contents) |
| 167 self.assertEqual(actual_dict, expected_dict) | 196 self.assertEqual(actual_dict, expected_dict) |
| 168 | 197 |
| 169 | 198 |
| 170 def main(): | 199 def main(): |
| 171 base_unittest.main(RenderPicturesTest) | 200 base_unittest.main(RenderPicturesTest) |
| 172 | 201 |
| 173 | 202 |
| 174 if __name__ == '__main__': | 203 if __name__ == '__main__': |
| 175 main() | 204 main() |
| OLD | NEW |