From c54fdfe1eaea59668e569136f5c246095a56ce69 Mon Sep 17 00:00:00 2001 From: "levin@chromium.org" Date: Sat, 1 Oct 2011 00:39:52 +0000 Subject: [PATCH] watchlist: Add a way to detect a net increase or decrease of a pattern (in a file). https://bugs.webkit.org/show_bug.cgi?id=69031 Reviewed by Adam Barth. * Scripts/webkitpy/common/config/watchlist: Added usage of the new pattern, a comment to explain something important about the email addresses, and a comment to let emacs know to treat the file as a python file. * Scripts/webkitpy/common/watchlist/amountchangedpattern.py: Added. Detects increases or decreases in a pattern. * Scripts/webkitpy/common/watchlist/amountchangedpattern_unittest.py: Added. * Scripts/webkitpy/common/watchlist/watchlist_unittest.py: Added unit tests for watchlist which has "more" or "less". * Scripts/webkitpy/common/watchlist/watchlistparser.py: Added support for "more" or "less". git-svn-id: http://svn.webkit.org/repository/webkit/trunk@96441 268f45cc-cd09-0410-ab3c-d52691b4dbfc --- Tools/ChangeLog | 18 ++++++ Tools/Scripts/webkitpy/common/config/watchlist | 14 ++++- .../common/watchlist/amountchangedpattern.py | 73 ++++++++++++++++++++++ .../watchlist/amountchangedpattern_unittest.py | 64 +++++++++++++++++++ .../common/watchlist/watchlist_unittest.py | 35 ++++++++++- .../webkitpy/common/watchlist/watchlistparser.py | 4 ++ 6 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 Tools/Scripts/webkitpy/common/watchlist/amountchangedpattern.py create mode 100644 Tools/Scripts/webkitpy/common/watchlist/amountchangedpattern_unittest.py diff --git a/Tools/ChangeLog b/Tools/ChangeLog index 6a79e0f..e9d1f77 100644 --- a/Tools/ChangeLog +++ b/Tools/ChangeLog @@ -1,3 +1,21 @@ +2011-09-30 David Levin + + watchlist: Add a way to detect a net increase or decrease of a pattern (in a file). + https://bugs.webkit.org/show_bug.cgi?id=69031 + + Reviewed by Adam Barth. + + * Scripts/webkitpy/common/config/watchlist: Added usage of the new pattern, + a comment to explain something important about the email addresses, and + a comment to let emacs know to treat the file as a python file. + * Scripts/webkitpy/common/watchlist/amountchangedpattern.py: Added. + Detects increases or decreases in a pattern. + * Scripts/webkitpy/common/watchlist/amountchangedpattern_unittest.py: Added. + * Scripts/webkitpy/common/watchlist/watchlist_unittest.py: + Added unit tests for watchlist which has "more" or "less". + * Scripts/webkitpy/common/watchlist/watchlistparser.py: + Added support for "more" or "less". + 2011-09-30 Sam Weinig Add support for eventSender.mouseScrollBy in WTR diff --git a/Tools/Scripts/webkitpy/common/config/watchlist b/Tools/Scripts/webkitpy/common/config/watchlist index 503e081..3c92326 100644 --- a/Tools/Scripts/webkitpy/common/config/watchlist +++ b/Tools/Scripts/webkitpy/common/config/watchlist @@ -1,10 +1,22 @@ +# -*- mode: Python;-*- { "DEFINITIONS": { "WatchListScript": { - "filename": (r"Tools/Scripts/webkitpy/common/watchlist/.*"), + "filename": r"Tools/Scripts/webkitpy/common/watchlist/.*", + }, + "ThreadingFiles": { + "filename": r"Source/JavaScriptCore/wtf/ThreadSafeRefCounted\.h" + r"|Source/JavaScriptCore/wtf/Threading\.h", + }, + "ThreadingUsage": { + "more": r"deprecatedTurnOffVerifier|crossThreadString|threadsafeCopy|ThreadSafeRefCounted|CrossThreadRefCounted", }, }, "CC_RULES": { + # Note: All email addresses listed must be registered with bugzilla. + # Specifically, levin@chromium.org and levin+threading@chromium.org are + # two different accounts as far as bugzilla is concerned. "WatchListScript": [ "levin+watchlist@chromium.org", ], + "ThreadingFiles|ThreadingUsage": [ "levin+threading@chromium.org", ], }, } diff --git a/Tools/Scripts/webkitpy/common/watchlist/amountchangedpattern.py b/Tools/Scripts/webkitpy/common/watchlist/amountchangedpattern.py new file mode 100644 index 0000000..e3dec84 --- /dev/null +++ b/Tools/Scripts/webkitpy/common/watchlist/amountchangedpattern.py @@ -0,0 +1,73 @@ +# Copyright (C) 2011 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +import re + + +class AmountChangedPattern: + def __init__(self, regex, index_for_zero_value): + self._regex = re.compile(regex) + self._index_for_zero_value = index_for_zero_value + + def match(self, path, diff_file): + examined_strings = set() + for diff_line in diff_file: + if diff_line[self._index_for_zero_value]: + continue + match = self._regex.search(diff_line[2]) + if not match: + continue + matching_string = match.group(0) + if matching_string in examined_strings: + continue + if self._instance_difference(diff_file, matching_string) > 0: + return True + # Avoid reprocessing this same string. + examined_strings.add(matching_string) + return False + + def _instance_difference(self, diff_file, matching_string): + '''Returns the difference between the number of string occurences in + the added lines and deleted lines (which one is subtracted from the + other depends on _index_for_zero_value).''' + count = 0 + for diff_line in diff_file: + # If the line is unchanged, then don't examine it. + if diff_line[self._index_for_zero_value] and diff_line[1 - self._index_for_zero_value]: + continue + location_found = -len(matching_string) + while True: + location_found = diff_line[2].find(matching_string, location_found + len(matching_string)) + if location_found == -1: + break + if not diff_line[self._index_for_zero_value]: + count += 1 + else: + count -= 1 + return count diff --git a/Tools/Scripts/webkitpy/common/watchlist/amountchangedpattern_unittest.py b/Tools/Scripts/webkitpy/common/watchlist/amountchangedpattern_unittest.py new file mode 100644 index 0000000..51aa15c --- /dev/null +++ b/Tools/Scripts/webkitpy/common/watchlist/amountchangedpattern_unittest.py @@ -0,0 +1,64 @@ +# Copyright (C) 2011 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +'''Unit tests for amountchangedpattern.py.''' + + +import unittest +from webkitpy.common.watchlist.amountchangedpattern import AmountChangedPattern + + +class AmountChangedPatternTest(unittest.TestCase): + + # A quick note about the diff file structure. + # The first column indicated the old line number. + # The second column indicates the new line number. + # 0 in either column indicates it had no old or new line number. + _DIFF_FILE = ((0, 1, 'hi hi'), + (1, 0, 'bye hi'), + (2, 2, 'other hi'), + (3, 0, 'both'), + (0, 3, 'both'), + ) + + def test_added_lines(self): + self.assertTrue(AmountChangedPattern('hi', 0).match(None, self._DIFF_FILE)) + self.assertTrue(AmountChangedPattern('hi hi', 0).match(None, self._DIFF_FILE)) + self.assertFalse(AmountChangedPattern('other', 0).match(None, self._DIFF_FILE)) + self.assertFalse(AmountChangedPattern('both', 0).match(None, self._DIFF_FILE)) + self.assertFalse(AmountChangedPattern('bye', 0).match(None, self._DIFF_FILE)) + self.assertFalse(AmountChangedPattern('MatchesNothing', 0).match(None, self._DIFF_FILE)) + + def test_removed_lines(self): + self.assertFalse(AmountChangedPattern('hi', 1).match(None, self._DIFF_FILE)) + self.assertFalse(AmountChangedPattern('hi hi', 1).match(None, self._DIFF_FILE)) + self.assertFalse(AmountChangedPattern('other', 1).match(None, self._DIFF_FILE)) + self.assertFalse(AmountChangedPattern('both', 1).match(None, self._DIFF_FILE)) + self.assertTrue(AmountChangedPattern('bye', 1).match(None, self._DIFF_FILE)) + self.assertFalse(AmountChangedPattern('MatchesNothing', 1).match(None, self._DIFF_FILE)) diff --git a/Tools/Scripts/webkitpy/common/watchlist/watchlist_unittest.py b/Tools/Scripts/webkitpy/common/watchlist/watchlist_unittest.py index 6bbc62b..b7fbd91 100644 --- a/Tools/Scripts/webkitpy/common/watchlist/watchlist_unittest.py +++ b/Tools/Scripts/webkitpy/common/watchlist/watchlist_unittest.py @@ -212,18 +212,49 @@ class WatchListTest(unittest.TestCase): 'messages': set(), }, cc_set_and_messages) + def test_more_and_less_match(self): + watch_list = self._watch_list_parser.parse( + '{' + ' "DEFINITIONS": {' + ' "WatchList1": {' + # This pattern is in both added and deleted lines, so no match. + ' "more": r"userSelect == o\.userSelect",' + ' },' + ' "WatchList2": {' + ' "more": r"boxOrient\(o\.boxOrient\)",' + ' },' + ' "WatchList3": {' + ' "less": r"unsigned orient"' + ' },' + ' },' + ' "CC_RULES": {' + ' "WatchList1": [ "eric@webkit.org", ],' + ' "WatchList2": [ "levin@chromium.org", ],' + ' },' + ' "MESSAGE_RULES": {' + ' "WatchList3": ["Test message."],' + ' },' + '}') + cc_set_and_messages = watch_list.determine_cc_set_and_messages(DIFF_TEST_DATA) + self.assertEquals({ + 'cc_set': set(['levin@chromium.org']), + 'messages': set(["Test message."]), + }, cc_set_and_messages) + def test_complex_match(self): watch_list = self._watch_list_parser.parse( '{' ' "DEFINITIONS": {' ' "WatchList1": {' ' "filename": r"WebCore/rendering/style/StyleRareInheritedData\.cpp",' - ' "in_added_lines": r"\&\& boxOrient == o.boxOrient;",' - ' "in_deleted_lines": r"\&\& userSelect == o.userSelect;",' + ' "in_added_lines": r"\&\& boxOrient == o\.boxOrient;",' + ' "in_deleted_lines": r"\&\& userSelect == o\.userSelect;",' + ' "more": r"boxOrient\(o\.boxOrient\)",' ' },' ' "WatchList2": {' ' "filename": r"WebCore/rendering/style/StyleRareInheritedData\.cpp",' ' "in_added_lines": r"RenderStyle::initialBoxOrient",' + ' "less": r"userSelect;"' ' },' # WatchList3 won't match because these two patterns aren't in the same file. ' "WatchList3": {' diff --git a/Tools/Scripts/webkitpy/common/watchlist/watchlistparser.py b/Tools/Scripts/webkitpy/common/watchlist/watchlistparser.py index b58e57e..7c3d600 100644 --- a/Tools/Scripts/webkitpy/common/watchlist/watchlistparser.py +++ b/Tools/Scripts/webkitpy/common/watchlist/watchlistparser.py @@ -26,9 +26,11 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + import difflib import re +from webkitpy.common.watchlist.amountchangedpattern import AmountChangedPattern from webkitpy.common.watchlist.changedlinepattern import ChangedLinePattern from webkitpy.common.watchlist.filenamepattern import FilenamePattern from webkitpy.common.watchlist.watchlist import WatchList @@ -51,6 +53,8 @@ class WatchListParser(object): 'filename': FilenamePattern, 'in_added_lines': (lambda regex: ChangedLinePattern(regex, 0)), 'in_deleted_lines': (lambda regex: ChangedLinePattern(regex, 1)), + 'less': (lambda regex: AmountChangedPattern(regex, 1)), + 'more': (lambda regex: AmountChangedPattern(regex, 0)), } def parse(self, watch_list_contents): -- 2.7.4