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 |