| 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 (1) files that have been added or removed. | 77 (1) files that have been added or removed. |
| 78 (2) lines to remove from TestExpectations. | 78 (2) lines to remove from TestExpectations. |
| 79 | 79 |
| 80 The reason for keeping track of these changes together is that after rebasel
ining | 80 The reason for keeping track of these changes together is that after rebasel
ining |
| 81 many tests in parallel by subprocesses, we can update the git staged files l
ist | 81 many tests in parallel by subprocesses, we can update the git staged files l
ist |
| 82 and the TestExpectations all at once at the end. | 82 and the TestExpectations all at once at the end. |
| 83 | 83 |
| 84 Each subprocess can communicate some set of changes by outputting JSON lines
, | 84 Each subprocess can communicate some set of changes by outputting JSON lines
, |
| 85 and another process can aggregate the changes. | 85 and another process can aggregate the changes. |
| 86 | 86 |
| 87 TODO(qyearsley): Refactor this so that: | 87 TODO(qyearsley): Refactor this so that lines to remove are only tracked in o
ne format. |
| 88 - lines to remove are only tracked in one format. | |
| 89 - files to add and delete are always disjoint sets. | |
| 90 """ | 88 """ |
| 91 def __init__(self, files_to_add=None, files_to_delete=None, lines_to_remove=
None): | 89 def __init__(self, files_to_add=None, files_to_delete=None, lines_to_remove=
None): |
| 92 self._files_to_add = set(files_to_add or []) | 90 self._files_to_add = set(files_to_add or []) |
| 93 self._files_to_delete = set(files_to_delete or []) | 91 self._files_to_delete = set(files_to_delete or []) |
| 94 lines_to_remove = lines_to_remove or {} | 92 lines_to_remove = lines_to_remove or {} |
| 95 self._lines_to_remove = {t: set(builders) for t, builders in lines_to_re
move.iteritems()} | 93 self._lines_to_remove = {t: set(builders) for t, builders in lines_to_re
move.iteritems()} |
| 96 | 94 |
| 97 def add_file(self, path): | 95 def add_file(self, path): |
| 98 self._files_to_add.add(path) | 96 self._files_to_add.add(path) |
| 99 | 97 |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 408 cmd_line.extend(['--results-directory', options.results_
directory]) | 406 cmd_line.extend(['--results-directory', options.results_
directory]) |
| 409 if options.verbose: | 407 if options.verbose: |
| 410 cmd_line.append('--verbose') | 408 cmd_line.append('--verbose') |
| 411 copy_baseline_commands.append( | 409 copy_baseline_commands.append( |
| 412 tuple([[self._tool.executable, path_to_webkit_patch, 'co
py-existing-baselines-internal'] + cmd_line, cwd])) | 410 tuple([[self._tool.executable, path_to_webkit_patch, 'co
py-existing-baselines-internal'] + cmd_line, cwd])) |
| 413 rebaseline_commands.append( | 411 rebaseline_commands.append( |
| 414 tuple([[self._tool.executable, path_to_webkit_patch, 're
baseline-test-internal'] + cmd_line, cwd])) | 412 tuple([[self._tool.executable, path_to_webkit_patch, 're
baseline-test-internal'] + cmd_line, cwd])) |
| 415 return copy_baseline_commands, rebaseline_commands, lines_to_remove | 413 return copy_baseline_commands, rebaseline_commands, lines_to_remove |
| 416 | 414 |
| 417 @staticmethod | 415 @staticmethod |
| 418 def _serial_commands(command_results): | 416 def _extract_scm_changes(command_results): |
| 419 """Parses the JSON lines from command output to extract SCM changes. | 417 """Parses the JSON lines from sub-command output and returns the result
as a ChangeSet.""" |
| 420 | |
| 421 TODO(qyearsley): Refactor and rename this function. | |
| 422 """ | |
| 423 change_set = ChangeSet() | 418 change_set = ChangeSet() |
| 424 for output in [result[1].split('\n') for result in command_results]: | 419 for _, stdout, _ in command_results: |
| 425 file_added = False | 420 updated = False |
| 426 for line in output: | 421 for line in filter(None, stdout.splitlines()): |
| 427 try: | 422 try: |
| 428 if line: | 423 parsed_line = json.loads(line) |
| 429 parsed_line = json.loads(line) | 424 change_set.update(ChangeSet.from_dict(parsed_line)) |
| 430 change_set.update(ChangeSet.from_dict(parsed_line)) | 425 updated = True |
| 431 file_added = True | |
| 432 except ValueError: | 426 except ValueError: |
| 433 _log.debug('"%s" is not a JSON object, ignoring', line) | 427 _log.debug('"%s" is not a JSON object, ignoring', line) |
| 434 | 428 if not updated: |
| 435 if not file_added: | 429 # TODO(qyearsley): This probably should be an error. See http://
crbug.com/649412. |
| 436 _log.debug('Could not add file based off output "%s"', output) | 430 _log.debug('Could not add file based off output "%s"', stdout) |
| 437 | |
| 438 return change_set | 431 return change_set |
| 439 | 432 |
| 440 def _optimize_baselines(self, test_prefix_list, verbose=False): | 433 def _optimize_baselines(self, test_prefix_list, verbose=False): |
| 441 optimize_commands = [] | 434 optimize_commands = [] |
| 442 for test in test_prefix_list: | 435 for test in test_prefix_list: |
| 443 all_suffixes = set() | 436 all_suffixes = set() |
| 444 builders_to_fetch_from = self._builders_to_fetch_from(self._builder_
names(test_prefix_list[test])) | 437 builders_to_fetch_from = self._builders_to_fetch_from(self._builder_
names(test_prefix_list[test])) |
| 445 for build in sorted(test_prefix_list[test]): | 438 for build in sorted(test_prefix_list[test]): |
| 446 if build.builder_name not in builders_to_fetch_from: | 439 if build.builder_name not in builders_to_fetch_from: |
| 447 break | 440 break |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 if fs.exists(smoke_test_filename) and test not in fs.read_text_file(
smoke_test_filename): | 496 if fs.exists(smoke_test_filename) and test not in fs.read_text_file(
smoke_test_filename): |
| 504 return True | 497 return True |
| 505 | 498 |
| 506 return (SKIP in full_expectations.get_expectations(test) and | 499 return (SKIP in full_expectations.get_expectations(test) and |
| 507 SKIP not in generic_expectations.get_expectations(test)) | 500 SKIP not in generic_expectations.get_expectations(test)) |
| 508 | 501 |
| 509 def _run_in_parallel(self, commands): | 502 def _run_in_parallel(self, commands): |
| 510 if not commands: | 503 if not commands: |
| 511 return ChangeSet() | 504 return ChangeSet() |
| 512 | 505 |
| 513 # TODO(qyearsley): Refactor this block. | |
| 514 command_results = self._tool.executive.run_in_parallel(commands) | 506 command_results = self._tool.executive.run_in_parallel(commands) |
| 515 log_output = '\n'.join(result[2] for result in command_results).replace(
'\n\n', '\n') | 507 for _, _, stderr in command_results: |
| 516 for line in log_output.split('\n'): | 508 if stderr: |
| 517 if line: | 509 _log.error(stderr) |
| 518 _log.error(line) | |
| 519 | 510 |
| 520 return self._serial_commands(command_results) | 511 return self._extract_scm_changes(command_results) |
| 521 | 512 |
| 522 def _rebaseline(self, options, test_prefix_list): | 513 def _rebaseline(self, options, test_prefix_list): |
| 523 """Downloads new baselines in parallel, then updates expectations files | 514 """Downloads new baselines in parallel, then updates expectations files |
| 524 and optimizes baselines. | 515 and optimizes baselines. |
| 525 | 516 |
| 526 Args: | 517 Args: |
| 527 options: An object with the options passed to the current command. | 518 options: An object with the options passed to the current command. |
| 528 test_prefix_list: A map of test names to Build objects to file suffi
xes | 519 test_prefix_list: A map of test names to Build objects to file suffi
xes |
| 529 for new baselines. For example: | 520 for new baselines. For example: |
| 530 { | 521 { |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 for test in args: | 684 for test in args: |
| 694 if test not in test_prefix_list: | 685 if test not in test_prefix_list: |
| 695 test_prefix_list[test] = {} | 686 test_prefix_list[test] = {} |
| 696 build = Build(builder) | 687 build = Build(builder) |
| 697 test_prefix_list[test][build] = suffixes_to_update | 688 test_prefix_list[test][build] = suffixes_to_update |
| 698 | 689 |
| 699 if options.verbose: | 690 if options.verbose: |
| 700 _log.debug("rebaseline-json: " + str(test_prefix_list)) | 691 _log.debug("rebaseline-json: " + str(test_prefix_list)) |
| 701 | 692 |
| 702 self._rebaseline(options, test_prefix_list) | 693 self._rebaseline(options, test_prefix_list) |
| OLD | NEW |