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

Side by Side Diff: third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline.py

Issue 2760463004: Simplification: Remove support for specifying suffix lists when rebaselining. (Closed)
Patch Set: Remove blank lines Created 3 years, 9 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
« no previous file with comments | « no previous file | third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 lines_to_remove = {} 361 lines_to_remove = {}
362 port = self._tool.port_factory.get() 362 port = self._tool.port_factory.get()
363 363
364 for test_prefix in test_prefix_list: 364 for test_prefix in test_prefix_list:
365 for test in port.tests([test_prefix]): 365 for test in port.tests([test_prefix]):
366 builders_to_fetch_from = self._builders_to_fetch_from(self._buil der_names(test_prefix_list[test_prefix])) 366 builders_to_fetch_from = self._builders_to_fetch_from(self._buil der_names(test_prefix_list[test_prefix]))
367 for build in sorted(test_prefix_list[test_prefix]): 367 for build in sorted(test_prefix_list[test_prefix]):
368 builder, build_number = build.builder_name, build.build_numb er 368 builder, build_number = build.builder_name, build.build_numb er
369 if builder not in builders_to_fetch_from: 369 if builder not in builders_to_fetch_from:
370 break 370 break
371 else: 371
372 actual_failures_suffixes = self._suffixes_for_actual_fai lures( 372 suffixes = self._suffixes_for_actual_failures(test, build)
373 test, build, test_prefix_list[test_prefix][build]) 373 if not suffixes:
374 if not actual_failures_suffixes:
375 # If we're not going to rebaseline the test because it's passing on this 374 # If we're not going to rebaseline the test because it's passing on this
376 # builder, we still want to remove the line from TestExp ectations. 375 # builder, we still want to remove the line from TestExp ectations.
377 if test not in lines_to_remove: 376 if test not in lines_to_remove:
378 lines_to_remove[test] = [] 377 lines_to_remove[test] = []
379 lines_to_remove[test].append(builder) 378 lines_to_remove[test].append(builder)
380 continue 379 continue
381 380
382 suffixes = ','.join(actual_failures_suffixes) 381 args = ['--suffixes', ','.join(suffixes), '--builder', build er, '--test', test]
383 args = ['--suffixes', suffixes, '--builder', builder, '--tes t', test]
384 382
385 if options.verbose: 383 if options.verbose:
386 args.append('--verbose') 384 args.append('--verbose')
387 385
388 copy_baseline_commands.append( 386 copy_baseline_commands.append(
389 tuple([[self._tool.executable, path_to_webkit_patch, 'co py-existing-baselines-internal'] + args, cwd])) 387 tuple([[self._tool.executable, path_to_webkit_patch, 'co py-existing-baselines-internal'] + args, cwd]))
390 388
391 if build_number: 389 if build_number:
392 args.extend(['--build-number', str(build_number)]) 390 args.extend(['--build-number', str(build_number)])
393 if options.results_directory: 391 if options.results_directory:
(...skipping 22 matching lines...) Expand all
416 return change_set 414 return change_set
417 415
418 def _optimize_baselines(self, test_prefix_list, verbose=False): 416 def _optimize_baselines(self, test_prefix_list, verbose=False):
419 optimize_commands = [] 417 optimize_commands = []
420 for test in test_prefix_list: 418 for test in test_prefix_list:
421 all_suffixes = set() 419 all_suffixes = set()
422 builders_to_fetch_from = self._builders_to_fetch_from(self._builder_ names(test_prefix_list[test])) 420 builders_to_fetch_from = self._builders_to_fetch_from(self._builder_ names(test_prefix_list[test]))
423 for build in sorted(test_prefix_list[test]): 421 for build in sorted(test_prefix_list[test]):
424 if build.builder_name not in builders_to_fetch_from: 422 if build.builder_name not in builders_to_fetch_from:
425 break 423 break
426 all_suffixes.update(self._suffixes_for_actual_failures(test, bui ld, test_prefix_list[test][build])) 424 all_suffixes.update(self._suffixes_for_actual_failures(test, bui ld))
427 425
428 # No need to optimize baselines for a test with no failures. 426 # No need to optimize baselines for a test with no failures.
429 if not all_suffixes: 427 if not all_suffixes:
430 continue 428 continue
431 429
432 # FIXME: We should propagate the platform options as well. 430 # FIXME: We should propagate the platform options as well.
433 cmd_line = ['--suffixes', ','.join(all_suffixes), test] 431 cmd_line = ['--suffixes', ','.join(all_suffixes), test]
434 if verbose: 432 if verbose:
435 cmd_line.append('--verbose') 433 cmd_line.append('--verbose')
436 434
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 command_results = self._tool.executive.run_in_parallel(commands) 478 command_results = self._tool.executive.run_in_parallel(commands)
481 for _, _, stderr in command_results: 479 for _, _, stderr in command_results:
482 if stderr: 480 if stderr:
483 _log.error(stderr) 481 _log.error(stderr)
484 482
485 change_set = self._extract_expectation_line_changes(command_results) 483 change_set = self._extract_expectation_line_changes(command_results)
486 484
487 return change_set.lines_to_remove 485 return change_set.lines_to_remove
488 486
489 def rebaseline(self, options, test_prefix_list): 487 def rebaseline(self, options, test_prefix_list):
490 """Downloads new baselines in parallel, then updates expectations files 488 """Fetches new baselines and removes related test expectation lines.
491 and optimizes baselines.
492 489
493 Args: 490 Args:
494 options: An object with the options passed to the current command. 491 options: An object with the command line options.
495 test_prefix_list: A map of test names to Build objects to file suffi xes 492 test_prefix_list: A dict of test names to Build objects for new
496 for new baselines. For example: 493 baselines. For example:
497 { 494 {
498 "some/test.html": {Build("builder-1", 412): ["txt"], Build(" builder-2", 100): ["txt"]}, 495 "some/test.html": [Build("builder-1", 412),
499 "some/other.html": {Build("builder-1", 412): ["txt"]} 496 Build("builder-2", 100)]},
497 "some/other.html": [Build("builder-1", 412)}
500 } 498 }
501 This would mean that new text baselines should be downloaded for 499 This would mean that new text baselines should be
502 "some/test.html" on both builder-1 (build 412) and builder-2 500 downloaded for "some/test.html" on both builder-1
503 (build 100), and new text baselines should be downloaded for 501 (build 412) and builder-2 (build 100), and new text
504 "some/other.html" but only from builder-1. 502 baselines should be downloaded for "some/other.html"
505 TODO(qyearsley): Replace test_prefix_list everywhere with some 503 but only from builder-1.
506 sort of class that contains the same data. 504 TODO(qyearsley): Replace test_prefix_list everywhere
505 with some sort of class that contains the same data.
507 """ 506 """
508 if self._tool.git().has_working_directory_changes(pathspec=self._layout_ tests_dir()): 507 if self._tool.git().has_working_directory_changes(pathspec=self._layout_ tests_dir()):
509 _log.error('There are uncommitted changes in the layout tests direct ory; aborting.') 508 _log.error('There are uncommitted changes in the layout tests direct ory; aborting.')
510 return 509 return
511 510
512 for test, builds_to_check in sorted(test_prefix_list.items()): 511 for test, builds_to_check in sorted(test_prefix_list.items()):
513 _log.info('Rebaselining %s', test) 512 _log.info('Rebaselining %s', test)
514 for build, suffixes in sorted(builds_to_check.items()): 513 for build in sorted(builds_to_check):
515 _log.debug(' %s: %s', build, ','.join(suffixes)) 514 _log.debug(' %s', build)
516 515
517 copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = sel f._rebaseline_commands( 516 copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = sel f._rebaseline_commands(
518 test_prefix_list, options) 517 test_prefix_list, options)
519 lines_to_remove = {} 518 lines_to_remove = {}
520 519
521 self._run_in_parallel(copy_baseline_commands) 520 self._run_in_parallel(copy_baseline_commands)
522 lines_to_remove = self._run_in_parallel(rebaseline_commands) 521 lines_to_remove = self._run_in_parallel(rebaseline_commands)
523 522
524 for test in extra_lines_to_remove: 523 for test in extra_lines_to_remove:
525 if test in lines_to_remove: 524 if test in lines_to_remove:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 for path in baseline_paths: 557 for path in baseline_paths:
559 if not (filesystem.exists(path) and 558 if not (filesystem.exists(path) and
560 filesystem.splitext(path)[1] == '.txt'): 559 filesystem.splitext(path)[1] == '.txt'):
561 continue 560 continue
562 contents = filesystem.read_text_file(path) 561 contents = filesystem.read_text_file(path)
563 if is_all_pass_testharness_result(contents): 562 if is_all_pass_testharness_result(contents):
564 _log.info('Removing all-PASS testharness baseline: %s', path) 563 _log.info('Removing all-PASS testharness baseline: %s', path)
565 filesystem.remove(path) 564 filesystem.remove(path)
566 565
567 def _all_baseline_paths(self, test_prefix_list): 566 def _all_baseline_paths(self, test_prefix_list):
568 """Return file paths for all baselines for the given tests and builders. 567 """Returns file paths for all baselines for the given tests and builders .
569 568
570 Args: 569 Args:
571 test_prefix_list: A dict mapping test prefixes, which could be 570 test_prefix_list: A dict mapping test prefixes, which could be
572 directories or full test paths, to builds to baseline suffixes. 571 directories or full test paths, to Builds.
573 TODO(qyearsley): If a class is added to replace test_prefix_list , 572 TODO(qyearsley): If a class is added to replace
574 then this can be made a method on that class. 573 test_prefix_list, then this can be made a method on
574 that class.
575 575
576 Returns: 576 Returns:
577 A list of absolute paths to possible baseline files, 577 A list of absolute paths to possible baseline files,
578 which may or may not exist on the local filesystem. 578 which may or may not exist on the local filesystem.
579 """ 579 """
580 filesystem = self._tool.filesystem 580 filesystem = self._tool.filesystem
581 baseline_paths = [] 581 baseline_paths = []
582 port = self._tool.port_factory.get() 582 port = self._tool.port_factory.get()
583 583
584 for test_prefix in test_prefix_list: 584 for test_prefix in test_prefix_list:
585 tests = port.tests([test_prefix]) 585 tests = port.tests([test_prefix])
586 all_suffixes = set()
587 586
588 for build, suffixes in test_prefix_list[test_prefix].iteritems(): 587 for build in test_prefix_list[test_prefix]:
589 all_suffixes.update(suffixes)
590 port_baseline_dir = self._baseline_directory(build.builder_name) 588 port_baseline_dir = self._baseline_directory(build.builder_name)
591 baseline_paths.extend([ 589 baseline_paths.extend([
592 filesystem.join(port_baseline_dir, self._file_name_for_expec ted_result(test, suffix)) 590 filesystem.join(port_baseline_dir, self._file_name_for_expec ted_result(test, suffix))
593 for test in tests for suffix in suffixes 591 for test in tests for suffix in BASELINE_SUFFIX_LIST
594 ]) 592 ])
595 593
596 baseline_paths.extend([ 594 baseline_paths.extend([
597 filesystem.join(self._layout_tests_dir(), self._file_name_for_ex pected_result(test, suffix)) 595 filesystem.join(self._layout_tests_dir(), self._file_name_for_ex pected_result(test, suffix))
598 for test in tests for suffix in all_suffixes 596 for test in tests for suffix in BASELINE_SUFFIX_LIST
599 ]) 597 ])
600 598
601 return sorted(baseline_paths) 599 return sorted(baseline_paths)
602 600
603 def _layout_tests_dir(self): 601 def _layout_tests_dir(self):
604 return self._tool.port_factory.get().layout_tests_dir() 602 return self._tool.port_factory.get().layout_tests_dir()
605 603
606 def _suffixes_for_actual_failures(self, test, build, existing_suffixes): 604 def _suffixes_for_actual_failures(self, test, build):
607 """Gets the baseline suffixes for actual mismatch failures in some resul ts. 605 """Gets the baseline suffixes for actual mismatch failures in some resul ts.
608 606
609 Args: 607 Args:
610 test: A full test path string. 608 test: A full test path string.
611 build: A Build object. 609 build: A Build object.
612 existing_suffixes: A collection of all suffixes to consider.
613 610
614 Returns: 611 Returns:
615 A set of file suffix strings. 612 A set of file suffix strings.
616 """ 613 """
617 results = self._tool.buildbot.fetch_results(build) 614 results = self._tool.buildbot.fetch_results(build)
618 if not results: 615 if not results:
619 _log.debug('No results found for build %s', build) 616 _log.debug('No results found for build %s', build)
620 return set() 617 return set()
621 test_result = results.result_for_test(test) 618 test_result = results.result_for_test(test)
622 if not test_result: 619 if not test_result:
623 _log.debug('No test result for test %s in build %s', test, build) 620 _log.debug('No test result for test %s in build %s', test, build)
624 return set() 621 return set()
625 return set(existing_suffixes) & TestExpectations.suffixes_for_test_resul t(test_result) 622 return TestExpectations.suffixes_for_test_result(test_result)
626 623
627 624
628 class RebaselineJson(AbstractParallelRebaselineCommand): 625 class RebaselineJson(AbstractParallelRebaselineCommand):
629 name = 'rebaseline-json' 626 name = 'rebaseline-json'
630 help_text = 'Rebaseline based off JSON passed to stdin. Intended to only be called from other scripts.' 627 help_text = 'Rebaseline based off JSON passed to stdin. Intended to only be called from other scripts.'
631 628
632 def __init__(self,): 629 def __init__(self,):
633 super(RebaselineJson, self).__init__(options=[ 630 super(RebaselineJson, self).__init__(options=[
634 self.no_optimize_option, 631 self.no_optimize_option,
635 self.results_directory_option, 632 self.results_directory_option,
(...skipping 10 matching lines...) Expand all
646 show_in_main_help = True 643 show_in_main_help = True
647 644
648 def __init__(self): 645 def __init__(self):
649 super(RebaselineExpectations, self).__init__(options=[ 646 super(RebaselineExpectations, self).__init__(options=[
650 self.no_optimize_option, 647 self.no_optimize_option,
651 ] + self.platform_options) 648 ] + self.platform_options)
652 self._test_prefix_list = None 649 self._test_prefix_list = None
653 650
654 @staticmethod 651 @staticmethod
655 def _tests_to_rebaseline(port): 652 def _tests_to_rebaseline(port):
656 tests_to_rebaseline = {} 653 tests_to_rebaseline = []
657 for path, value in port.expectations_dict().items(): 654 for path, value in port.expectations_dict().items():
658 expectations = TestExpectations(port, include_overrides=False, expec tations_dict={path: value}) 655 expectations = TestExpectations(port, include_overrides=False, expec tations_dict={path: value})
659 for test in expectations.get_rebaselining_failures(): 656 for test in expectations.get_rebaselining_failures():
660 suffixes = TestExpectations.suffixes_for_expectations(expectatio ns.get_expectations(test)) 657 tests_to_rebaseline.append(test)
661 tests_to_rebaseline[test] = suffixes or BASELINE_SUFFIX_LIST
662 return tests_to_rebaseline 658 return tests_to_rebaseline
663 659
664 def _add_tests_to_rebaseline(self, port_name): 660 def _add_tests_to_rebaseline(self, port_name):
665 builder_name = self._tool.builders.builder_name_for_port_name(port_name) 661 builder_name = self._tool.builders.builder_name_for_port_name(port_name)
666 if not builder_name: 662 if not builder_name:
667 return 663 return
668 tests = self._tests_to_rebaseline(self._tool.port_factory.get(port_name) ).items() 664 tests = self._tests_to_rebaseline(self._tool.port_factory.get(port_name) )
669 665
670 if tests: 666 if tests:
671 _log.info('Retrieving results for %s from %s.', port_name, builder_n ame) 667 _log.info('Retrieving results for %s from %s.', port_name, builder_n ame)
672 668
673 for test_name, suffixes in tests: 669 for test_name in tests:
674 _log.info(' %s (%s)', test_name, ','.join(suffixes)) 670 _log.info(' %s', test_name)
675 if test_name not in self._test_prefix_list: 671 if test_name not in self._test_prefix_list:
676 self._test_prefix_list[test_name] = {} 672 self._test_prefix_list[test_name] = []
677 self._test_prefix_list[test_name][Build(builder_name)] = suffixes 673 self._test_prefix_list[test_name].append(Build(builder_name))
678 674
679 def execute(self, options, args, tool): 675 def execute(self, options, args, tool):
680 self._tool = tool 676 self._tool = tool
681 options.results_directory = None 677 options.results_directory = None
682 self._test_prefix_list = {} 678 self._test_prefix_list = {}
683 port_names = tool.port_factory.all_port_names(options.platform) 679 port_names = tool.port_factory.all_port_names(options.platform)
684 for port_name in port_names: 680 for port_name in port_names:
685 self._add_tests_to_rebaseline(port_name) 681 self._add_tests_to_rebaseline(port_name)
686 if not self._test_prefix_list: 682 if not self._test_prefix_list:
687 _log.warning('Did not find any tests marked Rebaseline.') 683 _log.warning('Did not find any tests marked Rebaseline.')
688 return 684 return
689 685
690 self.rebaseline(options, self._test_prefix_list) 686 self.rebaseline(options, self._test_prefix_list)
691 687
692 688
693 class Rebaseline(AbstractParallelRebaselineCommand): 689 class Rebaseline(AbstractParallelRebaselineCommand):
694 name = 'rebaseline' 690 name = 'rebaseline'
695 help_text = 'Rebaseline tests with results from the build bots.' 691 help_text = 'Rebaseline tests with results from the build bots.'
696 show_in_main_help = True 692 show_in_main_help = True
697 argument_names = '[TEST_NAMES]' 693 argument_names = '[TEST_NAMES]'
698 694
699 def __init__(self): 695 def __init__(self):
700 super(Rebaseline, self).__init__(options=[ 696 super(Rebaseline, self).__init__(options=[
701 self.no_optimize_option, 697 self.no_optimize_option,
702 # FIXME: should we support the platform options in addition to (or i nstead of) --builders? 698 # FIXME: should we support the platform options in addition to (or i nstead of) --builders?
703 self.suffixes_option,
704 self.results_directory_option, 699 self.results_directory_option,
705 optparse.make_option('--builders', default=None, action='append', 700 optparse.make_option('--builders', default=None, action='append',
706 help=('Comma-separated-list of builders to pull new baselines from ' 701 help=('Comma-separated-list of builders to pull new baselines from '
707 '(can also be provided multiple times).') ), 702 '(can also be provided multiple times).') ),
708 ]) 703 ])
709 704
710 def _builders_to_pull_from(self): 705 def _builders_to_pull_from(self):
711 return self._tool.user.prompt_with_list( 706 return self._tool.user.prompt_with_list(
712 'Which builder to pull results from:', self._release_builders(), can _choose_multiple=True) 707 'Which builder to pull results from:', self._release_builders(), can _choose_multiple=True)
713 708
714 def execute(self, options, args, tool): 709 def execute(self, options, args, tool):
715 self._tool = tool 710 self._tool = tool
716 if not args: 711 if not args:
717 _log.error('Must list tests to rebaseline.') 712 _log.error('Must list tests to rebaseline.')
718 return 713 return
719 714
720 if options.builders: 715 if options.builders:
721 builders_to_check = [] 716 builders_to_check = []
722 for builder_names in options.builders: 717 for builder_names in options.builders:
723 builders_to_check += builder_names.split(',') 718 builders_to_check += builder_names.split(',')
724 else: 719 else:
725 builders_to_check = self._builders_to_pull_from() 720 builders_to_check = self._builders_to_pull_from()
726 721
727 test_prefix_list = {} 722 test_prefix_list = {}
728 suffixes_to_update = options.suffixes.split(',')
729 723
730 for builder in builders_to_check: 724 for builder in builders_to_check:
731 for test in args: 725 for test in args:
732 if test not in test_prefix_list: 726 if test not in test_prefix_list:
733 test_prefix_list[test] = {} 727 test_prefix_list[test] = []
734 build = Build(builder) 728 test_prefix_list[test].append(Build(builder))
735 test_prefix_list[test][build] = suffixes_to_update
736 729
737 if options.verbose: 730 if options.verbose:
738 _log.debug('rebaseline-json: ' + str(test_prefix_list)) 731 _log.debug('rebaseline-json: ' + str(test_prefix_list))
739 732
740 self.rebaseline(options, test_prefix_list) 733 self.rebaseline(options, test_prefix_list)
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Tools/Scripts/webkitpy/tool/commands/rebaseline_cl.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698