Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 import optparse | |
| 2 | |
| 3 from webkitpy.layout_tests.models.test_expectations import TestExpectations | |
| 4 from webkitpy.layout_tests.layout_package.bot_test_expectations import BotTestEx pectationsFactory | |
| 5 from webkitpy.layout_tests.port import builders | |
| 6 | |
| 7 | |
| 8 def main(host, argv): | |
| 9 parser = optparse.OptionParser(usage='%prog ') | |
| 10 # parser.add_option('-f', '--forward', action='store', type='int', | |
| 11 # help='group times by first N directories of test') | |
| 12 # parser.add_option('-b', '--backward', action='store', type='int', | |
| 13 # help='group times by last N directories of test') | |
| 14 # parser.add_option('--fastest', action='store', type='float', | |
| 15 # help='print a list of tests that will take N % of the ti me') | |
| 16 | |
| 17 epilog = """ | |
| 18 Test test test""" | |
| 19 parser.epilog = '\n'.join(s.lstrip() for s in epilog.splitlines()) | |
| 20 | |
| 21 options, args = parser.parse_args(argv) | |
|
qyearsley
2016/03/07 19:09:53
This could be switched to argparse, the successor
bokan
2016/03/07 22:59:15
Thanks, done.
| |
| 22 | |
| 23 remove_flakes_o_matic = RemoveFlakesOMatic() | |
| 24 remove_flakes_o_matic.execute(host) | |
|
qyearsley
2016/03/07 19:09:53
Possible refactoring: Maybe RemoveFlakesOMatic.exe
bokan
2016/03/07 22:59:15
My patch is based on Ojan's CL which originally us
| |
| 25 | |
| 26 | |
| 27 class RemoveFlakesOMatic: | |
|
qyearsley
2016/03/07 19:09:53
What do instances of this class represent? Could t
bokan
2016/03/07 22:59:16
Addressed above.
| |
| 28 def __init__(self): | |
| 29 self.expectations_factory = BotTestExpectationsFactory() | |
| 30 | |
| 31 def _can_delete_line(self, test_expectation_line): | |
|
qyearsley
2016/03/07 19:09:53
test_expectation_line is an instance of test_expec
bokan
2016/03/07 22:59:15
Done.
| |
| 32 expectations = test_expectation_line.expectations | |
| 33 if len(expectations) < 2: | |
| 34 return False | |
|
qyearsley
2016/03/07 19:09:53
What does an expectation list of length 0 or 1 ind
bokan
2016/03/07 22:59:15
It means the test isn't flaky and this script (rig
| |
| 35 | |
| 36 if self._has_unstripable_expectations(expectations): | |
| 37 return False | |
| 38 | |
| 39 if not self._has_pass_expectation(expectations): | |
| 40 return False | |
| 41 | |
| 42 # The line can be deleted if the only expectation on the line that appea rs in the actual | |
| 43 # results is the PASS expectation. | |
| 44 for config in test_expectation_line.matching_configurations: | |
| 45 builder_name = builders.builder_name_for_specifiers(config.version, config.build_type) | |
| 46 | |
| 47 if not builder_name: | |
| 48 # TODO(bokan): We probably want to report a problem if we can't get turn the | |
| 49 # specifiers into a bot. | |
| 50 # TODO(bokan): Matching configurations often give us bots that d on't have a | |
|
bokan
2016/03/04 03:44:10
There seems to be more matching_configurations tha
| |
| 51 # builder in builders.py's exact_matches. Should we ignore those or be conservative | |
| 52 # and assume those need these expectations? | |
| 53 return False | |
| 54 | |
| 55 if builder_name not in self.builder_results_by_path.keys(): | |
| 56 # TODO(bokan): We probably want to report a problem if we can't get results for | |
| 57 # a bot. | |
| 58 return False | |
| 59 | |
| 60 results_by_path = self.builder_results_by_path[builder_name] | |
| 61 | |
| 62 # No results means the test was all skipped or all results are passi ng. | |
| 63 if test_expectation_line.path not in results_by_path.keys(): | |
| 64 continue | |
| 65 | |
| 66 results_for_test = results_by_path[test_expectation_line.path] | |
| 67 | |
| 68 if self._met_expectations(test_expectation_line, results_for_test) ! = set(['PASS']): | |
| 69 return False | |
| 70 | |
| 71 return True | |
| 72 | |
| 73 def _has_pass_expectation(self, expectations): | |
| 74 return 'PASS' in expectations | |
| 75 | |
| 76 def _met_expectations(self, test_expectation_line, results_for_test): | |
| 77 # TODO(bokan): Does this not exist in a more central place? | |
|
bokan
2016/03/04 03:44:10
Ditto here, is there a function that turns "failur
| |
| 78 def replace_failing_with_fail(expectation): | |
| 79 if expectation in ('TEXT', 'IMAGE', 'IMAGE+TEXT', 'AUDIO'): | |
| 80 return 'FAIL' | |
| 81 else: | |
| 82 return expectation | |
| 83 | |
| 84 test_results = set(results_for_test) | |
|
qyearsley
2016/03/07 19:09:53
This line could be removed without changing the ou
bokan
2016/03/07 22:59:15
Yes, you're right, removed.
| |
| 85 | |
| 86 actual_results = set(map(replace_failing_with_fail, test_results)) | |
|
qyearsley
2016/03/07 19:09:54
Possible rephrasing:
actual_results = {replac
bokan
2016/03/07 22:59:15
Done.
| |
| 87 | |
| 88 return set(test_expectation_line.expectations) & actual_results | |
| 89 | |
| 90 def _has_unstripable_expectations(self, expectations): | |
|
qyearsley
2016/03/07 19:09:53
unstripable -> unstrippable
bokan
2016/03/07 22:59:15
Done.
| |
| 91 return ('REBASELINE' in expectations | |
| 92 or 'NEEDSREBASLINE' in expectations | |
| 93 or 'NEEDSMANUALREBASELINE' in expectations | |
| 94 or 'SLOW' in expectations) | |
|
qyearsley
2016/03/07 19:09:53
Possible alternate phrasing:
passing_statuses
bokan
2016/03/07 22:59:15
Done.
| |
| 95 | |
| 96 def execute(self, host): | |
| 97 port = host.port_factory.get() | |
| 98 test_expectations = TestExpectations(port, include_overrides=False)._exp ectations | |
|
qyearsley
2016/03/07 19:09:53
1. What is the class of the objects in test_expect
bokan
2016/03/07 22:59:15
test_expectations is a list of TestExpectationLine
| |
| 99 | |
| 100 self.builder_results_by_path = {} | |
| 101 for builder_name in builders.all_builder_names(): | |
| 102 self.builder_results_by_path[builder_name] = ( | |
| 103 self.expectations_factory.expectations_for_builder(builder_name) .all_results_by_path() | |
| 104 ) | |
| 105 pass | |
| 106 | |
| 107 expectations_to_remove = [] | |
| 108 | |
| 109 for expectation in test_expectations: | |
| 110 if self._can_delete_line(expectation): | |
| 111 expectations_to_remove.append(expectation) | |
| 112 | |
| 113 for expectation in expectations_to_remove: | |
| 114 index = test_expectations.index(expectation) | |
| 115 test_expectations.remove(expectation) | |
| 116 | |
| 117 # Remove associated comments if we've removed the last expectation u nder a comment block. | |
| 118 if index == len(test_expectations) or test_expectations[index].is_wh itespace_or_comment(): | |
| 119 while index and test_expectations[index - 1].is_whitespace_or_co mment(): | |
| 120 index = index - 1 | |
| 121 test_expectations.pop(index) | |
| 122 | |
| 123 expectations_file = port.path_to_generic_test_expectations_file() | |
|
bokan
2016/03/04 03:44:10
Presumably we also want to update ASAN and other b
| |
| 124 host.filesystem.write_text_file( | |
| 125 expectations_file, | |
| 126 TestExpectations.list_to_string(test_expectations, reconstitute_only _these=[])) | |
| OLD | NEW |