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

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

Issue 2397573002: Don't track SCM changes in rebaseline commands. (Closed)
Patch Set: Update message and docstring for has_working_directory_changes Created 4 years, 2 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
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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 platform_options = factory.platform_options(use_globs=True) 56 platform_options = factory.platform_options(use_globs=True)
57 57
58 results_directory_option = optparse.make_option("--results-directory", help= "Local results directory to use.") 58 results_directory_option = optparse.make_option("--results-directory", help= "Local results directory to use.")
59 59
60 suffixes_option = optparse.make_option("--suffixes", default=','.join(BASELI NE_SUFFIX_LIST), action="store", 60 suffixes_option = optparse.make_option("--suffixes", default=','.join(BASELI NE_SUFFIX_LIST), action="store",
61 help="Comma-separated-list of file ty pes to rebaseline.") 61 help="Comma-separated-list of file ty pes to rebaseline.")
62 62
63 def __init__(self, options=None): 63 def __init__(self, options=None):
64 super(AbstractRebaseliningCommand, self).__init__(options=options) 64 super(AbstractRebaseliningCommand, self).__init__(options=options)
65 self._baseline_suffix_list = BASELINE_SUFFIX_LIST 65 self._baseline_suffix_list = BASELINE_SUFFIX_LIST
66 self._scm_changes = ChangeSet() 66 self.expectation_line_changes = ChangeSet()
67 self._tool = None 67 self._tool = None
68 68
69 def _print_scm_changes(self): 69 def _print_expectation_line_changes(self):
70 print(json.dumps(self._scm_changes.to_dict())) 70 print(json.dumps(self.expectation_line_changes.to_dict()))
71 71
72 72
73 class ChangeSet(object): 73 class ChangeSet(object):
74 """A record of added and deleted files and TestExpectation lines to remove. 74 """A record of TestExpectation lines to remove.
75 75
76 This class groups two kinds of changes together: 76 TODO(qyearsley): Remove this class, track list of lines to remove directly
77 (1) files that have been added or removed. 77 in an attribute of AbstractRebaseliningCommand.
78 (2) lines to remove from TestExpectations.
79
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
82 and the TestExpectations all at once at the end.
83
84 Each subprocess can communicate some set of changes by outputting JSON lines ,
85 and another process can aggregate the changes.
86
87 TODO(qyearsley): Refactor this so that lines to remove are only tracked in o ne format.
88 """ 78 """
89 def __init__(self, files_to_add=None, files_to_delete=None, lines_to_remove= None): 79 def __init__(self, lines_to_remove=None):
90 self.files_to_add = files_to_add or []
91 self.files_to_delete = files_to_delete or []
92 self.lines_to_remove = lines_to_remove or {} 80 self.lines_to_remove = lines_to_remove or {}
93 81
94 def add_file(self, path):
95 self.files_to_add.append(path)
96
97 def delete_file(self, path):
98 self.files_to_delete.append(path)
99
100 def remove_line(self, test, builder): 82 def remove_line(self, test, builder):
101 if test not in self.lines_to_remove: 83 if test not in self.lines_to_remove:
102 self.lines_to_remove[test] = [] 84 self.lines_to_remove[test] = []
103 self.lines_to_remove[test].append(builder) 85 self.lines_to_remove[test].append(builder)
104 86
105 def to_dict(self): 87 def to_dict(self):
106 remove_lines = [] 88 remove_lines = []
107 for test in self.lines_to_remove: 89 for test in self.lines_to_remove:
108 for builder in self.lines_to_remove[test]: 90 for builder in self.lines_to_remove[test]:
109 remove_lines.append({'test': test, 'builder': builder}) 91 remove_lines.append({'test': test, 'builder': builder})
110 return { 92 return {'remove-lines': remove_lines}
111 'add': list(self.files_to_add),
112 'delete': list(self.files_to_delete),
113 'remove-lines': remove_lines,
114 }
115 93
116 @staticmethod 94 @staticmethod
117 def from_dict(change_dict): 95 def from_dict(change_dict):
118 files_to_add = set()
119 files_to_delete = set()
120 lines_to_remove = {} 96 lines_to_remove = {}
121 if 'add' in change_dict:
122 files_to_add.update(change_dict['add'])
123 if 'delete' in change_dict:
124 files_to_delete.update(change_dict['delete'])
125 if 'remove-lines' in change_dict: 97 if 'remove-lines' in change_dict:
126 for line_to_remove in change_dict['remove-lines']: 98 for line_to_remove in change_dict['remove-lines']:
127 test = line_to_remove['test'] 99 test = line_to_remove['test']
128 builder = line_to_remove['builder'] 100 builder = line_to_remove['builder']
129 if test not in lines_to_remove: 101 if test not in lines_to_remove:
130 lines_to_remove[test] = [] 102 lines_to_remove[test] = []
131 lines_to_remove[test].append(builder) 103 lines_to_remove[test].append(builder)
132 return ChangeSet( 104 return ChangeSet(lines_to_remove=lines_to_remove)
133 files_to_add=list(files_to_add),
134 files_to_delete=list(files_to_delete),
135 lines_to_remove=lines_to_remove)
136 105
137 def update(self, other): 106 def update(self, other):
138 assert isinstance(other, ChangeSet) 107 assert isinstance(other, ChangeSet)
139 assert type(other.lines_to_remove) is dict 108 assert type(other.lines_to_remove) is dict
140 self.files_to_add.extend(other.files_to_add)
141 self.files_to_delete.extend(other.files_to_delete)
142 for test in other.lines_to_remove: 109 for test in other.lines_to_remove:
143 if test not in self.lines_to_remove: 110 if test not in self.lines_to_remove:
144 self.lines_to_remove[test] = [] 111 self.lines_to_remove[test] = []
145 self.lines_to_remove[test].extend(other.lines_to_remove[test]) 112 self.lines_to_remove[test].extend(other.lines_to_remove[test])
146 113
147 114
148 class BaseInternalRebaselineCommand(AbstractRebaseliningCommand): 115 class BaseInternalRebaselineCommand(AbstractRebaseliningCommand):
149 """Base class for rebaseline-related commands that are intended to be used b y other commands.""" 116 """Base class for rebaseline-related commands that are intended to be used b y other commands."""
150 # Not overriding execute() - pylint: disable=abstract-method 117 # Not overriding execute() - pylint: disable=abstract-method
151 118
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 old_baselines.append(old_baseline) 198 old_baselines.append(old_baseline)
232 new_baselines.append(new_baseline) 199 new_baselines.append(new_baseline)
233 200
234 for i in range(len(old_baselines)): 201 for i in range(len(old_baselines)):
235 old_baseline = old_baselines[i] 202 old_baseline = old_baselines[i]
236 new_baseline = new_baselines[i] 203 new_baseline = new_baselines[i]
237 204
238 _log.debug("Copying baseline from %s to %s.", old_baseline, new_base line) 205 _log.debug("Copying baseline from %s to %s.", old_baseline, new_base line)
239 self._tool.filesystem.maybe_make_directory(self._tool.filesystem.dir name(new_baseline)) 206 self._tool.filesystem.maybe_make_directory(self._tool.filesystem.dir name(new_baseline))
240 self._tool.filesystem.copyfile(old_baseline, new_baseline) 207 self._tool.filesystem.copyfile(old_baseline, new_baseline)
241 if not self._tool.scm().exists(new_baseline):
242 self._scm_changes.add_file(new_baseline)
243 208
244 def execute(self, options, args, tool): 209 def execute(self, options, args, tool):
245 self._tool = tool 210 self._tool = tool
246 for suffix in options.suffixes.split(','): 211 for suffix in options.suffixes.split(','):
247 self._copy_existing_baseline(options.builder, options.test, suffix) 212 self._copy_existing_baseline(options.builder, options.test, suffix)
248 self._print_scm_changes()
249 213
250 214
251 class RebaselineTest(BaseInternalRebaselineCommand): 215 class RebaselineTest(BaseInternalRebaselineCommand):
252 name = "rebaseline-test-internal" 216 name = "rebaseline-test-internal"
253 help_text = "Rebaseline a single test from a buildbot. Only intended for use by other webkit-patch commands." 217 help_text = "Rebaseline a single test from a buildbot. Only intended for use by other webkit-patch commands."
254 218
255 def _save_baseline(self, data, target_baseline): 219 def _save_baseline(self, data, target_baseline):
256 if not data: 220 if not data:
257 _log.debug("No baseline data to save.") 221 _log.debug("No baseline data to save.")
258 return 222 return
259 223
260 filesystem = self._tool.filesystem 224 filesystem = self._tool.filesystem
261 filesystem.maybe_make_directory(filesystem.dirname(target_baseline)) 225 filesystem.maybe_make_directory(filesystem.dirname(target_baseline))
262 filesystem.write_binary_file(target_baseline, data) 226 filesystem.write_binary_file(target_baseline, data)
263 if not self._tool.scm().exists(target_baseline):
264 self._scm_changes.add_file(target_baseline)
265 227
266 def _rebaseline_test(self, builder_name, test_name, suffix, results_url): 228 def _rebaseline_test(self, builder_name, test_name, suffix, results_url):
267 baseline_directory = self._baseline_directory(builder_name) 229 baseline_directory = self._baseline_directory(builder_name)
268 230
269 source_baseline = "%s/%s" % (results_url, self._file_name_for_actual_res ult(test_name, suffix)) 231 source_baseline = "%s/%s" % (results_url, self._file_name_for_actual_res ult(test_name, suffix))
270 target_baseline = self._tool.filesystem.join(baseline_directory, self._f ile_name_for_expected_result(test_name, suffix)) 232 target_baseline = self._tool.filesystem.join(baseline_directory, self._f ile_name_for_expected_result(test_name, suffix))
271 233
272 _log.debug("Retrieving source %s for target %s.", source_baseline, targe t_baseline) 234 _log.debug("Retrieving source %s for target %s.", source_baseline, targe t_baseline)
273 self._save_baseline(self._tool.web.get_binary(source_baseline, convert_4 04_to_None=True), 235 self._save_baseline(self._tool.web.get_binary(source_baseline, convert_4 04_to_None=True),
274 target_baseline) 236 target_baseline)
275 237
276 def _rebaseline_test_and_update_expectations(self, options): 238 def _rebaseline_test_and_update_expectations(self, options):
277 self._baseline_suffix_list = options.suffixes.split(',') 239 self._baseline_suffix_list = options.suffixes.split(',')
278 240
279 port = self._tool.port_factory.get_from_builder_name(options.builder) 241 port = self._tool.port_factory.get_from_builder_name(options.builder)
280 if port.reference_files(options.test): 242 if port.reference_files(options.test):
281 if 'png' in self._baseline_suffix_list: 243 if 'png' in self._baseline_suffix_list:
282 _log.warning("Cannot rebaseline image result for reftest: %s", o ptions.test) 244 _log.warning("Cannot rebaseline image result for reftest: %s", o ptions.test)
283 return 245 return
284 assert self._baseline_suffix_list == ['txt'] 246 assert self._baseline_suffix_list == ['txt']
285 247
286 if options.results_directory: 248 if options.results_directory:
287 results_url = 'file://' + options.results_directory 249 results_url = 'file://' + options.results_directory
288 else: 250 else:
289 results_url = self._tool.buildbot.results_url(options.builder, build _number=options.build_number) 251 results_url = self._tool.buildbot.results_url(options.builder, build _number=options.build_number)
290 252
291 for suffix in self._baseline_suffix_list: 253 for suffix in self._baseline_suffix_list:
292 self._rebaseline_test(options.builder, options.test, suffix, results _url) 254 self._rebaseline_test(options.builder, options.test, suffix, results _url)
293 self._scm_changes.remove_line(test=options.test, builder=options.builder ) 255 self.expectation_line_changes.remove_line(test=options.test, builder=opt ions.builder)
294 256
295 def execute(self, options, args, tool): 257 def execute(self, options, args, tool):
296 self._tool = tool 258 self._tool = tool
297 self._rebaseline_test_and_update_expectations(options) 259 self._rebaseline_test_and_update_expectations(options)
298 self._print_scm_changes() 260 self._print_expectation_line_changes()
299 261
300 262
301 class AbstractParallelRebaselineCommand(AbstractRebaseliningCommand): 263 class AbstractParallelRebaselineCommand(AbstractRebaseliningCommand):
302 """Base class for rebaseline commands that do some tasks in parallel.""" 264 """Base class for rebaseline commands that do some tasks in parallel."""
303 # Not overriding execute() - pylint: disable=abstract-method 265 # Not overriding execute() - pylint: disable=abstract-method
304 266
305 def __init__(self, options=None): 267 def __init__(self, options=None):
306 super(AbstractParallelRebaselineCommand, self).__init__(options=options) 268 super(AbstractParallelRebaselineCommand, self).__init__(options=options)
307 269
308 def _release_builders(self): 270 def _release_builders(self):
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 if build_number: 360 if build_number:
399 args.extend(['--build-number', str(build_number)]) 361 args.extend(['--build-number', str(build_number)])
400 if options.results_directory: 362 if options.results_directory:
401 args.extend(['--results-directory', options.results_dire ctory]) 363 args.extend(['--results-directory', options.results_dire ctory])
402 364
403 rebaseline_commands.append( 365 rebaseline_commands.append(
404 tuple([[self._tool.executable, path_to_webkit_patch, 're baseline-test-internal'] + args, cwd])) 366 tuple([[self._tool.executable, path_to_webkit_patch, 're baseline-test-internal'] + args, cwd]))
405 return copy_baseline_commands, rebaseline_commands, lines_to_remove 367 return copy_baseline_commands, rebaseline_commands, lines_to_remove
406 368
407 @staticmethod 369 @staticmethod
408 def _extract_scm_changes(command_results): 370 def _extract_expectation_line_changes(command_results):
409 """Parses the JSON lines from sub-command output and returns the result as a ChangeSet.""" 371 """Parses the JSON lines from sub-command output and returns the result as a ChangeSet."""
410 change_set = ChangeSet() 372 change_set = ChangeSet()
411 for _, stdout, _ in command_results: 373 for _, stdout, _ in command_results:
412 updated = False 374 updated = False
413 for line in filter(None, stdout.splitlines()): 375 for line in filter(None, stdout.splitlines()):
414 try: 376 try:
415 parsed_line = json.loads(line) 377 parsed_line = json.loads(line)
416 change_set.update(ChangeSet.from_dict(parsed_line)) 378 change_set.update(ChangeSet.from_dict(parsed_line))
417 updated = True 379 updated = True
418 except ValueError: 380 except ValueError:
(...skipping 11 matching lines...) Expand all
430 for build in sorted(test_prefix_list[test]): 392 for build in sorted(test_prefix_list[test]):
431 if build.builder_name not in builders_to_fetch_from: 393 if build.builder_name not in builders_to_fetch_from:
432 break 394 break
433 all_suffixes.update(self._suffixes_for_actual_failures(test, bui ld, test_prefix_list[test][build])) 395 all_suffixes.update(self._suffixes_for_actual_failures(test, bui ld, test_prefix_list[test][build]))
434 396
435 # No need to optimize baselines for a test with no failures. 397 # No need to optimize baselines for a test with no failures.
436 if not all_suffixes: 398 if not all_suffixes:
437 continue 399 continue
438 400
439 # FIXME: We should propagate the platform options as well. 401 # FIXME: We should propagate the platform options as well.
440 cmd_line = ['--no-modify-scm', '--suffixes', ','.join(all_suffixes), test] 402 cmd_line = ['--suffixes', ','.join(all_suffixes), test]
441 if verbose: 403 if verbose:
442 cmd_line.append('--verbose') 404 cmd_line.append('--verbose')
443 405
444 path_to_webkit_patch = self._tool.path() 406 path_to_webkit_patch = self._tool.path()
445 cwd = self._tool.scm().checkout_root 407 cwd = self._tool.scm().checkout_root
446 optimize_commands.append(tuple([[self._tool.executable, path_to_webk it_patch, 'optimize-baselines'] + cmd_line, cwd])) 408 optimize_commands.append(tuple([[self._tool.executable, path_to_webk it_patch, 'optimize-baselines'] + cmd_line, cwd]))
447 return optimize_commands 409 return optimize_commands
448 410
449 def _update_expectations_files(self, lines_to_remove): 411 def _update_expectations_files(self, lines_to_remove):
450 # FIXME: This routine is way too expensive. We're creating O(n ports) Te stExpectations objects. 412 # FIXME: This routine is way too expensive. We're creating O(n ports) Te stExpectations objects.
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 def _port_skips_test(port, test, generic_expectations, full_expectations): 446 def _port_skips_test(port, test, generic_expectations, full_expectations):
485 fs = port.host.filesystem 447 fs = port.host.filesystem
486 if port.default_smoke_test_only(): 448 if port.default_smoke_test_only():
487 smoke_test_filename = fs.join(port.layout_tests_dir(), 'SmokeTests') 449 smoke_test_filename = fs.join(port.layout_tests_dir(), 'SmokeTests')
488 if fs.exists(smoke_test_filename) and test not in fs.read_text_file( smoke_test_filename): 450 if fs.exists(smoke_test_filename) and test not in fs.read_text_file( smoke_test_filename):
489 return True 451 return True
490 452
491 return (SKIP in full_expectations.get_expectations(test) and 453 return (SKIP in full_expectations.get_expectations(test) and
492 SKIP not in generic_expectations.get_expectations(test)) 454 SKIP not in generic_expectations.get_expectations(test))
493 455
494 def _run_in_parallel(self, commands, update_scm=True): 456 def _run_in_parallel(self, commands):
495 if not commands: 457 if not commands:
496 return {} 458 return {}
497 459
498 command_results = self._tool.executive.run_in_parallel(commands) 460 command_results = self._tool.executive.run_in_parallel(commands)
499 for _, _, stderr in command_results: 461 for _, _, stderr in command_results:
500 if stderr: 462 if stderr:
501 _log.error(stderr) 463 _log.error(stderr)
502 464
503 change_set = self._extract_scm_changes(command_results) 465 change_set = self._extract_expectation_line_changes(command_results)
504
505 # TODO(qyearsley): Instead of updating the SCM state here, aggregate cha nges
506 # and update once in rebaseline. See http://crbug.com/639410.
507 if update_scm:
508 if change_set.files_to_delete:
509 self._tool.scm().delete_list(change_set.files_to_delete)
510 if change_set.files_to_add:
511 self._tool.scm().add_list(change_set.files_to_add)
512 466
513 return change_set.lines_to_remove 467 return change_set.lines_to_remove
514 468
515 def rebaseline(self, options, test_prefix_list, update_scm=True): 469 def rebaseline(self, options, test_prefix_list):
516 """Downloads new baselines in parallel, then updates expectations files 470 """Downloads new baselines in parallel, then updates expectations files
517 and optimizes baselines. 471 and optimizes baselines.
518 472
519 Args: 473 Args:
520 options: An object with the options passed to the current command. 474 options: An object with the options passed to the current command.
521 test_prefix_list: A map of test names to Build objects to file suffi xes 475 test_prefix_list: A map of test names to Build objects to file suffi xes
522 for new baselines. For example: 476 for new baselines. For example:
523 { 477 {
524 "some/test.html": {Build("builder-1", 412): ["txt"], Build(" builder-2", 100): ["txt"]}, 478 "some/test.html": {Build("builder-1", 412): ["txt"], Build(" builder-2", 100): ["txt"]},
525 "some/other.html": {Build("builder-1", 412): ["txt"]} 479 "some/other.html": {Build("builder-1", 412): ["txt"]}
526 } 480 }
527 This would mean that new text baselines should be downloaded for 481 This would mean that new text baselines should be downloaded for
528 "some/test.html" on both builder-1 (build 412) and builder-2 482 "some/test.html" on both builder-1 (build 412) and builder-2
529 (build 100), and new text baselines should be downloaded for 483 (build 100), and new text baselines should be downloaded for
530 "some/other.html" but only from builder-1. 484 "some/other.html" but only from builder-1.
531 TODO(qyearsley): Replace test_prefix_list everywhere with some 485 TODO(qyearsley): Replace test_prefix_list everywhere with some
532 sort of class that contains the same data. 486 sort of class that contains the same data.
533 update_scm: If True, commands like `git add` and `git rm` will be ru n.
534 """ 487 """
488 if self._tool.scm().has_working_directory_changes(pathspec=self._layout_ tests_dir()):
489 _log.error('There are uncommitted changes in the layout tests direct ory; aborting.')
490 return
491
535 for test, builds_to_check in sorted(test_prefix_list.items()): 492 for test, builds_to_check in sorted(test_prefix_list.items()):
536 _log.info("Rebaselining %s", test) 493 _log.info("Rebaselining %s", test)
537 for build, suffixes in sorted(builds_to_check.items()): 494 for build, suffixes in sorted(builds_to_check.items()):
538 _log.debug(" %s: %s", build, ",".join(suffixes)) 495 _log.debug(" %s: %s", build, ",".join(suffixes))
539 496
540 copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = sel f._rebaseline_commands( 497 copy_baseline_commands, rebaseline_commands, extra_lines_to_remove = sel f._rebaseline_commands(
541 test_prefix_list, options) 498 test_prefix_list, options)
542 lines_to_remove = {} 499 lines_to_remove = {}
543 500
544 self._run_in_parallel(copy_baseline_commands, update_scm=update_scm) 501 self._run_in_parallel(copy_baseline_commands)
545 lines_to_remove = self._run_in_parallel(rebaseline_commands, update_scm= update_scm) 502 lines_to_remove = self._run_in_parallel(rebaseline_commands)
546 503
547 for test in extra_lines_to_remove: 504 for test in extra_lines_to_remove:
548 if test in lines_to_remove: 505 if test in lines_to_remove:
549 lines_to_remove[test] = lines_to_remove[test] + extra_lines_to_r emove[test] 506 lines_to_remove[test] = lines_to_remove[test] + extra_lines_to_r emove[test]
550 else: 507 else:
551 lines_to_remove[test] = extra_lines_to_remove[test] 508 lines_to_remove[test] = extra_lines_to_remove[test]
552 509
553 if lines_to_remove: 510 if lines_to_remove:
554 self._update_expectations_files(lines_to_remove) 511 self._update_expectations_files(lines_to_remove)
555 512
556 if options.optimize: 513 if options.optimize:
557 # TODO(wkorman): Consider changing temporary branch to base off of H EAD rather than 514 # TODO(wkorman): Consider changing temporary branch to base off of H EAD rather than
558 # origin/master to ensure we run baseline optimization processes wit h the same code as 515 # origin/master to ensure we run baseline optimization processes wit h the same code as
559 # auto-rebaseline itself. 516 # auto-rebaseline itself.
560 self._run_in_parallel(self._optimize_baselines(test_prefix_list, opt ions.verbose), update_scm=update_scm) 517 self._run_in_parallel(self._optimize_baselines(test_prefix_list, opt ions.verbose))
518
519 self._tool.scm().add_all(pathspec=self._layout_tests_dir())
520
521 def _layout_tests_dir(self):
522 return self._tool.port_factory.get().layout_tests_dir()
561 523
562 def _suffixes_for_actual_failures(self, test, build, existing_suffixes): 524 def _suffixes_for_actual_failures(self, test, build, existing_suffixes):
563 """Gets the baseline suffixes for actual mismatch failures in some resul ts. 525 """Gets the baseline suffixes for actual mismatch failures in some resul ts.
564 526
565 Args: 527 Args:
566 test: A full test path string. 528 test: A full test path string.
567 build: A Build object. 529 build: A Build object.
568 existing_suffixes: A collection of all suffixes to consider. 530 existing_suffixes: A collection of all suffixes to consider.
569 531
570 Returns: 532 Returns:
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 for test in args: 649 for test in args:
688 if test not in test_prefix_list: 650 if test not in test_prefix_list:
689 test_prefix_list[test] = {} 651 test_prefix_list[test] = {}
690 build = Build(builder) 652 build = Build(builder)
691 test_prefix_list[test][build] = suffixes_to_update 653 test_prefix_list[test][build] = suffixes_to_update
692 654
693 if options.verbose: 655 if options.verbose:
694 _log.debug("rebaseline-json: " + str(test_prefix_list)) 656 _log.debug("rebaseline-json: " + str(test_prefix_list))
695 657
696 self.rebaseline(options, test_prefix_list) 658 self.rebaseline(options, test_prefix_list)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698