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 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 |