Chromium Code Reviews| 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 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 170 # Currently, there is no way to make this script mark | 170 # Currently, there is no way to make this script mark |
| 171 # expectations as reviewed-by-human=True. | 171 # expectations as reviewed-by-human=True. |
| 172 # TODO(epoger): Add that capability to a review tool. | 172 # TODO(epoger): Add that capability to a review tool. |
| 173 # mark_ignore_failure: if True, mark failures of a given test as being | 173 # mark_ignore_failure: if True, mark failures of a given test as being |
| 174 # ignored. | 174 # ignored. |
| 175 def __init__(self, expectations_root, expectations_input_filename, | 175 def __init__(self, expectations_root, expectations_input_filename, |
| 176 expectations_output_filename, actuals_base_url, | 176 expectations_output_filename, actuals_base_url, |
| 177 actuals_filename, exception_handler, | 177 actuals_filename, exception_handler, |
| 178 tests=None, configs=None, add_new=False, bugs=None, notes=None, | 178 tests=None, configs=None, add_new=False, bugs=None, notes=None, |
| 179 mark_unreviewed=None, mark_ignore_failure=False, | 179 mark_unreviewed=None, mark_ignore_failure=False, |
| 180 from_trybot=False): | 180 from_trybot=False, skip_pattern_matching=False): |
|
epoger
2013/10/10 15:05:09
please update the docstring above
scroggo
2013/10/10 19:32:36
Done.
| |
| 181 self._expectations_root = expectations_root | 181 self._expectations_root = expectations_root |
| 182 self._expectations_input_filename = expectations_input_filename | 182 self._expectations_input_filename = expectations_input_filename |
| 183 self._expectations_output_filename = expectations_output_filename | 183 self._expectations_output_filename = expectations_output_filename |
| 184 self._tests = tests | 184 self._tests = tests |
| 185 self._configs = configs | 185 self._configs = configs |
| 186 self._actuals_base_url = actuals_base_url | 186 self._actuals_base_url = actuals_base_url |
| 187 self._actuals_filename = actuals_filename | 187 self._actuals_filename = actuals_filename |
| 188 self._exception_handler = exception_handler | 188 self._exception_handler = exception_handler |
| 189 self._add_new = add_new | 189 self._add_new = add_new |
| 190 self._bugs = bugs | 190 self._bugs = bugs |
| 191 self._notes = notes | 191 self._notes = notes |
| 192 self._mark_unreviewed = mark_unreviewed | 192 self._mark_unreviewed = mark_unreviewed |
| 193 self._mark_ignore_failure = mark_ignore_failure; | 193 self._mark_ignore_failure = mark_ignore_failure; |
| 194 self._image_filename_re = re.compile(gm_json.IMAGE_FILENAME_PATTERN) | 194 # TODO(scroggo): This is a hack. Since the filenames will not match |
| 195 # the pattern in skimage, we skip the pattern matching entirely. | |
| 196 if skip_pattern_matching: | |
| 197 self._image_filename_re = None | |
| 198 else: | |
| 199 self._image_filename_re = re.compile(gm_json.IMAGE_FILENAME_PATTERN) | |
| 195 self._using_svn = os.path.isdir(os.path.join(expectations_root, '.svn')) | 200 self._using_svn = os.path.isdir(os.path.join(expectations_root, '.svn')) |
| 196 self._from_trybot = from_trybot | 201 self._from_trybot = from_trybot |
| 197 | 202 |
| 198 # Executes subprocess.call(cmd). | 203 # Executes subprocess.call(cmd). |
| 199 # Raises an Exception if the command fails. | 204 # Raises an Exception if the command fails. |
| 200 def _Call(self, cmd): | 205 def _Call(self, cmd): |
| 201 if subprocess.call(cmd) != 0: | 206 if subprocess.call(cmd) != 0: |
| 202 raise _InternalException('error running command: ' + ' '.join(cmd)) | 207 raise _InternalException('error running command: ' + ' '.join(cmd)) |
| 203 | 208 |
| 204 # Returns the full contents of filepath, as a single string. | 209 # Returns the full contents of filepath, as a single string. |
| 205 # If filepath looks like a URL, try to read it that way instead of as | 210 # If filepath looks like a URL, try to read it that way instead of as |
| 206 # a path on local storage. | 211 # a path on local storage. |
| 207 # | 212 # |
| 208 # Raises _InternalException if there is a problem. | 213 # Raises _InternalException if there is a problem. |
| 209 def _GetFileContents(self, filepath): | 214 def _GetFileContents(self, filepath): |
| 210 if filepath.startswith('http:') or filepath.startswith('https:'): | 215 if filepath.startswith('http:') or filepath.startswith('https:'): |
| 211 try: | 216 try: |
| 212 return urllib2.urlopen(filepath).read() | 217 return urllib2.urlopen(filepath).read() |
| 213 except urllib2.HTTPError as e: | 218 except urllib2.HTTPError as e: |
| 214 raise _InternalException('unable to read URL %s: %s' % ( | 219 raise _InternalException('unable to read URL %s: %s' % ( |
| 215 filepath, e)) | 220 filepath, e)) |
| 221 elif filepath.startswith('gs:'): | |
|
epoger
2013/10/10 15:05:09
As discussed live: I think it's better to download
scroggo
2013/10/10 19:32:36
Done.
| |
| 222 try: | |
| 223 return subprocess.check_output(['gsutil', 'cat', filepath]) | |
| 224 except subprocess.CalledProcessError: | |
| 225 raise _InternalException('unable to read Google Storage URL %s: %s' % ( | |
| 226 filepath, e)) | |
| 216 else: | 227 else: |
| 217 return open(filepath, 'r').read() | 228 return open(filepath, 'r').read() |
| 218 | 229 |
| 219 # Returns a dictionary of actual results from actual-results.json file. | 230 # Returns a dictionary of actual results from actual-results.json file. |
| 220 # | 231 # |
| 221 # The dictionary returned has this format: | 232 # The dictionary returned has this format: |
| 222 # { | 233 # { |
| 223 # u'imageblur_565.png': [u'bitmap-64bitMD5', 3359963596899141322], | 234 # u'imageblur_565.png': [u'bitmap-64bitMD5', 3359963596899141322], |
| 224 # u'imageblur_8888.png': [u'bitmap-64bitMD5', 4217923806027861152], | 235 # u'imageblur_8888.png': [u'bitmap-64bitMD5', 4217923806027861152], |
| 225 # u'shadertext3_8888.png': [u'bitmap-64bitMD5', 3713708307125704716] | 236 # u'shadertext3_8888.png': [u'bitmap-64bitMD5', 3713708307125704716] |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 286 expected_results = expectations_dict.get(gm_json.JSONKEY_EXPECTEDRESULTS) | 297 expected_results = expectations_dict.get(gm_json.JSONKEY_EXPECTEDRESULTS) |
| 287 if not expected_results: | 298 if not expected_results: |
| 288 expected_results = {} | 299 expected_results = {} |
| 289 expectations_dict[gm_json.JSONKEY_EXPECTEDRESULTS] = expected_results | 300 expectations_dict[gm_json.JSONKEY_EXPECTEDRESULTS] = expected_results |
| 290 | 301 |
| 291 # Update the expectations in memory, skipping any tests/configs that | 302 # Update the expectations in memory, skipping any tests/configs that |
| 292 # the caller asked to exclude. | 303 # the caller asked to exclude. |
| 293 skipped_images = [] | 304 skipped_images = [] |
| 294 if results_to_update: | 305 if results_to_update: |
| 295 for (image_name, image_results) in results_to_update.iteritems(): | 306 for (image_name, image_results) in results_to_update.iteritems(): |
| 296 (test, config) = self._image_filename_re.match(image_name).groups() | 307 if self._image_filename_re: |
| 297 if self._tests: | 308 (test, config) = self._image_filename_re.match(image_name).groups() |
| 298 if test not in self._tests: | 309 if self._tests: |
| 299 skipped_images.append(image_name) | 310 if test not in self._tests: |
| 300 continue | 311 skipped_images.append(image_name) |
| 301 if self._configs: | 312 continue |
| 302 if config not in self._configs: | 313 if self._configs: |
| 303 skipped_images.append(image_name) | 314 if config not in self._configs: |
| 304 continue | 315 skipped_images.append(image_name) |
| 316 continue | |
| 305 if not expected_results.get(image_name): | 317 if not expected_results.get(image_name): |
| 306 expected_results[image_name] = {} | 318 expected_results[image_name] = {} |
| 307 expected_results[image_name]\ | 319 expected_results[image_name]\ |
| 308 [gm_json.JSONKEY_EXPECTEDRESULTS_ALLOWEDDIGESTS]\ | 320 [gm_json.JSONKEY_EXPECTEDRESULTS_ALLOWEDDIGESTS]\ |
| 309 = [image_results] | 321 = [image_results] |
| 310 if self._mark_unreviewed: | 322 if self._mark_unreviewed: |
| 311 expected_results[image_name]\ | 323 expected_results[image_name]\ |
| 312 [gm_json.JSONKEY_EXPECTEDRESULTS_REVIEWED]\ | 324 [gm_json.JSONKEY_EXPECTEDRESULTS_REVIEWED]\ |
| 313 = False | 325 = False |
| 314 if self._mark_ignore_failure: | 326 if self._mark_ignore_failure: |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 407 help=('mark all expectations modified by this run as ' | 419 help=('mark all expectations modified by this run as ' |
| 408 '"%s": False' % | 420 '"%s": False' % |
| 409 gm_json.JSONKEY_EXPECTEDRESULTS_REVIEWED)) | 421 gm_json.JSONKEY_EXPECTEDRESULTS_REVIEWED)) |
| 410 parser.add_argument('--ignore-failure', action='store_true', | 422 parser.add_argument('--ignore-failure', action='store_true', |
| 411 help=('mark all expectations modified by this run as ' | 423 help=('mark all expectations modified by this run as ' |
| 412 '"%s": True' % | 424 '"%s": True' % |
| 413 gm_json.JSONKEY_ACTUALRESULTS_FAILUREIGNORED)) | 425 gm_json.JSONKEY_ACTUALRESULTS_FAILUREIGNORED)) |
| 414 parser.add_argument('--from-trybot', action='store_true', | 426 parser.add_argument('--from-trybot', action='store_true', |
| 415 help=('pull the actual-results.json file from the ' | 427 help=('pull the actual-results.json file from the ' |
| 416 'corresponding trybot, rather than the main builder')) | 428 'corresponding trybot, rather than the main builder')) |
| 429 parser.add_argument('--skimage', action='store_true', | |
| 430 help=('Rebaseline skimage results instead of gm. Defaults ' | |
| 431 'to False.')) | |
| 417 args = parser.parse_args() | 432 args = parser.parse_args() |
| 418 exception_handler = ExceptionHandler( | 433 exception_handler = ExceptionHandler( |
| 419 keep_going_on_failure=args.keep_going_on_failure) | 434 keep_going_on_failure=args.keep_going_on_failure) |
| 420 if args.builders: | 435 if args.builders: |
| 421 builders = args.builders | 436 builders = args.builders |
| 422 missing_json_is_fatal = True | 437 missing_json_is_fatal = True |
| 423 else: | 438 else: |
| 424 builders = sorted(TEST_BUILDERS) | 439 builders = sorted(TEST_BUILDERS) |
| 425 missing_json_is_fatal = False | 440 missing_json_is_fatal = False |
| 441 if args.skimage: | |
| 442 # Hardcode variables for skimage. | |
| 443 args.actuals_base_url = 'gs://chromium-skia-gm/skimage/actuals' | |
|
epoger
2013/10/10 15:05:09
I think it will be surprising that these args are
scroggo
2013/10/10 19:32:36
Done, for --tests and --configs.
| |
| 444 args.expectations_root = os.path.join('expectations', 'skimage') | |
| 426 for builder in builders: | 445 for builder in builders: |
| 427 if not builder in TEST_BUILDERS: | 446 if not builder in TEST_BUILDERS: |
| 428 raise Exception(('unrecognized builder "%s"; ' + | 447 raise Exception(('unrecognized builder "%s"; ' + |
| 429 'should be one of %s') % ( | 448 'should be one of %s') % ( |
| 430 builder, TEST_BUILDERS)) | 449 builder, TEST_BUILDERS)) |
| 431 | 450 |
| 432 expectations_json_file = os.path.join(args.expectations_root, builder, | 451 expectations_json_file = os.path.join(args.expectations_root, builder, |
| 433 args.expectations_filename) | 452 args.expectations_filename) |
| 434 if os.path.isfile(expectations_json_file): | 453 if os.path.isfile(expectations_json_file): |
| 435 rebaseliner = JsonRebaseliner( | 454 rebaseliner = JsonRebaseliner( |
| 436 expectations_root=args.expectations_root, | 455 expectations_root=args.expectations_root, |
| 437 expectations_input_filename=args.expectations_filename, | 456 expectations_input_filename=args.expectations_filename, |
| 438 expectations_output_filename=(args.expectations_filename_output or | 457 expectations_output_filename=(args.expectations_filename_output or |
| 439 args.expectations_filename), | 458 args.expectations_filename), |
| 440 tests=args.tests, configs=args.configs, | 459 tests=args.tests, configs=args.configs, |
| 441 actuals_base_url=args.actuals_base_url, | 460 actuals_base_url=args.actuals_base_url, |
| 442 actuals_filename=args.actuals_filename, | 461 actuals_filename=args.actuals_filename, |
| 443 exception_handler=exception_handler, | 462 exception_handler=exception_handler, |
| 444 add_new=args.add_new, bugs=args.bugs, notes=args.notes, | 463 add_new=args.add_new, bugs=args.bugs, notes=args.notes, |
| 445 mark_unreviewed=args.unreviewed, | 464 mark_unreviewed=args.unreviewed, |
| 446 mark_ignore_failure=args.ignore_failure, | 465 mark_ignore_failure=args.ignore_failure, |
| 447 from_trybot=args.from_trybot) | 466 from_trybot=args.from_trybot, |
| 467 skip_pattern_matching=args.skimage) | |
| 448 try: | 468 try: |
| 449 rebaseliner.RebaselineSubdir(builder=builder) | 469 rebaseliner.RebaselineSubdir(builder=builder) |
| 450 except: | 470 except: |
| 451 exception_handler.RaiseExceptionOrContinue() | 471 exception_handler.RaiseExceptionOrContinue() |
| 452 else: | 472 else: |
| 453 try: | 473 try: |
| 454 raise _InternalException('expectations_json_file %s not found' % | 474 raise _InternalException('expectations_json_file %s not found' % |
| 455 expectations_json_file) | 475 expectations_json_file) |
| 456 except: | 476 except: |
| 457 exception_handler.RaiseExceptionOrContinue() | 477 exception_handler.RaiseExceptionOrContinue() |
| 458 | 478 |
| 459 exception_handler.ReportAllFailures() | 479 exception_handler.ReportAllFailures() |
| OLD | NEW |