OLD | NEW |
1 # Copyright (c) 2010 Google Inc. All rights reserved. | 1 # Copyright (c) 2010 Google Inc. All rights reserved. |
2 # | 2 # |
3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
5 # met: | 5 # met: |
6 # | 6 # |
7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 from webkitpy.common.system.executive import ScriptError | 42 from webkitpy.common.system.executive import ScriptError |
43 from webkitpy.layout_tests.controllers.test_result_writer import baseline_name | 43 from webkitpy.layout_tests.controllers.test_result_writer import baseline_name |
44 from webkitpy.layout_tests.models.test_expectations import TestExpectations, BAS
ELINE_SUFFIX_LIST, SKIP | 44 from webkitpy.layout_tests.models.test_expectations import TestExpectations, BAS
ELINE_SUFFIX_LIST, SKIP |
45 from webkitpy.layout_tests.port import factory | 45 from webkitpy.layout_tests.port import factory |
46 from webkitpy.tool.commands.command import Command | 46 from webkitpy.tool.commands.command import Command |
47 | 47 |
48 | 48 |
49 _log = logging.getLogger(__name__) | 49 _log = logging.getLogger(__name__) |
50 | 50 |
51 | 51 |
52 class Build(object): | |
53 """Represents a combination of builder and build number. | |
54 | |
55 If build number is None, this represents the latest build | |
56 for a given builder. | |
57 | |
58 TODO(qyearsley): Move this somewhere else; note it's very similar to TryJob, | |
59 and it seems like it might belong in the buildbot module. | |
60 """ | |
61 def __init__(self, builder_name, build_number=None): | |
62 self.builder_name = builder_name | |
63 self.build_number = build_number | |
64 | |
65 # Having __hash__ and __eq__ allow instances of this class to be used | |
66 # as keys in dictionaries. | |
67 def __hash__(self): | |
68 return hash((self.builder_name, self.build_number)) | |
69 | |
70 def __eq__(self, other): | |
71 return (self.builder_name, self.build_number) == (other.builder_name, ot
her.build_number) | |
72 | |
73 | |
74 class AbstractRebaseliningCommand(Command): | 52 class AbstractRebaseliningCommand(Command): |
75 """Base class for rebaseline-related commands.""" | 53 """Base class for rebaseline-related commands.""" |
76 # Not overriding execute() - pylint: disable=abstract-method | 54 # Not overriding execute() - pylint: disable=abstract-method |
77 | 55 |
78 no_optimize_option = optparse.make_option('--no-optimize', dest='optimize',
action='store_false', default=True, | 56 no_optimize_option = optparse.make_option('--no-optimize', dest='optimize',
action='store_false', default=True, |
79 help=('Do not optimize/de-dup the
expectations after rebaselining (default is to de-dup automatically). ' | 57 help=('Do not optimize/de-dup the
expectations after rebaselining (default is to de-dup automatically). ' |
80 'You can use "webkit-patch o
ptimize-baselines" to optimize separately.')) | 58 'You can use "webkit-patch o
ptimize-baselines" to optimize separately.')) |
81 | 59 |
82 platform_options = factory.platform_options(use_globs=True) | 60 platform_options = factory.platform_options(use_globs=True) |
83 | 61 |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 | 280 |
303 | 281 |
304 class AbstractParallelRebaselineCommand(AbstractRebaseliningCommand): | 282 class AbstractParallelRebaselineCommand(AbstractRebaseliningCommand): |
305 """Base class for rebaseline commands that do some tasks in parallel.""" | 283 """Base class for rebaseline commands that do some tasks in parallel.""" |
306 # Not overriding execute() - pylint: disable=abstract-method | 284 # Not overriding execute() - pylint: disable=abstract-method |
307 | 285 |
308 def __init__(self, options=None): | 286 def __init__(self, options=None): |
309 super(AbstractParallelRebaselineCommand, self).__init__(options=options) | 287 super(AbstractParallelRebaselineCommand, self).__init__(options=options) |
310 | 288 |
311 @memoized | 289 @memoized |
312 def build_data(self): | 290 def builder_data(self): |
313 """Returns a map of Build objects to LayoutTestResult objects. | 291 builder_to_results = {} |
314 | |
315 The Build objects are the latest builds for the release builders, | |
316 and LayoutTestResult objects for results fetched from archived layout | |
317 test results. | |
318 """ | |
319 build_to_results = {} | |
320 for builder_name in self._release_builders(): | 292 for builder_name in self._release_builders(): |
321 builder = self._tool.buildbot.builder_with_name(builder_name) | 293 builder = self._tool.buildbot.builder_with_name(builder_name) |
322 builder_results = builder.latest_layout_test_results() | 294 builder_results = builder.latest_layout_test_results() |
323 if builder_results: | 295 if builder_results: |
324 build_to_results[Build(builder_name)] = builder_results | 296 builder_to_results[builder_name] = builder_results |
325 else: | 297 else: |
326 raise Exception("No result for builder %s." % builder_name) | 298 raise Exception("No result for builder %s." % builder_name) |
327 return build_to_results | 299 return builder_to_results |
328 | 300 |
329 # The release builders cycle much faster than the debug ones and cover all t
he platforms. | 301 # The release builders cycle much faster than the debug ones and cover all t
he platforms. |
330 def _release_builders(self): | 302 def _release_builders(self): |
331 release_builders = [] | 303 release_builders = [] |
332 for builder_name in self._tool.builders.all_continuous_builder_names(): | 304 for builder_name in self._tool.builders.all_continuous_builder_names(): |
333 if 'ASAN' in builder_name: | 305 if 'ASAN' in builder_name: |
334 continue | 306 continue |
335 port = self._tool.port_factory.get_from_builder_name(builder_name) | 307 port = self._tool.port_factory.get_from_builder_name(builder_name) |
336 if port.test_configuration().build_type == 'release': | 308 if port.test_configuration().build_type == 'release': |
337 release_builders.append(builder_name) | 309 release_builders.append(builder_name) |
338 return release_builders | 310 return release_builders |
339 | 311 |
340 def _run_webkit_patch(self, args, verbose): | 312 def _run_webkit_patch(self, args, verbose): |
341 try: | 313 try: |
342 verbose_args = ['--verbose'] if verbose else [] | 314 verbose_args = ['--verbose'] if verbose else [] |
343 stderr = self._tool.executive.run_command([self._tool.path()] + verb
ose_args + | 315 stderr = self._tool.executive.run_command([self._tool.path()] + verb
ose_args + |
344 args, cwd=self._tool.scm()
.checkout_root, return_stderr=True) | 316 args, cwd=self._tool.scm()
.checkout_root, return_stderr=True) |
345 for line in stderr.splitlines(): | 317 for line in stderr.splitlines(): |
346 _log.warning(line) | 318 _log.warning(line) |
347 except ScriptError: | 319 except ScriptError: |
348 traceback.print_exc(file=sys.stderr) | 320 traceback.print_exc(file=sys.stderr) |
349 | 321 |
350 def _builders_to_fetch_from(self, builders_to_check): | 322 def _builders_to_fetch_from(self, builders_to_check): |
351 """Returns the subset of builders that will cover all of the baseline | 323 """Returns the subset of builders that will cover all of the baseline se
arch paths |
352 search paths used in the input list. | 324 used in the input list. |
353 | 325 |
354 In particular, if the input list contains both Release and Debug | 326 In particular, if the input list contains both Release and Debug |
355 versions of a configuration, we *only* return the Release version | 327 versions of a configuration, we *only* return the Release version |
356 (since we don't save debug versions of baselines). | 328 (since we don't save debug versions of baselines). |
357 | 329 |
358 Args: | 330 Args: |
359 builders_to_check: List of builder names. | 331 builders_to_check: List of builder names. |
360 """ | 332 """ |
361 release_builders = set() | 333 release_builders = set() |
362 debug_builders = set() | 334 debug_builders = set() |
363 builders_to_fallback_paths = {} | 335 builders_to_fallback_paths = {} |
364 for builder in builders_to_check: | 336 for builder in builders_to_check: |
365 port = self._tool.port_factory.get_from_builder_name(builder) | 337 port = self._tool.port_factory.get_from_builder_name(builder) |
366 if port.test_configuration().build_type == 'release': | 338 if port.test_configuration().build_type == 'release': |
367 release_builders.add(builder) | 339 release_builders.add(builder) |
368 else: | 340 else: |
369 debug_builders.add(builder) | 341 debug_builders.add(builder) |
370 for builder in list(release_builders) + list(debug_builders): | 342 for builder in list(release_builders) + list(debug_builders): |
371 port = self._tool.port_factory.get_from_builder_name(builder) | 343 port = self._tool.port_factory.get_from_builder_name(builder) |
372 fallback_path = port.baseline_search_path() | 344 fallback_path = port.baseline_search_path() |
373 if fallback_path not in builders_to_fallback_paths.values(): | 345 if fallback_path not in builders_to_fallback_paths.values(): |
374 builders_to_fallback_paths[builder] = fallback_path | 346 builders_to_fallback_paths[builder] = fallback_path |
375 return builders_to_fallback_paths.keys() | 347 return builders_to_fallback_paths.keys() |
376 | 348 |
377 @staticmethod | |
378 def _builder_names(builds): | |
379 # TODO(qyearsley): If test_prefix_list dicts are converted to instances | |
380 # of some class, then this could be replaced with a method on that clas
s. | |
381 return [b.builder_name for b in builds] | |
382 | |
383 def _rebaseline_commands(self, test_prefix_list, options, skip_checking_actu
al_results=False): | 349 def _rebaseline_commands(self, test_prefix_list, options, skip_checking_actu
al_results=False): |
384 path_to_webkit_patch = self._tool.path() | 350 path_to_webkit_patch = self._tool.path() |
385 cwd = self._tool.scm().checkout_root | 351 cwd = self._tool.scm().checkout_root |
386 copy_baseline_commands = [] | 352 copy_baseline_commands = [] |
387 rebaseline_commands = [] | 353 rebaseline_commands = [] |
388 lines_to_remove = {} | 354 lines_to_remove = {} |
389 port = self._tool.port_factory.get() | 355 port = self._tool.port_factory.get() |
390 | 356 |
391 for test_prefix in test_prefix_list: | 357 for test_prefix in test_prefix_list: |
392 for test in port.tests([test_prefix]): | 358 for test in port.tests([test_prefix]): |
393 builders_to_fetch_from = self._builders_to_fetch_from(self._buil
der_names(test_prefix_list[test_prefix])) | 359 for builder in self._builders_to_fetch_from(test_prefix_list[tes
t_prefix]): |
394 for build in test_prefix_list[test_prefix]: | |
395 # TODO(qyearsley): Remove the parameter skip_checking_actual
_results | 360 # TODO(qyearsley): Remove the parameter skip_checking_actual
_results |
396 # and instead refactor the existing code so that this is not
necessary. | 361 # and instead refactor the existing code so that this is not
necessary. |
397 builder, build_number = build.builder_name, build.build_numb
er | |
398 | |
399 if builder not in builders_to_fetch_from: | |
400 break | |
401 if skip_checking_actual_results: | 362 if skip_checking_actual_results: |
402 actual_failures_suffixes = test_prefix_list[test_prefix]
[build] | 363 actual_failures_suffixes = test_prefix_list[test_prefix]
[builder] |
403 else: | 364 else: |
404 actual_failures_suffixes = self._suffixes_for_actual_fai
lures( | 365 actual_failures_suffixes = self._suffixes_for_actual_fai
lures( |
405 test, build, test_prefix_list[test_prefix][build]) | 366 test, builder, test_prefix_list[test_prefix][builder
]) |
406 if not actual_failures_suffixes: | 367 if not actual_failures_suffixes: |
407 # If we're not going to rebaseline the test because it's
passing on this | 368 # If we're not going to rebaseline the test because it's
passing on this |
408 # builder, we still want to remove the line from TestExp
ectations. | 369 # builder, we still want to remove the line from TestExp
ectations. |
409 if test not in lines_to_remove: | 370 if test not in lines_to_remove: |
410 lines_to_remove[test] = [] | 371 lines_to_remove[test] = [] |
411 lines_to_remove[test].append(builder) | 372 lines_to_remove[test].append(builder) |
412 continue | 373 continue |
413 | 374 |
414 suffixes = ','.join(actual_failures_suffixes) | 375 suffixes = ','.join(actual_failures_suffixes) |
415 cmd_line = ['--suffixes', suffixes, '--builder', builder, '-
-test', test] | 376 cmd_line = ['--suffixes', suffixes, '--builder', builder, '-
-test', test] |
416 if build_number: | |
417 cmd_line.extend(['--build-number', build_number]) | |
418 if options.results_directory: | 377 if options.results_directory: |
419 cmd_line.extend(['--results-directory', options.results_
directory]) | 378 cmd_line.extend(['--results-directory', options.results_
directory]) |
420 if options.verbose: | 379 if options.verbose: |
421 cmd_line.append('--verbose') | 380 cmd_line.append('--verbose') |
422 copy_baseline_commands.append( | 381 copy_baseline_commands.append( |
423 tuple([[self._tool.executable, path_to_webkit_patch, 'co
py-existing-baselines-internal'] + cmd_line, cwd])) | 382 tuple([[self._tool.executable, path_to_webkit_patch, 'co
py-existing-baselines-internal'] + cmd_line, cwd])) |
424 rebaseline_commands.append( | 383 rebaseline_commands.append( |
425 tuple([[self._tool.executable, path_to_webkit_patch, 're
baseline-test-internal'] + cmd_line, cwd])) | 384 tuple([[self._tool.executable, path_to_webkit_patch, 're
baseline-test-internal'] + cmd_line, cwd])) |
426 return copy_baseline_commands, rebaseline_commands, lines_to_remove | 385 return copy_baseline_commands, rebaseline_commands, lines_to_remove |
427 | 386 |
(...skipping 24 matching lines...) Expand all Loading... |
452 | 411 |
453 if not file_added: | 412 if not file_added: |
454 _log.debug('Could not add file based off output "%s"' % output) | 413 _log.debug('Could not add file based off output "%s"' % output) |
455 | 414 |
456 return list(files_to_add), list(files_to_delete), lines_to_remove | 415 return list(files_to_add), list(files_to_delete), lines_to_remove |
457 | 416 |
458 def _optimize_baselines(self, test_prefix_list, verbose=False): | 417 def _optimize_baselines(self, test_prefix_list, verbose=False): |
459 optimize_commands = [] | 418 optimize_commands = [] |
460 for test in test_prefix_list: | 419 for test in test_prefix_list: |
461 all_suffixes = set() | 420 all_suffixes = set() |
462 builders_to_fetch_from = self._builders_to_fetch_from(self._builder_
names(test_prefix_list[test])) | 421 for builder in self._builders_to_fetch_from(test_prefix_list[test]): |
463 for build in test_prefix_list[test]: | 422 all_suffixes.update(self._suffixes_for_actual_failures(test, bui
lder, test_prefix_list[test][builder])) |
464 if build.builder_name not in builders_to_fetch_from: | |
465 break | |
466 all_suffixes.update(self._suffixes_for_actual_failures(test, bui
ld, test_prefix_list[test][build])) | |
467 | 423 |
468 # No need to optimize baselines for a test with no failures. | 424 # No need to optimize baselines for a test with no failures. |
469 if not all_suffixes: | 425 if not all_suffixes: |
470 continue | 426 continue |
471 | 427 |
472 # FIXME: We should propagate the platform options as well. | 428 # FIXME: We should propagate the platform options as well. |
473 cmd_line = ['--no-modify-scm', '--suffixes', ','.join(all_suffixes),
test] | 429 cmd_line = ['--no-modify-scm', '--suffixes', ','.join(all_suffixes),
test] |
474 if verbose: | 430 if verbose: |
475 cmd_line.append('--verbose') | 431 cmd_line.append('--verbose') |
476 | 432 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 if files_to_add: | 495 if files_to_add: |
540 self._tool.scm().add_list(files_to_add) | 496 self._tool.scm().add_list(files_to_add) |
541 return lines_to_remove | 497 return lines_to_remove |
542 | 498 |
543 def _rebaseline(self, options, test_prefix_list, skip_checking_actual_result
s=False): | 499 def _rebaseline(self, options, test_prefix_list, skip_checking_actual_result
s=False): |
544 """Downloads new baselines in parallel, then updates expectations files | 500 """Downloads new baselines in parallel, then updates expectations files |
545 and optimizes baselines. | 501 and optimizes baselines. |
546 | 502 |
547 Args: | 503 Args: |
548 options: An object with the options passed to the current command. | 504 options: An object with the options passed to the current command. |
549 test_prefix_list: A map of test names to Build objects to file suffi
xes | 505 test_prefix_list: A map of test names to builder names to baseline |
550 for new baseilnes. For example: | 506 suffixes to rebaseline. For example: |
551 { | 507 { |
552 "some/test.html": {Build("builder-1", 412): ["txt"], Build("
builder-2", 100): ["txt"]}, | 508 "some/test.html": {"builder-1": ["txt"], "builder-2": ["txt"
]}, |
553 "some/other.html": {Build("builder-1", 412): ["txt"]} | 509 "some/other.html": {"builder-1": ["txt"]} |
554 } | 510 } |
555 This would mean that new text baselines should be downloaded for | 511 This would mean that new text baselines should be downloaded for |
556 "some/test.html" on both builder-1 (build 412) and builder-2 | 512 "some/test.html" on both builder-1 and builder-2, and new text |
557 (build 100), and new text baselines should be downloaded for | 513 baselines should be downloaded for "some/other.html" but only |
558 "some/other.html" but only from builder-1. | 514 from builder-1. |
559 TODO(qyearsley): Replace test_prefix_list everywhere with some | |
560 sort of class that contains the same data. | |
561 skip_checking_actual_results: If True, then the lists of suffixes | 515 skip_checking_actual_results: If True, then the lists of suffixes |
562 to rebaseline from |test_prefix_list| will be used directly; | 516 to rebaseline from |test_prefix_list| will be used directly; |
563 if False, then the list of suffixes will filtered to include | 517 if False, then the list of suffixes will filtered to include |
564 suffixes with mismatches in actual results. | 518 suffixes with mismatches in actual results. |
565 """ | 519 """ |
566 for test, builds_to_check in sorted(test_prefix_list.items()): | 520 for test, builders_to_check in sorted(test_prefix_list.items()): |
567 _log.info("Rebaselining %s" % test) | 521 _log.info("Rebaselining %s" % test) |
568 for build, suffixes in sorted(builds_to_check.items()): | 522 for builder, suffixes in sorted(builders_to_check.items()): |
569 _log.debug(" %s: %s" % (build, ",".join(suffixes))) | 523 _log.debug(" %s: %s" % (builder, ",".join(suffixes))) |
570 | 524 |
571 copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = sel
f._rebaseline_commands( | 525 copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = sel
f._rebaseline_commands( |
572 test_prefix_list, options, skip_checking_actual_results) | 526 test_prefix_list, options, skip_checking_actual_results) |
573 lines_to_remove = {} | 527 lines_to_remove = {} |
574 | 528 |
575 self._run_in_parallel_and_update_scm(copy_baseline_commands) | 529 self._run_in_parallel_and_update_scm(copy_baseline_commands) |
576 lines_to_remove = self._run_in_parallel_and_update_scm(rebaseline_comman
ds) | 530 lines_to_remove = self._run_in_parallel_and_update_scm(rebaseline_comman
ds) |
577 | 531 |
578 for test in extra_lines_to_remove: | 532 for test in extra_lines_to_remove: |
579 if test in lines_to_remove: | 533 if test in lines_to_remove: |
580 lines_to_remove[test] = lines_to_remove[test] + extra_lines_to_r
emove[test] | 534 lines_to_remove[test] = lines_to_remove[test] + extra_lines_to_r
emove[test] |
581 else: | 535 else: |
582 lines_to_remove[test] = extra_lines_to_remove[test] | 536 lines_to_remove[test] = extra_lines_to_remove[test] |
583 | 537 |
584 if lines_to_remove: | 538 if lines_to_remove: |
585 self._update_expectations_files(lines_to_remove) | 539 self._update_expectations_files(lines_to_remove) |
586 | 540 |
587 if options.optimize: | 541 if options.optimize: |
588 # TODO(wkorman): Consider changing temporary branch to base off of H
EAD rather than | 542 # TODO(wkorman): Consider changing temporary branch to base off of H
EAD rather than |
589 # origin/master to ensure we run baseline optimization processes wit
h the same code as | 543 # origin/master to ensure we run baseline optimization processes wit
h the same code as |
590 # auto-rebaseline itself. | 544 # auto-rebaseline itself. |
591 self._run_in_parallel_and_update_scm(self._optimize_baselines(test_p
refix_list, options.verbose)) | 545 self._run_in_parallel_and_update_scm(self._optimize_baselines(test_p
refix_list, options.verbose)) |
592 | 546 |
593 def _suffixes_for_actual_failures(self, test, build, existing_suffixes): | 547 def _suffixes_for_actual_failures(self, test, builder_name, existing_suffixe
s): |
594 """Gets the baseline suffixes for actual mismatch failures in some resul
ts. | 548 if builder_name not in self.builder_data(): |
595 | |
596 Args: | |
597 test: A full test path string. | |
598 build: A Build object. | |
599 existing_suffixes: A collection of all suffixes to consider. | |
600 | |
601 Returns: | |
602 A set of file suffix strings. | |
603 """ | |
604 if build not in self.build_data(): | |
605 return set() | 549 return set() |
606 test_result = self.build_data()[build].result_for_test(test) | 550 test_result = self.builder_data()[builder_name].result_for_test(test) |
607 if not test_result: | 551 if not test_result: |
608 return set() | 552 return set() |
609 return set(existing_suffixes) & TestExpectations.suffixes_for_test_resul
t(test_result) | 553 return set(existing_suffixes) & TestExpectations.suffixes_for_test_resul
t(test_result) |
610 | 554 |
611 | 555 |
612 class RebaselineJson(AbstractParallelRebaselineCommand): | 556 class RebaselineJson(AbstractParallelRebaselineCommand): |
613 name = "rebaseline-json" | 557 name = "rebaseline-json" |
614 help_text = "Rebaseline based off JSON passed to stdin. Intended to only be
called from other scripts." | 558 help_text = "Rebaseline based off JSON passed to stdin. Intended to only be
called from other scripts." |
615 | 559 |
616 def __init__(self,): | 560 def __init__(self,): |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
649 return | 593 return |
650 tests = self._tests_to_rebaseline(self._tool.port_factory.get(port_name)
).items() | 594 tests = self._tests_to_rebaseline(self._tool.port_factory.get(port_name)
).items() |
651 | 595 |
652 if tests: | 596 if tests: |
653 _log.info("Retrieving results for %s from %s." % (port_name, builder
_name)) | 597 _log.info("Retrieving results for %s from %s." % (port_name, builder
_name)) |
654 | 598 |
655 for test_name, suffixes in tests: | 599 for test_name, suffixes in tests: |
656 _log.info(" %s (%s)" % (test_name, ','.join(suffixes))) | 600 _log.info(" %s (%s)" % (test_name, ','.join(suffixes))) |
657 if test_name not in self._test_prefix_list: | 601 if test_name not in self._test_prefix_list: |
658 self._test_prefix_list[test_name] = {} | 602 self._test_prefix_list[test_name] = {} |
659 self._test_prefix_list[test_name][Build(builder_name)] = suffixes | 603 self._test_prefix_list[test_name][builder_name] = suffixes |
660 | 604 |
661 def execute(self, options, args, tool): | 605 def execute(self, options, args, tool): |
662 options.results_directory = None | 606 options.results_directory = None |
663 self._test_prefix_list = {} | 607 self._test_prefix_list = {} |
664 port_names = tool.port_factory.all_port_names(options.platform) | 608 port_names = tool.port_factory.all_port_names(options.platform) |
665 for port_name in port_names: | 609 for port_name in port_names: |
666 self._add_tests_to_rebaseline_for_port(port_name) | 610 self._add_tests_to_rebaseline_for_port(port_name) |
667 if not self._test_prefix_list: | 611 if not self._test_prefix_list: |
668 _log.warning("Did not find any tests marked Rebaseline.") | 612 _log.warning("Did not find any tests marked Rebaseline.") |
669 return | 613 return |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
707 else: | 651 else: |
708 builders_to_check = self._builders_to_pull_from() | 652 builders_to_check = self._builders_to_pull_from() |
709 | 653 |
710 test_prefix_list = {} | 654 test_prefix_list = {} |
711 suffixes_to_update = options.suffixes.split(",") | 655 suffixes_to_update = options.suffixes.split(",") |
712 | 656 |
713 for builder in builders_to_check: | 657 for builder in builders_to_check: |
714 for test in args: | 658 for test in args: |
715 if test not in test_prefix_list: | 659 if test not in test_prefix_list: |
716 test_prefix_list[test] = {} | 660 test_prefix_list[test] = {} |
717 build = Build(builder.name()) | 661 test_prefix_list[test][builder.name()] = suffixes_to_update |
718 test_prefix_list[test][build] = suffixes_to_update | |
719 | 662 |
720 if options.verbose: | 663 if options.verbose: |
721 _log.debug("rebaseline-json: " + str(test_prefix_list)) | 664 _log.debug("rebaseline-json: " + str(test_prefix_list)) |
722 | 665 |
723 self._rebaseline(options, test_prefix_list) | 666 self._rebaseline(options, test_prefix_list) |
724 | 667 |
725 | 668 |
726 class AutoRebaseline(AbstractParallelRebaselineCommand): | 669 class AutoRebaseline(AbstractParallelRebaselineCommand): |
727 name = "auto-rebaseline" | 670 name = "auto-rebaseline" |
728 help_text = "Rebaselines any NeedsRebaseline lines in TestExpectations that
have cycled through all the bots." | 671 help_text = "Rebaselines any NeedsRebaseline lines in TestExpectations that
have cycled through all the bots." |
(...skipping 26 matching lines...) Expand all Loading... |
755 @ | 698 @ |
756 [^@>]+ # Domain terminated by @ or >, some lines have an ad
ditional @ fragment after the email. | 699 [^@>]+ # Domain terminated by @ or >, some lines have an ad
ditional @ fragment after the email. |
757 ) | 700 ) |
758 .*?([^ ]*) # Test file name | 701 .*?([^ ]*) # Test file name |
759 \ \[ # Single space followed by opening [ for expectation
specifier | 702 \ \[ # Single space followed by opening [ for expectation
specifier |
760 [^[]*$ # Prevents matching previous [ for version specifier
s instead of expectation specifiers | 703 [^[]*$ # Prevents matching previous [ for version specifier
s instead of expectation specifiers |
761 """, re.VERBOSE) | 704 """, re.VERBOSE) |
762 | 705 |
763 def bot_revision_data(self, scm): | 706 def bot_revision_data(self, scm): |
764 revisions = [] | 707 revisions = [] |
765 for result in self.build_data().values(): | 708 for result in self.builder_data().values(): |
766 if result.run_was_interrupted(): | 709 if result.run_was_interrupted(): |
767 _log.error("Can't rebaseline because the latest run on %s exited
early." % result.builder_name()) | 710 _log.error("Can't rebaseline because the latest run on %s exited
early." % result.builder_name()) |
768 return [] | 711 return [] |
769 revisions.append({ | 712 revisions.append({ |
770 "builder": result.builder_name(), | 713 "builder": result.builder_name(), |
771 "revision": result.chromium_revision(scm), | 714 "revision": result.chromium_revision(scm), |
772 }) | 715 }) |
773 return revisions | 716 return revisions |
774 | 717 |
775 def _strip_comments(self, line): | 718 def _strip_comments(self, line): |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
855 port = self._tool.port_factory.get(port_name) | 798 port = self._tool.port_factory.get(port_name) |
856 expectations = TestExpectations(port, include_overrides=True) | 799 expectations = TestExpectations(port, include_overrides=True) |
857 for test in expectations.get_needs_rebaseline_failures(): | 800 for test in expectations.get_needs_rebaseline_failures(): |
858 if test not in tests: | 801 if test not in tests: |
859 continue | 802 continue |
860 | 803 |
861 if test not in test_prefix_list: | 804 if test not in test_prefix_list: |
862 lines_to_remove[test] = [] | 805 lines_to_remove[test] = [] |
863 test_prefix_list[test] = {} | 806 test_prefix_list[test] = {} |
864 lines_to_remove[test].append(builder_name) | 807 lines_to_remove[test].append(builder_name) |
865 test_prefix_list[test][Build(builder_name)] = BASELINE_SUFFIX_LI
ST | 808 test_prefix_list[test][builder_name] = BASELINE_SUFFIX_LIST |
866 | 809 |
867 return test_prefix_list, lines_to_remove | 810 return test_prefix_list, lines_to_remove |
868 | 811 |
869 def _run_git_cl_command(self, options, command): | 812 def _run_git_cl_command(self, options, command): |
870 subprocess_command = ['git', 'cl'] + command | 813 subprocess_command = ['git', 'cl'] + command |
871 if options.verbose: | 814 if options.verbose: |
872 subprocess_command.append('--verbose') | 815 subprocess_command.append('--verbose') |
873 if options.auth_refresh_token_json: | 816 if options.auth_refresh_token_json: |
874 subprocess_command.append('--auth-refresh-token-json') | 817 subprocess_command.append('--auth-refresh-token-json') |
875 subprocess_command.append(options.auth_refresh_token_json) | 818 subprocess_command.append(options.auth_refresh_token_json) |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
982 issue_already_closed = tool.executive.run_command( | 925 issue_already_closed = tool.executive.run_command( |
983 ['git', 'config', 'branch.%s.rietveldissue' % rebaseline
_branch_name], | 926 ['git', 'config', 'branch.%s.rietveldissue' % rebaseline
_branch_name], |
984 return_exit_code=True) | 927 return_exit_code=True) |
985 if not issue_already_closed: | 928 if not issue_already_closed: |
986 self._run_git_cl_command(options, ['set_close']) | 929 self._run_git_cl_command(options, ['set_close']) |
987 | 930 |
988 tool.scm().ensure_cleanly_tracking_remote_master() | 931 tool.scm().ensure_cleanly_tracking_remote_master() |
989 if old_branch_name_or_ref: | 932 if old_branch_name_or_ref: |
990 tool.scm().checkout_branch(old_branch_name_or_ref) | 933 tool.scm().checkout_branch(old_branch_name_or_ref) |
991 tool.scm().delete_branch(rebaseline_branch_name) | 934 tool.scm().delete_branch(rebaseline_branch_name) |
OLD | NEW |