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

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

Issue 379563005: rebaseline_server: cache results in long-running ImageDiffDB instance (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 5 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 2013 Google Inc. 4 Copyright 2013 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 Repackage expected/actual GM results as needed by our HTML rebaseline viewer. 9 Repackage expected/actual GM results as needed by our HTML rebaseline viewer.
10 """ 10 """
11 11
12 # System-level imports 12 # System-level imports
13 import argparse 13 import argparse
14 import fnmatch 14 import fnmatch
15 import json
16 import logging 15 import logging
17 import os 16 import os
18 import re
19 import sys
20 import time 17 import time
21 18
19 # Must fix up PYTHONPATH before importing from within Skia
20 # pylint: disable=W0611
21 import fix_pythonpath
22 # pylint: enable=W0611
23
22 # Imports from within Skia 24 # Imports from within Skia
23 import fix_pythonpath # must do this first
24 from pyutils import url_utils 25 from pyutils import url_utils
25 import gm_json 26 import gm_json
26 import imagediffdb 27 import imagediffdb
27 import imagepair 28 import imagepair
28 import imagepairset 29 import imagepairset
29 import results 30 import results
30 31
31 EXPECTATION_FIELDS_PASSED_THRU_VERBATIM = [ 32 EXPECTATION_FIELDS_PASSED_THRU_VERBATIM = [
32 results.KEY__EXPECTATIONS__BUGS, 33 results.KEY__EXPECTATIONS__BUGS,
33 results.KEY__EXPECTATIONS__IGNOREFAILURE, 34 results.KEY__EXPECTATIONS__IGNOREFAILURE,
34 results.KEY__EXPECTATIONS__REVIEWED, 35 results.KEY__EXPECTATIONS__REVIEWED,
35 ] 36 ]
36 TRUNK_DIRECTORY = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) 37 TRUNK_DIRECTORY = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
37 DEFAULT_EXPECTATIONS_DIR = os.path.join(TRUNK_DIRECTORY, 'expectations', 'gm') 38 DEFAULT_EXPECTATIONS_DIR = os.path.join(TRUNK_DIRECTORY, 'expectations', 'gm')
38 DEFAULT_IGNORE_FAILURES_FILE = 'ignored-tests.txt' 39 DEFAULT_IGNORE_FAILURES_FILE = 'ignored-tests.txt'
39 40
40 IMAGEPAIR_SET_DESCRIPTIONS = ('expected image', 'actual image') 41 IMAGEPAIR_SET_DESCRIPTIONS = ('expected image', 'actual image')
41 42
42 43
43 class ExpectationComparisons(results.BaseComparisons): 44 class ExpectationComparisons(results.BaseComparisons):
44 """Loads actual and expected GM results into an ImagePairSet. 45 """Loads actual and expected GM results into an ImagePairSet.
45 46
46 Loads actual and expected results from all builders, except for those skipped 47 Loads actual and expected results from all builders, except for those skipped
47 by _ignore_builder(). 48 by _ignore_builder().
48 49
49 Once this object has been constructed, the results (in self._results[]) 50 Once this object has been constructed, the results (in self._results[])
50 are immutable. If you want to update the results based on updated JSON 51 are immutable. If you want to update the results based on updated JSON
51 file contents, you will need to create a new ExpectationComparisons object.""" 52 file contents, you will need to create a new ExpectationComparisons object."""
52 53
53 def __init__(self, actuals_root=results.DEFAULT_ACTUALS_DIR, 54 def __init__(self, image_diff_db, actuals_root=results.DEFAULT_ACTUALS_DIR,
54 expected_root=DEFAULT_EXPECTATIONS_DIR, 55 expected_root=DEFAULT_EXPECTATIONS_DIR,
55 ignore_failures_file=DEFAULT_IGNORE_FAILURES_FILE, 56 ignore_failures_file=DEFAULT_IGNORE_FAILURES_FILE,
56 generated_images_root=results.DEFAULT_GENERATED_IMAGES_ROOT,
57 diff_base_url=None, builder_regex_list=None): 57 diff_base_url=None, builder_regex_list=None):
58 """ 58 """
59 Args: 59 Args:
60 image_diff_db: instance of ImageDiffDB we use to cache the image diffs
60 actuals_root: root directory containing all actual-results.json files 61 actuals_root: root directory containing all actual-results.json files
61 expected_root: root directory containing all expected-results.json files 62 expected_root: root directory containing all expected-results.json files
62 ignore_failures_file: if a file with this name is found within 63 ignore_failures_file: if a file with this name is found within
63 expected_root, ignore failures for any tests listed in the file 64 expected_root, ignore failures for any tests listed in the file
64 generated_images_root: directory within which to create all pixel diffs;
65 if this directory does not yet exist, it will be created
66 diff_base_url: base URL within which the client should look for diff 65 diff_base_url: base URL within which the client should look for diff
67 images; if not specified, defaults to a "file:///" URL representation 66 images; if not specified, defaults to a "file:///" URL representation
68 of generated_images_root 67 of image_diff_db's storage_root
69 builder_regex_list: List of regular expressions specifying which builders 68 builder_regex_list: List of regular expressions specifying which builders
70 we will process. If None, process all builders. 69 we will process. If None, process all builders.
71 """ 70 """
72 time_start = int(time.time()) 71 time_start = int(time.time())
73 if builder_regex_list != None: 72 if builder_regex_list != None:
74 self.set_match_builders_pattern_list(builder_regex_list) 73 self.set_match_builders_pattern_list(builder_regex_list)
75 self._image_diff_db = imagediffdb.ImageDiffDB(generated_images_root) 74 self._image_diff_db = image_diff_db
76 self._diff_base_url = ( 75 self._diff_base_url = (
77 diff_base_url or 76 diff_base_url or
78 url_utils.create_filepath_url(generated_images_root)) 77 url_utils.create_filepath_url(image_diff_db.get_storage_root()))
79 self._actuals_root = actuals_root 78 self._actuals_root = actuals_root
80 self._expected_root = expected_root 79 self._expected_root = expected_root
81 self._ignore_failures_on_these_tests = [] 80 self._ignore_failures_on_these_tests = []
82 if ignore_failures_file: 81 if ignore_failures_file:
83 self._ignore_failures_on_these_tests = ( 82 self._ignore_failures_on_these_tests = (
84 ExpectationComparisons._read_noncomment_lines( 83 ExpectationComparisons._read_noncomment_lines(
85 os.path.join(expected_root, ignore_failures_file))) 84 os.path.join(expected_root, ignore_failures_file)))
86 self._load_actual_and_expected() 85 self._load_actual_and_expected()
87 self._timestamp = int(time.time()) 86 self._timestamp = int(time.time())
88 logging.info('Results complete; took %d seconds.' % 87 logging.info('Results complete; took %d seconds.' %
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 pattern: which files to write within root (fnmatch-style pattern) 163 pattern: which files to write within root (fnmatch-style pattern)
165 164
166 Raises: 165 Raises:
167 IOError if root does not refer to an existing directory 166 IOError if root does not refer to an existing directory
168 KeyError if the set of per-builder dictionaries written out was 167 KeyError if the set of per-builder dictionaries written out was
169 different than expected 168 different than expected
170 """ 169 """
171 if not os.path.isdir(root): 170 if not os.path.isdir(root):
172 raise IOError('no directory found at path %s' % root) 171 raise IOError('no directory found at path %s' % root)
173 actual_builders_written = [] 172 actual_builders_written = []
174 for dirpath, dirnames, filenames in os.walk(root): 173 for dirpath, _, filenames in os.walk(root):
175 for matching_filename in fnmatch.filter(filenames, pattern): 174 for matching_filename in fnmatch.filter(filenames, pattern):
176 builder = os.path.basename(dirpath) 175 builder = os.path.basename(dirpath)
177 per_builder_dict = meta_dict.get(builder) 176 per_builder_dict = meta_dict.get(builder)
178 if per_builder_dict is not None: 177 if per_builder_dict is not None:
179 fullpath = os.path.join(dirpath, matching_filename) 178 fullpath = os.path.join(dirpath, matching_filename)
180 gm_json.WriteToFile(per_builder_dict, fullpath) 179 gm_json.WriteToFile(per_builder_dict, fullpath)
181 actual_builders_written.append(builder) 180 actual_builders_written.append(builder)
182 181
183 # Check: did we write out the set of per-builder dictionaries we 182 # Check: did we write out the set of per-builder dictionaries we
184 # expected to? 183 # expected to?
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 imageA_relative_url=expected_image_relative_url, 331 imageA_relative_url=expected_image_relative_url,
333 imageB_relative_url=actual_image_relative_url, 332 imageB_relative_url=actual_image_relative_url,
334 expectations=expectations_dict, 333 expectations=expectations_dict,
335 extra_columns=extra_columns_dict) 334 extra_columns=extra_columns_dict)
336 all_image_pairs.add_image_pair(image_pair) 335 all_image_pairs.add_image_pair(image_pair)
337 if updated_result_type != results.KEY__RESULT_TYPE__SUCCEEDED: 336 if updated_result_type != results.KEY__RESULT_TYPE__SUCCEEDED:
338 failing_image_pairs.add_image_pair(image_pair) 337 failing_image_pairs.add_image_pair(image_pair)
339 except Exception: 338 except Exception:
340 logging.exception('got exception while creating new ImagePair') 339 logging.exception('got exception while creating new ImagePair')
341 340
341 # pylint: disable=W0201
342 self._results = { 342 self._results = {
343 results.KEY__HEADER__RESULTS_ALL: all_image_pairs.as_dict(), 343 results.KEY__HEADER__RESULTS_ALL: all_image_pairs.as_dict(),
344 results.KEY__HEADER__RESULTS_FAILURES: failing_image_pairs.as_dict(), 344 results.KEY__HEADER__RESULTS_FAILURES: failing_image_pairs.as_dict(),
345 } 345 }
346 346
347 347
348 def main(): 348 def main():
349 logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s', 349 logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
350 datefmt='%m/%d/%Y %H:%M:%S', 350 datefmt='%m/%d/%Y %H:%M:%S',
351 level=logging.INFO) 351 level=logging.INFO)
(...skipping 18 matching lines...) Expand all
370 '--results', default=results.KEY__HEADER__RESULTS_FAILURES, 370 '--results', default=results.KEY__HEADER__RESULTS_FAILURES,
371 help='Which result types to include. Defaults to \'%(default)s\'; ' 371 help='Which result types to include. Defaults to \'%(default)s\'; '
372 'must be one of ' + 372 'must be one of ' +
373 str([results.KEY__HEADER__RESULTS_FAILURES, 373 str([results.KEY__HEADER__RESULTS_FAILURES,
374 results.KEY__HEADER__RESULTS_ALL])) 374 results.KEY__HEADER__RESULTS_ALL]))
375 parser.add_argument( 375 parser.add_argument(
376 '--workdir', default=results.DEFAULT_GENERATED_IMAGES_ROOT, 376 '--workdir', default=results.DEFAULT_GENERATED_IMAGES_ROOT,
377 help='Directory within which to download images and generate diffs; ' 377 help='Directory within which to download images and generate diffs; '
378 'defaults to \'%(default)s\' .') 378 'defaults to \'%(default)s\' .')
379 args = parser.parse_args() 379 args = parser.parse_args()
380 image_diff_db = imagediffdb.ImageDiffDB(storage_root=args.workdir)
380 results_obj = ExpectationComparisons( 381 results_obj = ExpectationComparisons(
382 image_diff_db=image_diff_db,
381 actuals_root=args.actuals, 383 actuals_root=args.actuals,
382 expected_root=args.expectations, 384 expected_root=args.expectations,
383 ignore_failures_file=args.ignore_failures_file, 385 ignore_failures_file=args.ignore_failures_file)
384 generated_images_root=args.workdir)
385 gm_json.WriteToFile( 386 gm_json.WriteToFile(
386 results_obj.get_packaged_results_of_type(results_type=args.results), 387 results_obj.get_packaged_results_of_type(results_type=args.results),
387 args.outfile) 388 args.outfile)
388 389
389 390
390 if __name__ == '__main__': 391 if __name__ == '__main__':
391 main() 392 main()
OLDNEW
« no previous file with comments | « no previous file | gm/rebaseline_server/compare_to_expectations_test.py » ('j') | gm/rebaseline_server/imagediffdb.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698