Changeset 91166 in webkit
- Timestamp:
- Jul 17, 2011 12:38:01 AM (13 years ago)
- Location:
- trunk/Tools
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r91144 r91166 1 2011-07-17 Dimitri Glazkov <dglazkov@chromium.org> 2 3 Rename ModifierMatcher to SpecificityCalculator. 4 https://bugs.webkit.org/show_bug.cgi?id=64660 5 6 It's a little longer than before, but it is much clearer. 7 8 Reviewed by Adam Barth. 9 10 * Scripts/webkitpy/layout_tests/models/test_expectations.py: Renamed and adjusted 11 all callsites, also rewrote the comments. 12 * Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py: Adjusted callsites 13 and renamed tests. 14 1 15 2011-07-15 Adam Barth <abarth@webkit.org> 2 16 -
trunk/Tools/Scripts/webkitpy/layout_tests/models/test_expectations.py
r91124 r91166 177 177 def __init__(self, port, test_config, full_test_list, allow_rebaseline_modifier): 178 178 self._port = port 179 self._ matcher = ModifierMatcher(test_config)179 self._specificity_calculator = SpecificityCalculator(test_config) 180 180 self._full_test_list = full_test_list 181 181 self._allow_rebaseline_modifier = allow_rebaseline_modifier 182 182 183 183 def parse(self, expectation_line): 184 self._ matcher.match(expectation_line)184 self._specificity_calculator.calculate(expectation_line) 185 185 self._check_semantics(expectation_line) 186 186 187 if expectation_line. num_matches == ModifierMatcher.NO_MATCH:187 if expectation_line.specificity == SpecificityCalculator.INVALID: 188 188 return 189 189 … … 330 330 self.parsed_expectations = set() 331 331 self.comment = None 332 self. num_matches = ModifierMatcher.NO_MATCH332 self.specificity = SpecificityCalculator.INVALID 333 333 self.matching_tests = [] 334 334 self.errors = [] … … 498 498 than this path does 499 499 """ 500 # FIXME: See comment below about matching test configs and num_matches.500 # FIXME: See comment below about matching test configs and specificity. 501 501 if not self.has_test(test): 502 502 # We've never seen this test before. … … 531 531 # However, we currently view these as errors. If we decide to make 532 532 # this policy permanent, we can probably simplify this code 533 # and the ModifierMatcher code a fair amount.533 # and the SpecificityCalculator code a fair amount. 534 534 # 535 535 # To use the "more modifiers wins" policy, change the errors for overrides 536 536 # to be warnings and return False". 537 537 538 if prev_expectation_line. num_matches == expectation_line.num_matches:538 if prev_expectation_line.specificity == expectation_line.specificity: 539 539 expectation_line.errors.append('Duplicate or ambiguous %s.' % expectation_source) 540 540 return True 541 541 542 if prev_expectation_line. num_matches < expectation_line.num_matches:542 if prev_expectation_line.specificity < expectation_line.specificity: 543 543 expectation_line.errors.append('More specific entry on line %d overrides line %d' % (lineno, prev_lineno)) 544 544 # FIXME: return False if we want more specific to win. … … 807 807 808 808 809 class ModifierMatchResult(object):809 class SpecificityCalculation(object): 810 810 def __init__(self, modifiers): 811 self. num_matches = ModifierMatcher.NO_MATCH811 self.specificity = SpecificityCalculator.INVALID 812 812 self._modifiers = modifiers 813 813 self._matched_modifiers = [] … … 816 816 817 817 818 class ModifierMatcher(object):818 class SpecificityCalculator(object): 819 819 820 820 """ 821 This class manages the interpretation of the "modifiers"for a given822 line in the expectations file. Modifiers are the tokens that appear to the823 left of the colon on a line. For example, "BUG1234", "DEBUG", and "WIN" are824 all modifiers. This class gets what the valid modifiers are, and which 825 modifiers are allowed to exist together on a line, from the826 TestConfiguration object that is passed in to the call.827 828 This class detects *intra*-line errors like unknown modifiers, but829 does not detect *inter*-line modifiers like duplicate expectations. 830 831 More importantly, this class is also used to determine if a given line832 matches the port in question. Matches are ranked according to the number 833 of modifiers that match on a line. A line with no modifiers matches821 This class determines how specific are the modifiers for a given 822 TestExpectationLine. Some modifiers describe a test configuration for which this 823 test expectation is applicable. There is a degree of specificity for these modifiers. 824 825 For example, 'XP RELEASE CPU' is very specific, because it limits applicable test configuration to 826 Windows XP system in Release mode, with CPU-backed graphics. 827 828 On the other hand, '' (empty modifier) makes the test applicable to any test configuration. 829 830 This class finds such modifiers, interprets their meaning and determines specificity of 831 a given test expectation. 832 833 The specificity is determined as a count of modifiers that match. A line with no modifiers matches 834 834 everything and has a score of zero. A line with one modifier matches only 835 835 ports that have that modifier and gets a score of 1, and so one. Ports … … 854 854 supports "macros" that are expanded prior to interpretation, and "ignore 855 855 regexes" that can be used to skip over modifiers like the BUG* modifiers. 856 857 This class also detects errors in this test expectation, like unknown modifiers, 858 invalid modifier combinations, and duplicate modifiers. 856 859 """ 857 860 MACROS = { … … 866 869 DUPLICATE_REGEXES_ALLOWED = ['bug\w+'] 867 870 868 # Magic value returned when the modifiers don't match .869 NO_MATCH= -1871 # Magic value returned when the modifiers don't match the configuration at all. 872 INVALID = -1 870 873 871 874 # FIXME: The code currently doesn't detect combinations of modifiers 872 875 # that are syntactically valid but semantically invalid, like 873 # 'MAC XP'. See ModifierMatchTest.test_invalid_combinations() in the876 # 'MAC XP'. See SpecificityCalculatorTest.test_invalid_combinations() in the 874 877 # _unittest.py file. 875 878 876 879 def __init__(self, test_config): 877 """Initialize a ModifierMatcher argument with the TestConfiguration it880 """Initialize a SpecificityCalculator argument with the TestConfiguration it 878 881 should be matched against.""" 879 882 self.test_config = test_config … … 895 898 self._all_modifiers.add(modifier) 896 899 897 def match(self, expectation_line):900 def calculate(self, expectation_line): 898 901 """Checks a expectation.modifiers against the config set in the constructor. 899 902 Options may be either actual modifier strings, "macro" strings … … 901 904 to be ignored. All of the modifiers must be passed in in lower case. 902 905 903 Returns the number of matching categories, or NO_MATCH(-1) if it906 Returns specificity relative to the test configuration, or INVALID (-1) if it 904 907 doesn't match or there were errors found. Matches are prioritized 905 908 by the number of matching categories, because the more specific … … 907 910 """ 908 911 old_error_count = len(expectation_line.errors) 909 result = ModifierMatchResult(expectation_line.modifiers)912 result = SpecificityCalculation(expectation_line.modifiers) 910 913 self._parse(expectation_line, result) 911 914 if old_error_count == len(expectation_line.errors): 912 915 self._count_matches(result) 913 expectation_line. num_matches = result.num_matches916 expectation_line.specificity = result.specificity 914 917 915 918 def _parse(self, expectation_line, result): … … 964 967 """Returns the number of modifiers that match the test config.""" 965 968 categorized_modifiers = self._group_by_category(result._matched_modifiers) 966 result. num_matches= 0969 result.specificity = 0 967 970 for category, modifier in self.test_config.items(): 968 971 if category in categorized_modifiers: 969 972 if modifier in categorized_modifiers[category]: 970 result. num_matches+= 1973 result.specificity += 1 971 974 else: 972 result. num_matches = self.NO_MATCH975 result.specificity = self.INVALID 973 976 return 974 977 -
trunk/Tools/Scripts/webkitpy/layout_tests/models/test_expectations_unittest.py
r91103 r91166 385 385 386 386 387 class ModifierTests(unittest.TestCase):387 class SpecificityCalculatorTests(unittest.TestCase): 388 388 def setUp(self): 389 389 port_obj = port.get('test-win-xp', None) 390 390 self.config = port_obj.test_configuration() 391 self.matcher = ModifierMatcher(self.config) 392 393 def match(self, modifiers, expected_num_matches=-1, values=None, num_errors=0): 394 matcher = self.matcher 395 if values: 396 matcher = ModifierMatcher(self.FakeTestConfiguration(values)) 391 self.calculator = SpecificityCalculator(self.config) 392 393 def assert_specificity(self, modifiers, expected_specificity=-1, num_errors=0): 397 394 expectation = TestExpectationLine() 398 395 expectation.modifiers = modifiers 399 matcher.match(expectation)396 self.calculator.calculate(expectation) 400 397 self.assertEqual(len(expectation.warnings), 0) 401 398 self.assertEqual(len(expectation.errors), num_errors) 402 self.assertEqual(expectation. num_matches, expected_num_matches,399 self.assertEqual(expectation.specificity, expected_specificity, 403 400 'match(%s, %s) returned -> %d, expected %d' % 404 401 (modifiers, str(self.config.values()), 405 expectation. num_matches, expected_num_matches))402 expectation.specificity, expected_specificity)) 406 403 407 404 def test_bad_match_modifier(self): 408 self. match(['foo'], num_errors=1)405 self.assert_specificity(['foo'], num_errors=1) 409 406 410 407 def test_none(self): 411 self. match([], 0)408 self.assert_specificity([], 0) 412 409 413 410 def test_one(self): 414 self. match(['xp'], 1)415 self. match(['win'], 1)416 self. match(['release'], 1)417 self. match(['cpu'], 1)418 self. match(['x86'], 1)419 self. match(['leopard'], -1)420 self. match(['gpu'], -1)421 self. match(['debug'], -1)411 self.assert_specificity(['xp'], 1) 412 self.assert_specificity(['win'], 1) 413 self.assert_specificity(['release'], 1) 414 self.assert_specificity(['cpu'], 1) 415 self.assert_specificity(['x86'], 1) 416 self.assert_specificity(['leopard'], -1) 417 self.assert_specificity(['gpu'], -1) 418 self.assert_specificity(['debug'], -1) 422 419 423 420 def test_two(self): 424 self. match(['xp', 'release'], 2)425 self. match(['win7', 'release'], -1)426 self. match(['win7', 'xp'], 1)421 self.assert_specificity(['xp', 'release'], 2) 422 self.assert_specificity(['win7', 'release'], -1) 423 self.assert_specificity(['win7', 'xp'], 1) 427 424 428 425 def test_three(self): 429 self. match(['win7', 'xp', 'release'], 2)430 self. match(['xp', 'debug', 'x86'], -1)431 self. match(['xp', 'release', 'x86'], 3)432 self. match(['xp', 'cpu', 'release'], 3)426 self.assert_specificity(['win7', 'xp', 'release'], 2) 427 self.assert_specificity(['xp', 'debug', 'x86'], -1) 428 self.assert_specificity(['xp', 'release', 'x86'], 3) 429 self.assert_specificity(['xp', 'cpu', 'release'], 3) 433 430 434 431 def test_four(self): 435 self. match(['xp', 'release', 'cpu', 'x86'], 4)436 self. match(['win7', 'xp', 'release', 'cpu'], 3)437 self. match(['win7', 'xp', 'debug', 'cpu'], -1)432 self.assert_specificity(['xp', 'release', 'cpu', 'x86'], 4) 433 self.assert_specificity(['win7', 'xp', 'release', 'cpu'], 3) 434 self.assert_specificity(['win7', 'xp', 'debug', 'cpu'], -1) 438 435 439 436 def test_case_insensitivity(self): 440 self. match(['Win'], num_errors=1)441 self. match(['WIN'], num_errors=1)442 self. match(['win'], 1)437 self.assert_specificity(['Win'], num_errors=1) 438 self.assert_specificity(['WIN'], num_errors=1) 439 self.assert_specificity(['win'], 1) 443 440 444 441 def test_duplicates(self): 445 self. match(['release', 'release'], num_errors=1)446 self. match(['win', 'xp'], num_errors=1)447 self. match(['xp', 'xp'], num_errors=1)448 self. match(['xp', 'release', 'xp', 'release'], num_errors=2)449 self. match(['rebaseline', 'rebaseline'], num_errors=1)442 self.assert_specificity(['release', 'release'], num_errors=1) 443 self.assert_specificity(['win', 'xp'], num_errors=1) 444 self.assert_specificity(['xp', 'xp'], num_errors=1) 445 self.assert_specificity(['xp', 'release', 'xp', 'release'], num_errors=2) 446 self.assert_specificity(['rebaseline', 'rebaseline'], num_errors=1) 450 447 451 448 def test_unknown_modifier(self): 452 self. match(['vms'], num_errors=1)449 self.assert_specificity(['vms'], num_errors=1) 453 450 454 451 def test_duplicate_bugs(self): 455 452 # BUG* regexes can appear multiple times. 456 self. match(['bugfoo', 'bugbar'], 0)453 self.assert_specificity(['bugfoo', 'bugbar'], 0) 457 454 458 455 def test_regexes_are_ignored(self): 459 self. match(['bug123xy', 'rebaseline', 'wontfix', 'slow', 'skip'], 0)456 self.assert_specificity(['bug123xy', 'rebaseline', 'wontfix', 'slow', 'skip'], 0) 460 457 461 458 def test_none_is_invalid(self): 462 self. match(['none'], num_errors=1)459 self.assert_specificity(['none'], num_errors=1) 463 460 464 461
Note: See TracChangeset
for help on using the changeset viewer.