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 |