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