| 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 |
| 11 # in the documentation and/or other materials provided with the | 11 # in the documentation and/or other materials provided with the |
| 12 # distribution. | 12 # distribution. |
| 13 # * Neither the name of Google Inc. nor the names of its | 13 # * Neither the name of Google Inc. nor the names of its |
| 14 # contributors may be used to endorse or promote products derived from | 14 # contributors may be used to endorse or promote products derived from |
| 15 # this software without specific prior written permission. | 15 # this software without specific prior written permission. |
| 16 # | 16 # |
| 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | 28 |
| 29 """A helper class for reading in and dealing with tests expectations | 29 """A helper class for reading in and dealing with tests expectations for layout
tests.""" |
| 30 for layout tests. | |
| 31 """ | |
| 32 | 30 |
| 33 from collections import defaultdict | 31 from collections import defaultdict |
| 34 | 32 |
| 35 import logging | 33 import logging |
| 36 import re | 34 import re |
| 37 | 35 |
| 38 from webkitpy.layout_tests.models.test_configuration import TestConfigurationCon
verter | 36 from webkitpy.layout_tests.models.test_configuration import TestConfigurationCon
verter |
| 39 | 37 |
| 40 _log = logging.getLogger(__name__) | 38 _log = logging.getLogger(__name__) |
| 41 | 39 |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 245 'Pass': 'PASS', | 243 'Pass': 'PASS', |
| 246 'Rebaseline': 'REBASELINE', | 244 'Rebaseline': 'REBASELINE', |
| 247 NEEDS_REBASELINE_KEYWORD: 'NEEDSREBASELINE', | 245 NEEDS_REBASELINE_KEYWORD: 'NEEDSREBASELINE', |
| 248 NEEDS_MANUAL_REBASELINE_KEYWORD: 'NEEDSMANUALREBASELINE', | 246 NEEDS_MANUAL_REBASELINE_KEYWORD: 'NEEDSMANUALREBASELINE', |
| 249 'Skip': 'SKIP', | 247 'Skip': 'SKIP', |
| 250 'Slow': 'SLOW', | 248 'Slow': 'SLOW', |
| 251 'Timeout': 'TIMEOUT', | 249 'Timeout': 'TIMEOUT', |
| 252 'WontFix': 'WONTFIX', | 250 'WontFix': 'WONTFIX', |
| 253 } | 251 } |
| 254 | 252 |
| 255 _inverted_expectation_tokens = dict([(value, name) for name, value in _expec
tation_tokens.iteritems()] + | 253 _inverted_expectation_tokens = dict( |
| 256 [('TEXT', 'Failure'), ('IMAGE', 'Failure
'), ('IMAGE+TEXT', 'Failure'), ('AUDIO', 'Failure')]) | 254 [(value, name) for name, value in _expectation_tokens.iteritems()] + |
| 255 [('TEXT', 'Failure'), ('IMAGE', 'Failure'), ('IMAGE+TEXT', 'Failure'), (
'AUDIO', 'Failure')]) |
| 257 | 256 |
| 258 # FIXME: Seems like these should be classmethods on TestExpectationLine inst
ead of TestExpectationParser. | 257 # FIXME: Seems like these should be classmethods on TestExpectationLine inst
ead of TestExpectationParser. |
| 259 @classmethod | 258 @classmethod |
| 260 def _tokenize_line(cls, filename, expectation_string, line_number): | 259 def _tokenize_line(cls, filename, expectation_string, line_number): |
| 261 """Tokenizes a line from TestExpectations and returns an unparsed TestEx
pectationLine instance using the old format. | 260 """Tokenizes a line from TestExpectations and returns an unparsed TestEx
pectationLine instance using the old format. |
| 262 | 261 |
| 263 The new format for a test expectation line is: | 262 The new format for a test expectation line is: |
| 264 | 263 |
| 265 [[bugs] [ "[" <configuration specifiers> "]" <name> [ "[" <expectations>
"]" ["#" <comment>] | 264 [[bugs] [ "[" <configuration specifiers> "]" <name> [ "[" <expectations>
"]" ["#" <comment>] |
| 266 | 265 |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 result.name = line1.name | 477 result.name = line1.name |
| 479 result.path = line1.path | 478 result.path = line1.path |
| 480 result.parsed_expectations = set(line1.parsed_expectations) | set(line2.
parsed_expectations) | 479 result.parsed_expectations = set(line1.parsed_expectations) | set(line2.
parsed_expectations) |
| 481 result.expectations = list(set(line1.expectations) | set(line2.expectati
ons)) | 480 result.expectations = list(set(line1.expectations) | set(line2.expectati
ons)) |
| 482 result.bugs = list(set(line1.bugs) | set(line2.bugs)) | 481 result.bugs = list(set(line1.bugs) | set(line2.bugs)) |
| 483 result.specifiers = list(set(line1.specifiers) | set(line2.specifiers)) | 482 result.specifiers = list(set(line1.specifiers) | set(line2.specifiers)) |
| 484 result.parsed_specifiers = list(set(line1.parsed_specifiers) | set(line2
.parsed_specifiers)) | 483 result.parsed_specifiers = list(set(line1.parsed_specifiers) | set(line2
.parsed_specifiers)) |
| 485 result.matching_configurations = set(line1.matching_configurations) | se
t(line2.matching_configurations) | 484 result.matching_configurations = set(line1.matching_configurations) | se
t(line2.matching_configurations) |
| 486 result.matching_tests = list(list(set(line1.matching_tests) | set(line2.
matching_tests))) | 485 result.matching_tests = list(list(set(line1.matching_tests) | set(line2.
matching_tests))) |
| 487 result.warnings = list(set(line1.warnings) | set(line2.warnings)) | 486 result.warnings = list(set(line1.warnings) | set(line2.warnings)) |
| 488 result.is_skipped_outside_expectations_file = line1.is_skipped_outside_e
xpectations_file or line2.is_skipped_outside_expectations_file | 487 result.is_skipped_outside_expectations_file = (line1.is_skipped_outside_
expectations_file or |
| 488 line2.is_skipped_outside_
expectations_file) |
| 489 return result | 489 return result |
| 490 | 490 |
| 491 def to_string(self, test_configuration_converter=None, include_specifiers=Tr
ue, include_expectations=True, include_comment=True): | 491 def to_string(self, test_configuration_converter=None, include_specifiers=Tr
ue, |
| 492 parsed_expectation_to_string = dict([[parsed_expectation, expectation_st
ring] | 492 include_expectations=True, include_comment=True): |
| 493 for expectation_string, parsed_expe
ctation in TestExpectations.EXPECTATIONS.items()]) | 493 parsed_expectation_to_string = dict( |
| 494 [[parsed_expectation, expectation_string] |
| 495 for expectation_string, parsed_expectation in TestExpectations.EXPE
CTATIONS.items()]) |
| 494 | 496 |
| 495 if self.is_invalid(): | 497 if self.is_invalid(): |
| 496 return self.original_string or '' | 498 return self.original_string or '' |
| 497 | 499 |
| 498 if self.name is None: | 500 if self.name is None: |
| 499 return '' if self.comment is None else "#%s" % self.comment | 501 return '' if self.comment is None else "#%s" % self.comment |
| 500 | 502 |
| 501 if test_configuration_converter and self.bugs: | 503 if test_configuration_converter and self.bugs: |
| 502 specifiers_list = test_configuration_converter.to_specifiers_list(se
lf.matching_configurations) | 504 specifiers_list = test_configuration_converter.to_specifiers_list(se
lf.matching_configurations) |
| 503 result = [] | 505 result = [] |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 # To use the "more specifiers wins" policy, change the errors for overri
des | 803 # To use the "more specifiers wins" policy, change the errors for overri
des |
| 802 # to be warnings and return False". | 804 # to be warnings and return False". |
| 803 | 805 |
| 804 if prev_expectation_line.matching_configurations == expectation_line.mat
ching_configurations: | 806 if prev_expectation_line.matching_configurations == expectation_line.mat
ching_configurations: |
| 805 expectation_line.warnings.append('Duplicate or ambiguous entry lines
%s:%s and %s:%s.' % ( | 807 expectation_line.warnings.append('Duplicate or ambiguous entry lines
%s:%s and %s:%s.' % ( |
| 806 self._shorten_filename(prev_expectation_line.filename), prev_exp
ectation_line.line_numbers, | 808 self._shorten_filename(prev_expectation_line.filename), prev_exp
ectation_line.line_numbers, |
| 807 self._shorten_filename(expectation_line.filename), expectation_l
ine.line_numbers)) | 809 self._shorten_filename(expectation_line.filename), expectation_l
ine.line_numbers)) |
| 808 return True | 810 return True |
| 809 | 811 |
| 810 if prev_expectation_line.matching_configurations >= expectation_line.mat
ching_configurations: | 812 if prev_expectation_line.matching_configurations >= expectation_line.mat
ching_configurations: |
| 811 expectation_line.warnings.append('More specific entry for %s on line
%s:%s overrides line %s:%s.' % (expectation_line.name, | 813 expectation_line.warnings.append('More specific entry for %s on line
%s:%s overrides line %s:%s.' % ( |
| 812
self._shorten_filename( | 814 expectation_line.name, |
| 813
prev_expectation_line.filename), prev_expec
tation_line.line_numbers, | 815 self._shorten_filename( |
| 814
self._shorten_filename(expectation_line.filenam
e), expectation_line.line_numbers)) | 816 prev_expectation_line.filename), prev_expectation_line.line_
numbers, |
| 817 self._shorten_filename(expectation_line.filename), expectation_l
ine.line_numbers)) |
| 815 # FIXME: return False if we want more specific to win. | 818 # FIXME: return False if we want more specific to win. |
| 816 return True | 819 return True |
| 817 | 820 |
| 818 if prev_expectation_line.matching_configurations <= expectation_line.mat
ching_configurations: | 821 if prev_expectation_line.matching_configurations <= expectation_line.mat
ching_configurations: |
| 819 expectation_line.warnings.append('More specific entry for %s on line
%s:%s overrides line %s:%s.' % (expectation_line.name, | 822 expectation_line.warnings.append('More specific entry for %s on line
%s:%s overrides line %s:%s.' % ( |
| 820
self._shorten_filename( | 823 expectation_line.name, |
| 821
expectation_line.filename), expectation_lin
e.line_numbers, | 824 self._shorten_filename( |
| 822
self._shorten_filename(prev_expectation_line.fi
lename), prev_expectation_line.line_numbers)) | 825 expectation_line.filename), expectation_line.line_numbers, |
| 826 self._shorten_filename(prev_expectation_line.filename), prev_exp
ectation_line.line_numbers)) |
| 823 return True | 827 return True |
| 824 | 828 |
| 825 if prev_expectation_line.matching_configurations & expectation_line.matc
hing_configurations: | 829 if prev_expectation_line.matching_configurations & expectation_line.matc
hing_configurations: |
| 826 expectation_line.warnings.append('Entries for %s on lines %s:%s and
%s:%s match overlapping sets of configurations.' % (expectation_line.name, | 830 expectation_line.warnings.append('Entries for %s on lines %s:%s and
%s:%s match overlapping sets of configurations.' % ( |
| 827
self._shorten_filename( | 831 expectation_line.name, |
| 828
prev_expectation_line.fi
lename), prev_expectation_line.line_numbers, | 832 self._shorten_filename( |
| 829
self._shorten_filename(expec
tation_line.filename), expectation_line.line_numbers)) | 833 prev_expectation_line.filename), prev_expectation_line.line_
numbers, |
| 834 self._shorten_filename(expectation_line.filename), expectation_l
ine.line_numbers)) |
| 830 return True | 835 return True |
| 831 | 836 |
| 832 # Configuration sets are disjoint, then. | 837 # Configuration sets are disjoint, then. |
| 833 return False | 838 return False |
| 834 | 839 |
| 835 | 840 |
| 836 class TestExpectations(object): | 841 class TestExpectations(object): |
| 837 """Test expectations consist of lines with specifications of what | 842 """Test expectations consist of lines with specifications of what |
| 838 to expect from layout test cases. The test cases can be directories | 843 to expect from layout test cases. The test cases can be directories |
| 839 in which case the expectations apply to all test cases in that | 844 in which case the expectations apply to all test cases in that |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1088 | 1093 |
| 1089 def _shorten_filename(self, filename): | 1094 def _shorten_filename(self, filename): |
| 1090 if filename.startswith(self._port.path_from_webkit_base()): | 1095 if filename.startswith(self._port.path_from_webkit_base()): |
| 1091 return self._port.host.filesystem.relpath(filename, self._port.path_
from_webkit_base()) | 1096 return self._port.host.filesystem.relpath(filename, self._port.path_
from_webkit_base()) |
| 1092 return filename | 1097 return filename |
| 1093 | 1098 |
| 1094 def _report_warnings(self): | 1099 def _report_warnings(self): |
| 1095 warnings = [] | 1100 warnings = [] |
| 1096 for expectation in self._expectations: | 1101 for expectation in self._expectations: |
| 1097 for warning in expectation.warnings: | 1102 for warning in expectation.warnings: |
| 1098 warnings.append('%s:%s %s %s' % (self._shorten_filename(expectat
ion.filename), expectation.line_numbers, | 1103 warnings.append('%s:%s %s %s' % ( |
| 1099 warning, expectation.name if ex
pectation.expectations else expectation.original_string)) | 1104 self._shorten_filename(expectation.filename), expectation.li
ne_numbers, |
| 1105 warning, expectation.name if expectation.expectations else e
xpectation.original_string)) |
| 1100 | 1106 |
| 1101 if warnings: | 1107 if warnings: |
| 1102 self._has_warnings = True | 1108 self._has_warnings = True |
| 1103 if self._is_lint_mode: | 1109 if self._is_lint_mode: |
| 1104 raise ParseError(warnings) | 1110 raise ParseError(warnings) |
| 1105 _log.warning('--lint-test-files warnings:') | 1111 _log.warning('--lint-test-files warnings:') |
| 1106 for warning in warnings: | 1112 for warning in warnings: |
| 1107 _log.warning(warning) | 1113 _log.warning(warning) |
| 1108 _log.warning('') | 1114 _log.warning('') |
| 1109 | 1115 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1130 expectation.matching_configurations.remove(test_configuration) | 1136 expectation.matching_configurations.remove(test_configuration) |
| 1131 if expectation.matching_configurations: | 1137 if expectation.matching_configurations: |
| 1132 modified_expectations.append(expectation) | 1138 modified_expectations.append(expectation) |
| 1133 else: | 1139 else: |
| 1134 expectations_to_remove.append(expectation) | 1140 expectations_to_remove.append(expectation) |
| 1135 | 1141 |
| 1136 for expectation in expectations_to_remove: | 1142 for expectation in expectations_to_remove: |
| 1137 index = self._expectations.index(expectation) | 1143 index = self._expectations.index(expectation) |
| 1138 self._expectations.remove(expectation) | 1144 self._expectations.remove(expectation) |
| 1139 | 1145 |
| 1140 if index == len(self._expectations) or self._expectations[index].is_
whitespace() or self._expectations[index].is_comment(): | 1146 if index == len(self._expectations) or self._expectations[ |
| 1147 index].is_whitespace() or self._expectations[index].is_comme
nt(): |
| 1141 while index and self._expectations[index - 1].is_comment(): | 1148 while index and self._expectations[index - 1].is_comment(): |
| 1142 index = index - 1 | 1149 index = index - 1 |
| 1143 self._expectations.pop(index) | 1150 self._expectations.pop(index) |
| 1144 while index and self._expectations[index - 1].is_whitespace(): | 1151 while index and self._expectations[index - 1].is_whitespace(): |
| 1145 index = index - 1 | 1152 index = index - 1 |
| 1146 self._expectations.pop(index) | 1153 self._expectations.pop(index) |
| 1147 | 1154 |
| 1148 return self.list_to_string(self._expectations, self._parser._test_config
uration_converter, modified_expectations) | 1155 return self.list_to_string(self._expectations, self._parser._test_config
uration_converter, modified_expectations) |
| 1149 | 1156 |
| 1150 def _add_expectations(self, expectation_list, model): | 1157 def _add_expectations(self, expectation_list, model): |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1196 # If reconstitute_only_these is an empty list, we want to return ori
ginal_string. | 1203 # If reconstitute_only_these is an empty list, we want to return ori
ginal_string. |
| 1197 # So we need to compare reconstitute_only_these to None, not just ch
eck if it's falsey. | 1204 # So we need to compare reconstitute_only_these to None, not just ch
eck if it's falsey. |
| 1198 if reconstitute_only_these is None or expectation_line in reconstitu
te_only_these: | 1205 if reconstitute_only_these is None or expectation_line in reconstitu
te_only_these: |
| 1199 return expectation_line.to_string(test_configuration_converter) | 1206 return expectation_line.to_string(test_configuration_converter) |
| 1200 return expectation_line.original_string | 1207 return expectation_line.original_string |
| 1201 | 1208 |
| 1202 def nones_out(expectation_line): | 1209 def nones_out(expectation_line): |
| 1203 return expectation_line is not None | 1210 return expectation_line is not None |
| 1204 | 1211 |
| 1205 return "\n".join(filter(nones_out, map(serialize, expectation_lines))) | 1212 return "\n".join(filter(nones_out, map(serialize, expectation_lines))) |
| OLD | NEW |