OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 ''' | 3 ''' |
4 Copyright 2012 Google Inc. | 4 Copyright 2012 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 | 9 |
10 ''' | 10 ''' |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 'Test-Win7-ShuttleA-HD2000-x86-Release', | 87 'Test-Win7-ShuttleA-HD2000-x86-Release', |
88 'Test-Win7-ShuttleA-HD2000-x86-Release-ANGLE', | 88 'Test-Win7-ShuttleA-HD2000-x86-Release-ANGLE', |
89 'Test-Win7-ShuttleA-HD2000-x86-Release-DirectWrite', | 89 'Test-Win7-ShuttleA-HD2000-x86-Release-DirectWrite', |
90 'Test-Win7-ShuttleA-HD2000-x86_64-Debug', | 90 'Test-Win7-ShuttleA-HD2000-x86_64-Debug', |
91 'Test-Win7-ShuttleA-HD2000-x86_64-Release', | 91 'Test-Win7-ShuttleA-HD2000-x86_64-Release', |
92 ] | 92 ] |
93 | 93 |
94 class _InternalException(Exception): | 94 class _InternalException(Exception): |
95 pass | 95 pass |
96 | 96 |
97 # Object that handles exceptions, either raising them immediately or collecting | |
98 # them to display later on. | |
99 class ExceptionHandler(object): | 97 class ExceptionHandler(object): |
| 98 """ Object that handles exceptions, either raising them immediately or |
| 99 collecting them to display later on.""" |
100 | 100 |
101 # params: | 101 # params: |
102 # keep_going_on_failure: if False, report failures and quit right away; | |
103 # if True, collect failures until | |
104 # ReportAllFailures() is called | |
105 def __init__(self, keep_going_on_failure=False): | 102 def __init__(self, keep_going_on_failure=False): |
| 103 """ |
| 104 params: |
| 105 keep_going_on_failure: if False, report failures and quit right away; |
| 106 if True, collect failures until |
| 107 ReportAllFailures() is called |
| 108 """ |
106 self._keep_going_on_failure = keep_going_on_failure | 109 self._keep_going_on_failure = keep_going_on_failure |
107 self._failures_encountered = [] | 110 self._failures_encountered = [] |
108 self._exiting = False | |
109 | 111 |
110 # Exit the program with the given status value. | 112 def RaiseExceptionOrContinue(self): |
111 def _Exit(self, status=1): | 113 """ We have encountered an exception; either collect the info and keep |
112 self._exiting = True | 114 going, or exit the program right away.""" |
113 sys.exit(status) | 115 # Get traceback information about the most recently raised exception. |
114 | 116 exc_info = sys.exc_info() |
115 # We have encountered an exception; either collect the info and keep going, | |
116 # or exit the program right away. | |
117 def RaiseExceptionOrContinue(self, e): | |
118 # If we are already quitting the program, propagate any exceptions | |
119 # so that the proper exit status will be communicated to the shell. | |
120 if self._exiting: | |
121 raise e | |
122 | 117 |
123 if self._keep_going_on_failure: | 118 if self._keep_going_on_failure: |
124 print >> sys.stderr, 'WARNING: swallowing exception %s' % e | 119 print >> sys.stderr, ('WARNING: swallowing exception %s' % |
125 self._failures_encountered.append(e) | 120 repr(exc_info[1])) |
| 121 self._failures_encountered.append(exc_info) |
126 else: | 122 else: |
127 print >> sys.stderr, e | |
128 print >> sys.stderr, ( | 123 print >> sys.stderr, ( |
129 'Halting at first exception; to keep going, re-run ' + | 124 'Halting at first exception; to keep going, re-run ' + |
130 'with the --keep-going-on-failure option set.') | 125 'with the --keep-going-on-failure option set.') |
131 self._Exit() | 126 raise exc_info[1], None, exc_info[2] |
132 | 127 |
133 def ReportAllFailures(self): | 128 def ReportAllFailures(self): |
134 if self._failures_encountered: | 129 if self._failures_encountered: |
135 print >> sys.stderr, ('Encountered %d failures (see above).' % | 130 print >> sys.stderr, ('Encountered %d failures (see above).' % |
136 len(self._failures_encountered)) | 131 len(self._failures_encountered)) |
137 self._Exit() | 132 sys.exit(1) |
138 | 133 |
139 | 134 |
140 # Object that rebaselines a JSON expectations file (not individual image files). | 135 # Object that rebaselines a JSON expectations file (not individual image files). |
141 class JsonRebaseliner(object): | 136 class JsonRebaseliner(object): |
142 | 137 |
143 # params: | 138 # params: |
144 # expectations_root: root directory of all expectations JSON files | 139 # expectations_root: root directory of all expectations JSON files |
145 # expectations_input_filename: filename (under expectations_root) of JSON | 140 # expectations_input_filename: filename (under expectations_root) of JSON |
146 # expectations file to read; typically | 141 # expectations file to read; typically |
147 # "expected-results.json" | 142 # "expected-results.json" |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 sections = [gm_json.JSONKEY_ACTUALRESULTS_FAILED] | 260 sections = [gm_json.JSONKEY_ACTUALRESULTS_FAILED] |
266 if self._add_new: | 261 if self._add_new: |
267 sections.append(gm_json.JSONKEY_ACTUALRESULTS_NOCOMPARISON) | 262 sections.append(gm_json.JSONKEY_ACTUALRESULTS_NOCOMPARISON) |
268 results_to_update = self._GetActualResults(json_url=actuals_url, | 263 results_to_update = self._GetActualResults(json_url=actuals_url, |
269 sections=sections) | 264 sections=sections) |
270 | 265 |
271 # Read in current expectations. | 266 # Read in current expectations. |
272 expectations_input_filepath = os.path.join( | 267 expectations_input_filepath = os.path.join( |
273 self._expectations_root, builder, self._expectations_input_filename) | 268 self._expectations_root, builder, self._expectations_input_filename) |
274 expectations_dict = gm_json.LoadFromFile(expectations_input_filepath) | 269 expectations_dict = gm_json.LoadFromFile(expectations_input_filepath) |
275 expected_results = expectations_dict[gm_json.JSONKEY_EXPECTEDRESULTS] | 270 expected_results = expectations_dict.get(gm_json.JSONKEY_EXPECTEDRESULTS) |
| 271 if not expected_results: |
| 272 expected_results = {} |
| 273 expectations_dict[gm_json.JSONKEY_EXPECTEDRESULTS] = expected_results |
276 | 274 |
277 # Update the expectations in memory, skipping any tests/configs that | 275 # Update the expectations in memory, skipping any tests/configs that |
278 # the caller asked to exclude. | 276 # the caller asked to exclude. |
279 skipped_images = [] | 277 skipped_images = [] |
280 if results_to_update: | 278 if results_to_update: |
281 for (image_name, image_results) in results_to_update.iteritems(): | 279 for (image_name, image_results) in results_to_update.iteritems(): |
282 (test, config) = self._image_filename_re.match(image_name).groups() | 280 (test, config) = self._image_filename_re.match(image_name).groups() |
283 if self._tests: | 281 if self._tests: |
284 if test not in self._tests: | 282 if test not in self._tests: |
285 skipped_images.append(image_name) | 283 skipped_images.append(image_name) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 parser.add_argument('--actuals-base-url', | 321 parser.add_argument('--actuals-base-url', |
324 help=('base URL from which to read files containing JSON ' | 322 help=('base URL from which to read files containing JSON ' |
325 'summaries of actual GM results; defaults to ' | 323 'summaries of actual GM results; defaults to ' |
326 '%(default)s'), | 324 '%(default)s'), |
327 default='http://skia-autogen.googlecode.com/svn/gm-actual') | 325 default='http://skia-autogen.googlecode.com/svn/gm-actual') |
328 parser.add_argument('--actuals-filename', | 326 parser.add_argument('--actuals-filename', |
329 help=('filename (within builder-specific subdirectories ' | 327 help=('filename (within builder-specific subdirectories ' |
330 'of ACTUALS_BASE_URL) to read a summary of results ' | 328 'of ACTUALS_BASE_URL) to read a summary of results ' |
331 'from; defaults to %(default)s'), | 329 'from; defaults to %(default)s'), |
332 default='actual-results.json') | 330 default='actual-results.json') |
333 # TODO(epoger): Add test that exercises --add-new argument. | |
334 parser.add_argument('--add-new', action='store_true', | 331 parser.add_argument('--add-new', action='store_true', |
335 help=('in addition to the standard behavior of ' | 332 help=('in addition to the standard behavior of ' |
336 'updating expectations for failing tests, add ' | 333 'updating expectations for failing tests, add ' |
337 'expectations for tests which don\'t have ' | 334 'expectations for tests which don\'t have ' |
338 'expectations yet.')) | 335 'expectations yet.')) |
339 parser.add_argument('--bugs', metavar='BUG', type=int, nargs='+', | 336 parser.add_argument('--bugs', metavar='BUG', type=int, nargs='+', |
340 help=('Skia bug numbers (under ' | 337 help=('Skia bug numbers (under ' |
341 'https://code.google.com/p/skia/issues/list ) which ' | 338 'https://code.google.com/p/skia/issues/list ) which ' |
342 'pertain to this set of rebaselines.')) | 339 'pertain to this set of rebaselines.')) |
343 parser.add_argument('--builders', metavar='BUILDER', nargs='+', | 340 parser.add_argument('--builders', metavar='BUILDER', nargs='+', |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 expectations_output_filename=(args.expectations_filename_output or | 407 expectations_output_filename=(args.expectations_filename_output or |
411 args.expectations_filename), | 408 args.expectations_filename), |
412 tests=args.tests, configs=args.configs, | 409 tests=args.tests, configs=args.configs, |
413 actuals_base_url=args.actuals_base_url, | 410 actuals_base_url=args.actuals_base_url, |
414 actuals_filename=args.actuals_filename, | 411 actuals_filename=args.actuals_filename, |
415 exception_handler=exception_handler, | 412 exception_handler=exception_handler, |
416 add_new=args.add_new, bugs=args.bugs, notes=args.notes, | 413 add_new=args.add_new, bugs=args.bugs, notes=args.notes, |
417 mark_unreviewed=args.unreviewed) | 414 mark_unreviewed=args.unreviewed) |
418 try: | 415 try: |
419 rebaseliner.RebaselineSubdir(builder=builder) | 416 rebaseliner.RebaselineSubdir(builder=builder) |
420 except BaseException as e: | 417 except: |
421 exception_handler.RaiseExceptionOrContinue(e) | 418 exception_handler.RaiseExceptionOrContinue() |
422 else: | 419 else: |
423 exception_handler.RaiseExceptionOrContinue(_InternalException( | 420 try: |
424 'expectations_json_file %s not found' % expectations_json_file)) | 421 raise _InternalException('expectations_json_file %s not found' % |
| 422 expectations_json_file) |
| 423 except: |
| 424 exception_handler.RaiseExceptionOrContinue() |
425 | 425 |
426 exception_handler.ReportAllFailures() | 426 exception_handler.ReportAllFailures() |
OLD | NEW |