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 Compare results of two render_pictures runs. | 9 Compare results of two render_pictures runs. |
10 | 10 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
54 COLUMN__TILED_OR_WHOLE, | 54 COLUMN__TILED_OR_WHOLE, |
55 COLUMN__TILENUM, | 55 COLUMN__TILENUM, |
56 ] | 56 ] |
57 | 57 |
58 # A special "repo:" URL type that we use to refer to Skia repo contents. | 58 # A special "repo:" URL type that we use to refer to Skia repo contents. |
59 # (Useful for comparing against expectations files we store in our repo.) | 59 # (Useful for comparing against expectations files we store in our repo.) |
60 REPO_URL_PREFIX = 'repo:' | 60 REPO_URL_PREFIX = 'repo:' |
61 REPO_BASEPATH = os.path.abspath(os.path.join( | 61 REPO_BASEPATH = os.path.abspath(os.path.join( |
62 os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir)) | 62 os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir)) |
63 | 63 |
64 # Which sections within a JSON summary file can contain results. | |
65 ALLOWED_SECTION_NAMES = [ | |
66 gm_json.JSONKEY_ACTUALRESULTS, | |
67 gm_json.JSONKEY_EXPECTEDRESULTS, | |
68 ] | |
69 | |
64 | 70 |
65 class RenderedPicturesComparisons(results.BaseComparisons): | 71 class RenderedPicturesComparisons(results.BaseComparisons): |
66 """Loads results from multiple render_pictures runs into an ImagePairSet. | 72 """Loads results from multiple render_pictures runs into an ImagePairSet. |
67 """ | 73 """ |
68 | 74 |
69 def __init__(self, setA_dirs, setB_dirs, image_diff_db, | 75 def __init__(self, |
70 image_base_gs_url=DEFAULT_IMAGE_BASE_GS_URL, | 76 setA_dirs, setB_dirs, |
epoger
2014/08/07 17:27:36
Added some extra linefeeds here to visually group
rmistry
2014/08/07 18:57:05
makes sense to me.
| |
71 diff_base_url=None, setA_label='setA', | 77 setA_section, setB_section, |
72 setB_label='setB', gs=None, | 78 image_diff_db, |
73 truncate_results=False, prefetch_only=False, | 79 image_base_gs_url=DEFAULT_IMAGE_BASE_GS_URL, diff_base_url=None, |
80 setA_label='setA', setB_label='setB', | |
81 gs=None, truncate_results=False, prefetch_only=False, | |
74 download_all_images=False): | 82 download_all_images=False): |
75 """Constructor: downloads images and generates diffs. | 83 """Constructor: downloads images and generates diffs. |
76 | 84 |
77 Once the object has been created (which may take a while), you can call its | 85 Once the object has been created (which may take a while), you can call its |
78 get_packaged_results_of_type() method to quickly retrieve the results... | 86 get_packaged_results_of_type() method to quickly retrieve the results... |
79 unless you have set prefetch_only to True, in which case we will | 87 unless you have set prefetch_only to True, in which case we will |
80 asynchronously warm up the ImageDiffDB cache but not fill in self._results. | 88 asynchronously warm up the ImageDiffDB cache but not fill in self._results. |
81 | 89 |
82 Args: | 90 Args: |
83 setA_dirs: list of root directories to copy all JSON summaries from, | 91 setA_dirs: list of root directories to copy all JSON summaries from, |
84 and to use as setA within the comparisons. These directories may be | 92 and to use as setA within the comparisons. These directories may be |
85 gs:// URLs, special "repo:" URLs, or local filepaths. | 93 gs:// URLs, special "repo:" URLs, or local filepaths. |
86 setB_dirs: list of root directories to copy all JSON summaries from, | 94 setB_dirs: list of root directories to copy all JSON summaries from, |
87 and to use as setB within the comparisons. These directories may be | 95 and to use as setB within the comparisons. These directories may be |
88 gs:// URLs, special "repo:" URLs, or local filepaths. | 96 gs:// URLs, special "repo:" URLs, or local filepaths. |
97 setA_section: which section within setA to examine; must be one of | |
98 ALLOWED_SECTION_NAMES | |
99 setB_section: which section within setB to examine; must be one of | |
100 ALLOWED_SECTION_NAMES | |
89 image_diff_db: ImageDiffDB instance | 101 image_diff_db: ImageDiffDB instance |
90 image_base_gs_url: "gs://" URL pointing at the Google Storage bucket/dir | 102 image_base_gs_url: "gs://" URL pointing at the Google Storage bucket/dir |
91 under which all render_pictures result images can | 103 under which all render_pictures result images can |
92 be found; this will be used to read images for comparison within | 104 be found; this will be used to read images for comparison within |
93 this code, and included in the ImagePairSet (as an HTTP URL) so its | 105 this code, and included in the ImagePairSet (as an HTTP URL) so its |
94 consumers know where to download the images from | 106 consumers know where to download the images from |
95 diff_base_url: base URL within which the client should look for diff | 107 diff_base_url: base URL within which the client should look for diff |
96 images; if not specified, defaults to a "file:///" URL representation | 108 images; if not specified, defaults to a "file:///" URL representation |
97 of image_diff_db's storage_root | 109 of image_diff_db's storage_root |
98 setA_label: description to use for results in setA | 110 setA_label: description to use for results in setA |
(...skipping 26 matching lines...) Expand all Loading... | |
125 tempdir = tempfile.mkdtemp() | 137 tempdir = tempfile.mkdtemp() |
126 try: | 138 try: |
127 setA_root = os.path.join(tempdir, 'setA') | 139 setA_root = os.path.join(tempdir, 'setA') |
128 setB_root = os.path.join(tempdir, 'setB') | 140 setB_root = os.path.join(tempdir, 'setB') |
129 for source_dir in setA_dirs: | 141 for source_dir in setA_dirs: |
130 self._copy_dir_contents(source_dir=source_dir, dest_dir=setA_root) | 142 self._copy_dir_contents(source_dir=source_dir, dest_dir=setA_root) |
131 for source_dir in setB_dirs: | 143 for source_dir in setB_dirs: |
132 self._copy_dir_contents(source_dir=source_dir, dest_dir=setB_root) | 144 self._copy_dir_contents(source_dir=source_dir, dest_dir=setB_root) |
133 | 145 |
134 time_start = int(time.time()) | 146 time_start = int(time.time()) |
135 # TODO(epoger): For now, this assumes that we are always comparing two | |
136 # sets of actual results, not actuals vs expectations. Allow the user | |
137 # to control this. | |
138 self._results = self._load_result_pairs( | 147 self._results = self._load_result_pairs( |
139 setA_root=setA_root, setA_section=gm_json.JSONKEY_ACTUALRESULTS, | 148 setA_root=setA_root, setA_section=setA_section, |
140 setB_root=setB_root, setB_section=gm_json.JSONKEY_ACTUALRESULTS) | 149 setB_root=setB_root, setB_section=setB_section) |
141 if self._results: | 150 if self._results: |
142 self._timestamp = int(time.time()) | 151 self._timestamp = int(time.time()) |
143 logging.info('Number of download file collisions: %s' % | 152 logging.info('Number of download file collisions: %s' % |
144 imagediffdb.global_file_collisions) | 153 imagediffdb.global_file_collisions) |
145 logging.info('Results complete; took %d seconds.' % | 154 logging.info('Results complete; took %d seconds.' % |
146 (self._timestamp - time_start)) | 155 (self._timestamp - time_start)) |
147 finally: | 156 finally: |
148 shutil.rmtree(tempdir) | 157 shutil.rmtree(tempdir) |
149 | 158 |
150 def _load_result_pairs(self, setA_root, setA_section, setB_root, | 159 def _load_result_pairs(self, setA_root, setA_section, setB_root, |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
224 dictA_results, None, | 233 dictA_results, None, |
225 skp_name, gm_json.JSONKEY_SOURCE_WHOLEIMAGE) | 234 skp_name, gm_json.JSONKEY_SOURCE_WHOLEIMAGE) |
226 whole_image_B = self.get_default( | 235 whole_image_B = self.get_default( |
227 dictB_results, None, | 236 dictB_results, None, |
228 skp_name, gm_json.JSONKEY_SOURCE_WHOLEIMAGE) | 237 skp_name, gm_json.JSONKEY_SOURCE_WHOLEIMAGE) |
229 imagepairs_for_this_skp.append(self._create_image_pair( | 238 imagepairs_for_this_skp.append(self._create_image_pair( |
230 image_dict_A=whole_image_A, image_dict_B=whole_image_B, | 239 image_dict_A=whole_image_A, image_dict_B=whole_image_B, |
231 source_skp_name=skp_name, tilenum=None)) | 240 source_skp_name=skp_name, tilenum=None)) |
232 | 241 |
233 tiled_images_A = self.get_default( | 242 tiled_images_A = self.get_default( |
234 dictA_results, None, | 243 dictA_results, [], |
235 skp_name, gm_json.JSONKEY_SOURCE_TILEDIMAGES) | 244 skp_name, gm_json.JSONKEY_SOURCE_TILEDIMAGES) |
236 tiled_images_B = self.get_default( | 245 tiled_images_B = self.get_default( |
237 dictB_results, None, | 246 dictB_results, [], |
238 skp_name, gm_json.JSONKEY_SOURCE_TILEDIMAGES) | 247 skp_name, gm_json.JSONKEY_SOURCE_TILEDIMAGES) |
239 # TODO(epoger): Report an error if we find tiles for A but not B? | 248 if tiled_images_A or tiled_images_B: |
epoger
2014/08/07 17:27:36
Made these changes so that empty expectations show
rmistry
2014/08/07 18:57:05
Acknowledged.
| |
240 if tiled_images_A and tiled_images_B: | 249 num_tiles_A = len(tiled_images_A) |
241 # TODO(epoger): Report an error if we find a different number of tiles | 250 num_tiles_B = len(tiled_images_B) |
242 # for A and B? | 251 num_tiles = max(num_tiles_A, num_tiles_B) |
243 num_tiles = len(tiled_images_A) | |
244 for tile_num in range(num_tiles): | 252 for tile_num in range(num_tiles): |
245 imagepairs_for_this_skp.append(self._create_image_pair( | 253 imagepairs_for_this_skp.append(self._create_image_pair( |
246 image_dict_A=tiled_images_A[tile_num], | 254 image_dict_A=(tiled_images_A[tile_num] |
247 image_dict_B=tiled_images_B[tile_num], | 255 if tile_num < num_tiles_A else None), |
256 image_dict_B=(tiled_images_B[tile_num] | |
257 if tile_num < num_tiles_B else None), | |
248 source_skp_name=skp_name, tilenum=tile_num)) | 258 source_skp_name=skp_name, tilenum=tile_num)) |
249 | 259 |
250 for one_imagepair in imagepairs_for_this_skp: | 260 for one_imagepair in imagepairs_for_this_skp: |
251 if one_imagepair: | 261 if one_imagepair: |
252 all_image_pairs.add_image_pair(one_imagepair) | 262 all_image_pairs.add_image_pair(one_imagepair) |
253 result_type = one_imagepair.extra_columns_dict\ | 263 result_type = one_imagepair.extra_columns_dict\ |
254 [COLUMN__RESULT_TYPE] | 264 [COLUMN__RESULT_TYPE] |
255 if result_type != results.KEY__RESULT_TYPE__SUCCEEDED: | 265 if result_type != results.KEY__RESULT_TYPE__SUCCEEDED: |
256 failing_image_pairs.add_image_pair(one_imagepair) | 266 failing_image_pairs.add_image_pair(one_imagepair) |
257 | 267 |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 """ | 377 """ |
368 if gs_utils.GSUtils.is_gs_url(source_dir): | 378 if gs_utils.GSUtils.is_gs_url(source_dir): |
369 (bucket, path) = gs_utils.GSUtils.split_gs_url(source_dir) | 379 (bucket, path) = gs_utils.GSUtils.split_gs_url(source_dir) |
370 self._gs.download_dir_contents(source_bucket=bucket, source_dir=path, | 380 self._gs.download_dir_contents(source_bucket=bucket, source_dir=path, |
371 dest_dir=dest_dir) | 381 dest_dir=dest_dir) |
372 elif source_dir.lower().startswith(REPO_URL_PREFIX): | 382 elif source_dir.lower().startswith(REPO_URL_PREFIX): |
373 repo_dir = os.path.join(REPO_BASEPATH, source_dir[len(REPO_URL_PREFIX):]) | 383 repo_dir = os.path.join(REPO_BASEPATH, source_dir[len(REPO_URL_PREFIX):]) |
374 shutil.copytree(repo_dir, dest_dir) | 384 shutil.copytree(repo_dir, dest_dir) |
375 else: | 385 else: |
376 shutil.copytree(source_dir, dest_dir) | 386 shutil.copytree(source_dir, dest_dir) |
OLD | NEW |