Title: [96390] trunk/Tools
Revision
96390
Author
[email protected]
Date
2011-09-29 22:22:55 -0700 (Thu, 29 Sep 2011)

Log Message

watchlist: Add cross-checks for WatchList once it is filled.
https://bugs.webkit.org/show_bug.cgi?id=68975

Reviewed by Eric Seidel.

* Scripts/webkitpy/common/watchlist/watchlist.py: Made the data members public
instead of having trivial getter and setters.
* Scripts/webkitpy/common/watchlist/watchlist_unittest.py: Fix the unit tests to
pass the validation checks.
* Scripts/webkitpy/common/watchlist/watchlistparser.py: Add validation checks
and fix a few style nits.
* Scripts/webkitpy/common/watchlist/watchlistparser_unittest.py: Add tests for the
validation checks.
* Scripts/webkitpy/common/watchlist/watchlistrule.py: Make definitions_to_match public.

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (96389 => 96390)


--- trunk/Tools/ChangeLog	2011-09-30 05:15:58 UTC (rev 96389)
+++ trunk/Tools/ChangeLog	2011-09-30 05:22:55 UTC (rev 96390)
@@ -1,3 +1,20 @@
+2011-09-29  David Levin  <[email protected]>
+
+        watchlist: Add cross-checks for WatchList once it is filled.
+        https://bugs.webkit.org/show_bug.cgi?id=68975
+
+        Reviewed by Eric Seidel.
+
+        * Scripts/webkitpy/common/watchlist/watchlist.py: Made the data members public
+        instead of having trivial getter and setters.
+        * Scripts/webkitpy/common/watchlist/watchlist_unittest.py: Fix the unit tests to
+        pass the validation checks.
+        * Scripts/webkitpy/common/watchlist/watchlistparser.py: Add validation checks
+        and fix a few style nits.
+        * Scripts/webkitpy/common/watchlist/watchlistparser_unittest.py: Add tests for the
+        validation checks.
+        * Scripts/webkitpy/common/watchlist/watchlistrule.py: Make definitions_to_match public.
+
 2011-09-29  Xianzhu Wang  <[email protected]>
 
         run-api-tests fails on chromium-win bot

Modified: trunk/Tools/Scripts/webkitpy/common/watchlist/watchlist.py (96389 => 96390)


--- trunk/Tools/Scripts/webkitpy/common/watchlist/watchlist.py	2011-09-30 05:15:58 UTC (rev 96389)
+++ trunk/Tools/Scripts/webkitpy/common/watchlist/watchlist.py	2011-09-30 05:22:55 UTC (rev 96390)
@@ -31,31 +31,22 @@
 
 class WatchList(object):
     def __init__(self):
-        self._definitions = {}
-        self._cc_rules = set()
-        self._message_rules = set()
+        self.definitions = {}
+        self.cc_rules = set()
+        self.message_rules = set()
 
-    def set_definitions(self, definitions):
-        self._definitions = definitions
-
-    def set_cc_rules(self, cc_rules):
-        self._cc_rules = cc_rules
-
-    def set_message_rules(self, message_rules):
-        self._message_rules = message_rules
-
     def find_matching_definitions(self, diff):
         matching_definitions = set()
         patch_files = DiffParser(diff.splitlines()).files
 
         for path, diff_file in patch_files.iteritems():
-            for definition in self._definitions:
+            for definition in self.definitions:
                 # If a definition has already matched, there is no need to process it.
                 if definition in matching_definitions:
                     continue
 
                 # See if the definition matches within one file.
-                for pattern in self._definitions[definition]:
+                for pattern in self.definitions[definition]:
                     if not pattern.match(path, diff_file.lines):
                         break
                 else:
@@ -70,10 +61,10 @@
         return instructions
 
     def determine_cc_set(self, matching_definitions):
-        return self._determine_instructions(matching_definitions, self._cc_rules)
+        return self._determine_instructions(matching_definitions, self.cc_rules)
 
     def determine_messages(self, matching_definitions):
-        return self._determine_instructions(matching_definitions, self._message_rules)
+        return self._determine_instructions(matching_definitions, self.message_rules)
 
     def determine_cc_set_and_messages(self, diff):
         definitions = self.find_matching_definitions(diff)

Modified: trunk/Tools/Scripts/webkitpy/common/watchlist/watchlist_unittest.py (96389 => 96390)


--- trunk/Tools/Scripts/webkitpy/common/watchlist/watchlist_unittest.py	2011-09-30 05:15:58 UTC (rev 96389)
+++ trunk/Tools/Scripts/webkitpy/common/watchlist/watchlist_unittest.py	2011-09-30 05:22:55 UTC (rev 96390)
@@ -46,6 +46,11 @@
             '            "filename": r".*\\MyFileName\\.cpp",'
             '        },'
             '     },'
+            '    "CC_RULES": {'
+            '        "WatchList1": ['
+            '            "[email protected]",'
+            '        ],'
+           '    },'
             '}')
         self.assertEquals(set([]), watch_list.find_matching_definitions(DIFF_TEST_DATA))
 
@@ -57,6 +62,11 @@
             '            "filename": r"WebCore/rendering/style/StyleFlexibleBoxData\.h",'
             '        },'
             '     },'
+            '    "CC_RULES": {'
+            '        "WatchList1": ['
+            '            "[email protected]",'
+            '        ],'
+           '    },'
             '}')
         self.assertEquals(set(['WatchList1']), watch_list.find_matching_definitions(DIFF_TEST_DATA))
 
@@ -87,6 +97,12 @@
             '        "WatchList1": {'
             '            "filename": r"WebCore/rendering/style/StyleFlexibleBoxData\.h",'
             '        },'
+            '        "WatchList2": {'
+            '            "filename": r"WillNotMatch",'
+            '        },'
+            '        "WatchList3": {'
+            '            "filename": r"WillNotMatch",'
+            '        },'
             '     },'
             '    "CC_RULES": {'
             '        "WatchList2|WatchList1|WatchList3": [ "[email protected]", ],'
@@ -105,6 +121,12 @@
             '        "WatchList1": {'
             '            "filename": r"WebCore/rendering/style/StyleFlexibleBoxData\.h",'
             '        },'
+            '        "WatchList2": {'
+            '            "filename": r"WillNotMatch",'
+            '        },'
+            '        "WatchList3": {'
+            '            "filename": r"WillNotMatch",'
+            '        },'
             '     },'
             '    "CC_RULES": {'
             '        "WatchList2|WatchList1|WatchList3": [ "[email protected]", ],'
@@ -126,6 +148,12 @@
             '        "WatchList1": {'
             '            "filename": r"WebCore/rendering/style/ThisFileDoesNotExist\.h",'
             '        },'
+            '        "WatchList2": {'
+            '            "filename": r"WillNotMatch",'
+            '        },'
+            '        "WatchList3": {'
+            '            "filename": r"WillNotMatch",'
+            '        },'
             '     },'
             '    "CC_RULES": {'
             '        "WatchList2|WatchList1|WatchList3": [ "[email protected]", ],'

Modified: trunk/Tools/Scripts/webkitpy/common/watchlist/watchlistparser.py (96389 => 96390)


--- trunk/Tools/Scripts/webkitpy/common/watchlist/watchlistparser.py	2011-09-30 05:15:58 UTC (rev 96389)
+++ trunk/Tools/Scripts/webkitpy/common/watchlist/watchlistparser.py	2011-09-30 05:22:55 UTC (rev 96390)
@@ -28,6 +28,7 @@
 
 import difflib
 import re
+
 from webkitpy.common.watchlist.changedlinepattern import ChangedLinePattern
 from webkitpy.common.watchlist.filenamepattern import FilenamePattern
 from webkitpy.common.watchlist.watchlist import WatchList
@@ -45,12 +46,12 @@
             self._DEFINITIONS: self._parse_definition_section,
             self._CC_RULES: self._parse_cc_rules,
             self._MESSAGE_RULES: self._parse_message_rules,
-            }
+        }
         self._definition_pattern_parsers = {
             'filename': FilenamePattern,
             'in_added_lines': (lambda regex: ChangedLinePattern(regex, 0)),
             'in_deleted_lines': (lambda regex: ChangedLinePattern(regex, 1)),
-            }
+        }
 
     def parse(self, watch_list_contents):
         watch_list = WatchList()
@@ -67,6 +68,7 @@
                                 % section)
             parser(dictionary[section], watch_list)
 
+        self._validate(watch_list)
         return watch_list
 
     def _eval_watch_list(self, watch_list_contents):
@@ -96,16 +98,52 @@
 
                 pattern = pattern_parser(definition[pattern_type])
                 definitions[name].append(pattern)
-        watch_list.set_definitions(definitions)
+            if not definitions[name]:
+                raise Exception('The definition "%s" has no patterns, so it should be deleted.' % name)
+        watch_list.definitions = definitions
 
     def _parse_rules(self, rules_section):
         rules = []
         for complex_definition in rules_section:
-            rules.append(WatchListRule(complex_definition, rules_section[complex_definition]))
+            instructions = rules_section[complex_definition]
+            if not instructions:
+                raise Exception('A rule for definition "%s" is empty, so it should be deleted.' % complex_definition)
+            rules.append(WatchListRule(complex_definition, instructions))
         return rules
 
     def _parse_cc_rules(self, cc_section, watch_list):
-        watch_list.set_cc_rules(self._parse_rules(cc_section))
+        watch_list.cc_rules = self._parse_rules(cc_section)
 
     def _parse_message_rules(self, message_section, watch_list):
-        watch_list.set_message_rules(self._parse_rules(message_section))
+        watch_list.message_rules = self._parse_rules(message_section)
+
+    def _validate(self, watch_list):
+        cc_definitions_set = self._rule_definitions_as_set(watch_list.cc_rules)
+        messages_definitions_set = self._rule_definitions_as_set(watch_list.message_rules)
+        self._verify_all_definitions_are_used(watch_list, cc_definitions_set.union(messages_definitions_set))
+
+        self._validate_definitions(cc_definitions_set, self._CC_RULES, watch_list)
+        self._validate_definitions(messages_definitions_set, self._MESSAGE_RULES, watch_list)
+
+    def _verify_all_definitions_are_used(self, watch_list, used_definitions):
+        definitions_not_used = set(watch_list.definitions.keys())
+        definitions_not_used.difference_update(used_definitions)
+        if definitions_not_used:
+            raise Exception('The following definitions are not used and should be removed: %s' % (', '.join(definitions_not_used)))
+
+    def _validate_definitions(self, definitions, rules_section_name, watch_list):
+        declared_definitions = watch_list.definitions.keys()
+        definition_set = set(definitions)
+        definition_set.difference_update(declared_definitions)
+
+        if definition_set:
+            suggestions = ''
+            if len(definition_set) == 1:
+                suggestions = self._suggest_words(set().union(definition_set).pop(), declared_definitions)
+            raise Exception('In section "%s", the following definitions are not used and should be removed: %s%s' % (rules_section_name, ', '.join(definition_set), suggestions))
+
+    def _rule_definitions_as_set(self, rules):
+        definition_set = set()
+        for rule in rules:
+            definition_set = definition_set.union(rule.definitions_to_match)
+        return definition_set

Modified: trunk/Tools/Scripts/webkitpy/common/watchlist/watchlistparser_unittest.py (96389 => 96390)


--- trunk/Tools/Scripts/webkitpy/common/watchlist/watchlistparser_unittest.py	2011-09-30 05:15:58 UTC (rev 96389)
+++ trunk/Tools/Scripts/webkitpy/common/watchlist/watchlistparser_unittest.py	2011-09-30 05:22:55 UTC (rev 96390)
@@ -87,3 +87,103 @@
         self.assertRaisesRegexp(r'Unknown pattern type "iflename" in definition "WatchList1"\.\s*'
                                 + r'Perhaps it should be filename\.',
                                 self._watch_list_parser.parse, watch_list_with_bad_match_type)
+
+    def test_empty_definition(self):
+        watch_list = (
+            '{'
+            '    "DEFINITIONS": {'
+            '        "WatchList1": {'
+            '        },'
+            '     },'
+            '}')
+
+        self.assertRaisesRegexp(r'The definition "WatchList1" has no patterns, so it should be deleted.',
+                                self._watch_list_parser.parse, watch_list)
+
+    def test_empty_cc_rule(self):
+        watch_list = (
+            '{'
+            '    "DEFINITIONS": {'
+            '        "WatchList1": {'
+            '            "filename": r".*\\MyFileName\\.cpp",'
+            '        },'
+            '     },'
+            '    "CC_RULES": {'
+            '        "WatchList1": [],'
+            '     },'
+            '}')
+
+        self.assertRaisesRegexp(r'A rule for definition "WatchList1" is empty, so it should be deleted.',
+                                self._watch_list_parser.parse, watch_list)
+
+    def test_empty_message_rule(self):
+        watch_list = (
+            '{'
+            '    "DEFINITIONS": {'
+            '        "WatchList1": {'
+            '            "filename": r".*\\MyFileName\\.cpp",'
+            '        },'
+            '     },'
+            '    "MESSAGE_RULES": {'
+            '        "WatchList1": ['
+            '        ],'
+            '     },'
+            '}')
+
+        self.assertRaisesRegexp(r'A rule for definition "WatchList1" is empty, so it should be deleted.',
+                                self._watch_list_parser.parse, watch_list)
+
+    def test_unused_defintion(self):
+        watch_list = (
+            '{'
+            '    "DEFINITIONS": {'
+            '        "WatchList1": {'
+            '            "filename": r".*\\MyFileName\\.cpp",'
+            '        },'
+            '     },'
+            '}')
+
+        self.assertRaisesRegexp(r'The following definitions are not used and should be removed: WatchList1',
+                                self._watch_list_parser.parse, watch_list)
+
+    def test_cc_rule_with_undefined_defintion(self):
+        watch_list = (
+            '{'
+            '    "CC_RULES": {'
+            '        "WatchList1": ["[email protected]"]'
+            '     },'
+            '}')
+
+        self.assertRaisesRegexp(r'In section "CC_RULES", the following definitions are not used and should be removed: WatchList1',
+                                self._watch_list_parser.parse, watch_list)
+
+    def test_message_rule_with_undefined_defintion(self):
+        watch_list = (
+            '{'
+            '    "MESSAGE_RULES": {'
+            '        "WatchList1": ["The message."]'
+            '     },'
+            '}')
+
+        self.assertRaisesRegexp(r'In section "MESSAGE_RULES", the following definitions are not used and should be removed: WatchList1',
+                                self._watch_list_parser.parse, watch_list)
+
+    def test_cc_rule_with_undefined_defintion_with_suggestion(self):
+        watch_list = (
+            '{'
+            '    "DEFINITIONS": {'
+            '        "WatchList1": {'
+            '            "filename": r".*\\MyFileName\\.cpp",'
+            '        },'
+            '     },'
+            '    "CC_RULES": {'
+            '        "WatchList": ["[email protected]"]'
+            '     },'
+            '    "MESSAGE_RULES": {'
+            '        "WatchList1": ["[email protected]"]'
+            '     },'
+            '}')
+
+        self.assertRaisesRegexp(r'In section "CC_RULES", the following definitions are not used and should be removed: WatchList\s*'
+                                r'Perhaps it should be WatchList1\.',
+                                self._watch_list_parser.parse, watch_list)

Modified: trunk/Tools/Scripts/webkitpy/common/watchlist/watchlistrule.py (96389 => 96390)


--- trunk/Tools/Scripts/webkitpy/common/watchlist/watchlistrule.py	2011-09-30 05:15:58 UTC (rev 96389)
+++ trunk/Tools/Scripts/webkitpy/common/watchlist/watchlistrule.py	2011-09-30 05:22:55 UTC (rev 96390)
@@ -30,11 +30,11 @@
 class WatchListRule:
     '''A rule with instructions to do when the rule is satisified.'''
     def __init__(self, complex_definition, instructions):
-        self._definitions_to_match = complex_definition.split('|')
+        self.definitions_to_match = complex_definition.split('|')
         self._instructions = instructions
 
     def match(self, matching_definitions):
-        for test_definition in self._definitions_to_match:
+        for test_definition in self.definitions_to_match:
             if test_definition in matching_definitions:
                 return True
         return False
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to