Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Side by Side Diff: gm/rebaseline_server/compare_rendered_pictures.py

Issue 453433004: rebaseline_server: allow live queries to examine JSONKEY_EXPECTEDRESULTS or JSONKEY_ACTUALRESULTS (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: create ALLOWED_SECTION_NAMES Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698