1 # Copyright (C) 2009 Google Inc. All rights reserved.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the
13 # * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
30 from webkitpy.common.config.committers import Account, CommitterList, Contributor, Committer, Reviewer
32 class CommittersTest(unittest.TestCase):
33 def test_committer_lookup(self):
34 account = Account('Test Zero', ['zero@test.com', 'zero@gmail.com'], 'zero')
35 committer = Committer('Test One', 'one@test.com', 'one')
36 reviewer = Reviewer('Test Two', ['two@test.com', 'Two@rad.com', 'so_two@gmail.com'])
37 contributor = Contributor('Test Three', ['Three@test.com'], 'three')
38 contributor_with_two_nicknames = Contributor('Other Four', ['otherfour@webkit.org', 'otherfour@webkit2.org'], ['four', 'otherfour'])
39 contributor_with_same_email_username = Contributor('Yet Another Four', ['otherfour@webkit.com'], ['yetanotherfour'])
40 committer_list = CommitterList(watchers=[account], committers=[committer], reviewers=[reviewer],
41 contributors=[contributor, contributor_with_two_nicknames, contributor_with_same_email_username])
43 # Test valid committer, reviewer and contributor lookup
44 self.assertEqual(committer_list.account_by_email('zero@test.com'), account)
45 self.assertEqual(committer_list.committer_by_email('one@test.com'), committer)
46 self.assertEqual(committer_list.reviewer_by_email('two@test.com'), reviewer)
47 self.assertEqual(committer_list.committer_by_email('two@test.com'), reviewer)
48 self.assertEqual(committer_list.committer_by_email('two@rad.com'), reviewer)
49 self.assertEqual(committer_list.reviewer_by_email('so_two@gmail.com'), reviewer)
50 self.assertEqual(committer_list.contributor_by_email('three@test.com'), contributor)
52 # Test valid committer, reviewer and contributor lookup
53 self.assertEqual(committer_list.committer_by_name("Test One"), committer)
54 self.assertEqual(committer_list.committer_by_name("Test Two"), reviewer)
55 self.assertEqual(committer_list.committer_by_name("Test Three"), None)
56 self.assertEqual(committer_list.contributor_by_name("Test Three"), contributor)
57 self.assertEqual(committer_list.contributor_by_name("test one"), committer)
58 self.assertEqual(committer_list.contributor_by_name("test two"), reviewer)
59 self.assertEqual(committer_list.contributor_by_name("test three"), contributor)
61 # Test that the first email is assumed to be the Bugzilla email address (for now)
62 self.assertEqual(committer_list.committer_by_email('two@rad.com').bugzilla_email(), 'two@test.com')
64 # Test lookup by login email address
65 self.assertEqual(committer_list.account_by_login('zero@test.com'), account)
66 self.assertEqual(committer_list.account_by_login('zero@gmail.com'), None)
67 self.assertEqual(committer_list.account_by_login('one@test.com'), committer)
68 self.assertEqual(committer_list.account_by_login('two@test.com'), reviewer)
69 self.assertEqual(committer_list.account_by_login('Two@rad.com'), None)
70 self.assertEqual(committer_list.account_by_login('so_two@gmail.com'), None)
72 # Test that a known committer is not returned during reviewer lookup
73 self.assertEqual(committer_list.reviewer_by_email('one@test.com'), None)
74 self.assertEqual(committer_list.reviewer_by_email('three@test.com'), None)
75 # and likewise that a known contributor is not returned for committer lookup.
76 self.assertEqual(committer_list.committer_by_email('three@test.com'), None)
78 # Test that unknown email address fail both committer and reviewer lookup
79 self.assertEqual(committer_list.committer_by_email('bar@bar.com'), None)
80 self.assertEqual(committer_list.reviewer_by_email('bar@bar.com'), None)
82 # Test that emails returns a list.
83 self.assertEqual(committer.emails, ['one@test.com'])
85 self.assertEqual(committer.irc_nicknames, ['one'])
86 self.assertEqual(committer_list.contributor_by_irc_nickname('one'), committer)
87 self.assertEqual(committer_list.contributor_by_irc_nickname('three'), contributor)
88 self.assertEqual(committer_list.contributor_by_irc_nickname('four'), contributor_with_two_nicknames)
89 self.assertEqual(committer_list.contributor_by_irc_nickname('otherfour'), contributor_with_two_nicknames)
91 # Test that the lists returned are are we expect them.
92 self.assertEqual(committer_list.contributors(), [contributor, contributor_with_two_nicknames, contributor_with_same_email_username, committer, reviewer])
93 self.assertEqual(committer_list.committers(), [committer, reviewer])
94 self.assertEqual(committer_list.reviewers(), [reviewer])
96 self.assertEqual(committer_list.contributors_by_search_string('test'), [contributor, committer, reviewer])
97 self.assertEqual(committer_list.contributors_by_search_string('rad'), [reviewer])
98 self.assertEqual(committer_list.contributors_by_search_string('Two'), [reviewer])
100 self.assertEqual(committer_list.contributors_by_email_username("one"), [committer])
101 self.assertEqual(committer_list.contributors_by_email_username("four"), [])
102 self.assertEqual(committer_list.contributors_by_email_username("otherfour"), [contributor_with_two_nicknames, contributor_with_same_email_username])
104 def _assert_fuzz_match(self, text, name_of_expected_contributor, expected_distance):
105 committers = CommitterList()
106 contributors, distance = committers.contributors_by_fuzzy_match(text)
107 expected_names = [name_of_expected_contributor] if name_of_expected_contributor else []
108 self.assertEqual(([contributor.full_name for contributor in contributors], distance), (expected_names, expected_distance))
110 def test_contributors_by_fuzzy_match(self):
111 self._assert_fuzz_match('Geoff Garen', 'Geoffrey Garen', 3)
112 self._assert_fuzz_match('Kenneth Christiansen', 'Kenneth Rohde Christiansen', 6)
113 self._assert_fuzz_match('Ken Russell', 'Kenneth Russell', 4)
114 self._assert_fuzz_match('Dave Hyatt', 'David Hyatt', 2)
115 self._assert_fuzz_match('Dave Kilzer', 'David Kilzer', 2)
116 self._assert_fuzz_match('Antti "printf" Koivisto', 'Antti Koivisto', 9)
117 self._assert_fuzz_match('Sammy Weinig', 'Sam Weinig', 2)
118 self._assert_fuzz_match('Andres Kling', 'Andreas Kling', 1)
119 self._assert_fuzz_match('Darin Adler\'', 'Darin Adler', 1)
120 self._assert_fuzz_match('Joe Pecoraro', 'Joseph Pecoraro', 3)
121 self._assert_fuzz_match('Dr Dan Bernstein', 'Dan Bernstein', 3)
122 self._assert_fuzz_match('Mitzpettel', 'Dan Bernstein', 0)
123 self._assert_fuzz_match('rniwa@webkit.org', 'Ryosuke Niwa', 0)
124 self._assert_fuzz_match('Ap', 'Alexey Proskuryakov', 0)
125 self._assert_fuzz_match('Sam', 'Sam Weinig', 0)
126 self._assert_fuzz_match('darin', 'Darin Adler', 0)
127 self._assert_fuzz_match('harrison', 'David Harrison', 0)
128 self._assert_fuzz_match('me', None, 2)
129 self._assert_fuzz_match('myself', None, 6)
130 self._assert_fuzz_match('others', None, 6)
131 self._assert_fuzz_match('BUILD FIX', None, 9)
132 self._assert_fuzz_match('but Dan Bernstein also reviewed', None, 31)
133 self._assert_fuzz_match('asked thoughtful questions', None, 26)
134 self._assert_fuzz_match('build fix of mac', None, 16)
135 self._assert_fuzz_match('a spell checker', None, 15)
136 self._assert_fuzz_match('nobody, build fix', None, 17)
137 self._assert_fuzz_match('NOBODY (chromium build fix)', None, 27)
139 def test_contributors_by_fuzzy_match_with_legacy_names(self):
140 # Commented out lines are test cases imported from the bug 26533 yet to pass.
142 self._assert_fuzz_match('Ada', 'Ada Chan', 0)
143 self._assert_fuzz_match('adele', 'Adele Peterson', 0)
144 # self._assert_fuzz_match('Adam', 'Adam Roben', 0)
145 self._assert_fuzz_match('aroben', 'Adam Roben', 0)
146 # self._assert_fuzz_match('Alexey', 'Alexey Proskuryakov', 0)
147 self._assert_fuzz_match('ap', 'Alexey Proskuryakov', 0)
148 self._assert_fuzz_match('Alexey P', 'Alexey Proskuryakov', 0)
149 # self._assert_fuzz_match('Alice', 'Alice Liu', 0)
150 self._assert_fuzz_match('aliu', 'Alice Liu', 0)
151 self._assert_fuzz_match('Liu', 'Alice Liu', 0)
152 self._assert_fuzz_match('Alp', 'Alp Toker', 0)
153 self._assert_fuzz_match('Anders', 'Anders Carlsson', 0)
154 self._assert_fuzz_match('andersca', 'Anders Carlsson', 0)
155 self._assert_fuzz_match('anders', 'Anders Carlsson', 0)
156 self._assert_fuzz_match('Andersca', 'Anders Carlsson', 0)
157 self._assert_fuzz_match('Antti', 'Antti Koivisto', 0)
159 self._assert_fuzz_match('Beth', 'Beth Dakin', 0)
160 self._assert_fuzz_match('beth', 'Beth Dakin', 0)
161 self._assert_fuzz_match('bdakin', 'Beth Dakin', 0)
162 self._assert_fuzz_match('Brady', 'Brady Eidson', 0)
163 self._assert_fuzz_match('bradee-oh', 'Brady Eidson', 0)
165 # self._assert_fuzz_match('Cameron', 'Cameron Zwarich', 0)
166 # self._assert_fuzz_match('cpst', 'Cameron Zwarich', 1)
167 # self._assert_fuzz_match('Chris', 'Chris Blumenberg', 0)
168 self._assert_fuzz_match('cblu', 'Chris Blumenberg', 0)
170 self._assert_fuzz_match('Dan', 'Dan Bernstein', 0)
171 self._assert_fuzz_match('Dan B', 'Dan Bernstein', 0)
172 # self._assert_fuzz_match('mitz', 'Dan Bernstein', 0)
173 self._assert_fuzz_match('Mitz Pettel', 'Dan Bernstein', 1)
174 self._assert_fuzz_match('Mitzpettel', 'Dan Bernstein', 0)
175 self._assert_fuzz_match('Mitz Pettel RTL', 'Dan Bernstein', 5)
176 self._assert_fuzz_match('Teh Mitzpettel', 'Dan Bernstein', 4)
177 # self._assert_fuzz_match('The Mitz', 'Dan Bernstein', 0)
179 self._assert_fuzz_match('Darin', 'Darin Adler', 0) # Thankfully "Fisher" is longer than "Adler"
181 self._assert_fuzz_match('Dave Harrison', 'David Harrison', 2)
182 self._assert_fuzz_match('harrison', 'David Harrison', 0)
183 self._assert_fuzz_match('Dr. Harrison', 'David Harrison', 4)
184 self._assert_fuzz_match('Dave Harrson', 'David Harrison', 3)
185 self._assert_fuzz_match('Dave Harrsion', 'David Harrison', 4) # Damerau-Levenshtein distance is 3
187 self._assert_fuzz_match('Daddy Hyatt', 'David Hyatt', 3)
188 # self._assert_fuzz_match('Dave', 'David Hyatt', 0) # 'Dave' could mean harrison.
189 self._assert_fuzz_match('hyatt', 'David Hyatt', 0)
190 # self._assert_fuzz_match('Haytt', 'David Hyatt', 0) # Works if we had implemented Damerau-Levenshtein distance!
191 self._assert_fuzz_match('Dave Kilzer', 'David Kilzer', 2)
192 self._assert_fuzz_match('David D. Kilzer', 'David Kilzer', 3)
193 self._assert_fuzz_match('ddkilzer', 'David Kilzer', 0)
194 self._assert_fuzz_match('Don', 'Don Melton', 0)
195 self._assert_fuzz_match('Gramps', 'Don Melton', 0)
197 # self._assert_fuzz_match('eric', 'Eric Seidel', 0)
198 self._assert_fuzz_match('Eric S', 'Eric Seidel', 0)
199 # self._assert_fuzz_match('MacDome', 'Eric Seidel', 0)
200 self._assert_fuzz_match('eseidel', 'Eric Seidel', 0)
202 # self._assert_fuzz_match('Geof', 'Geoffrey Garen', 4)
203 # self._assert_fuzz_match('Geoff', 'Geoffrey Garen', 3)
204 self._assert_fuzz_match('Geoff Garen', 'Geoffrey Garen', 3)
205 self._assert_fuzz_match('ggaren', 'Geoffrey Garen', 0)
206 # self._assert_fuzz_match('geoff', 'Geoffrey Garen', 0)
207 self._assert_fuzz_match('Geoffrey', 'Geoffrey Garen', 0)
208 self._assert_fuzz_match('GGaren', 'Geoffrey Garen', 0)
209 # self._assert_fuzz_match('Greg', 'Greg Bolsinga', 0)
211 self._assert_fuzz_match('Holger', 'Holger Freyther', 0)
212 self._assert_fuzz_match('Holger Hans Peter Freyther', 'Holger Freyther', 11)
214 # self._assert_fuzz_match('john', 'John Sullivan', 0)
215 self._assert_fuzz_match('sullivan', 'John Sullivan', 0)
216 self._assert_fuzz_match('John Honeycutt', 'Jon Honeycutt', 1)
217 # self._assert_fuzz_match('Jon', 'Jon Honeycutt', 0)
218 # self._assert_fuzz_match('justin', 'Justin Garcia', 0)
219 self._assert_fuzz_match('justing', 'Justin Garcia', 0)
221 self._assert_fuzz_match('ken', 'Ken Kocienda', 0)
222 self._assert_fuzz_match('kocienda', 'Ken Kocienda', 0)
223 self._assert_fuzz_match('kdecker', 'Kevin Decker', 0)
224 self._assert_fuzz_match('Kevin M', 'Kevin McCullough', 0)
225 self._assert_fuzz_match('Kevin McCulough', 'Kevin McCullough', 1)
226 self._assert_fuzz_match('mccullough', 'Kevin McCullough', 0)
228 self._assert_fuzz_match('lars', 'Lars Knoll', 0)
229 self._assert_fuzz_match('levi', 'Levi Weintraub', 0)
231 self._assert_fuzz_match('Maciej', 'Maciej Stachowiak', 0)
232 # self._assert_fuzz_match('mjs', 'Maciej Stachowiak', 0)
233 self._assert_fuzz_match('Maciej S', 'Maciej Stachowiak', 0)
235 # self._assert_fuzz_match('Mark', 'Mark Rowe', 0)
236 self._assert_fuzz_match('bdash', 'Mark Rowe', 0)
237 self._assert_fuzz_match('mrowe', 'Mark Rowe', 0)
238 # self._assert_fuzz_match('Brian Dash', 'Mark Rowe', 0)
240 # self._assert_fuzz_match('Niko', 'Nikolas Zimmermann', 1)
241 self._assert_fuzz_match('Niko Zimmermann', 'Nikolas Zimmermann', 3)
242 self._assert_fuzz_match('Nikolas', 'Nikolas Zimmermann', 0)
244 # self._assert_fuzz_match('Oliver', 'Oliver Hunt', 0)
245 self._assert_fuzz_match('Ollie', 'Oliver Hunt', 1)
246 self._assert_fuzz_match('Olliej', 'Oliver Hunt', 0)
247 self._assert_fuzz_match('Olliej Hunt', 'Oliver Hunt', 3)
248 self._assert_fuzz_match('olliej', 'Oliver Hunt', 0)
249 self._assert_fuzz_match('ollie', 'Oliver Hunt', 1)
250 self._assert_fuzz_match('ollliej', 'Oliver Hunt', 1)
252 self._assert_fuzz_match('Richard', 'Richard Williamson', 0)
253 self._assert_fuzz_match('rjw', 'Richard Williamson', 0)
254 self._assert_fuzz_match('Rob', 'Rob Buis', 0)
255 self._assert_fuzz_match('rwlbuis', 'Rob Buis', 0)
257 self._assert_fuzz_match('Sam', 'Sam Weinig', 0)
258 # self._assert_fuzz_match('Weinig Sam', 'weinig', 0)
259 self._assert_fuzz_match('Weinig', 'Sam Weinig', 0)
260 self._assert_fuzz_match('Sam W', 'Sam Weinig', 0)
261 self._assert_fuzz_match('Sammy Weinig', 'Sam Weinig', 2)
262 # self._assert_fuzz_match('Simon', 'Simon Fraser', 0)
263 self._assert_fuzz_match('Sfalken', 'Steve Falkenburg', 0)
264 # self._assert_fuzz_match('Steve', 'Steve Falkenburg', 0)
266 # self._assert_fuzz_match('timo', 'Tim Omernick', 0)
267 self._assert_fuzz_match('TimO', 'Tim Omernick', 0)
268 # self._assert_fuzz_match('Timo O', 'Tim Omernick', 0)
269 # self._assert_fuzz_match('Tim O.', 'Tim Omernick', 0)
270 self._assert_fuzz_match('Tim O', 'Tim Omernick', 0)
272 # self._assert_fuzz_match('Tim', 'Timothy Hatcher', 0)
273 # self._assert_fuzz_match('Tim H', 'Timothy Hatcher', 0)
274 self._assert_fuzz_match('Tim Hatcher', 'Timothy Hatcher', 4)
275 self._assert_fuzz_match('Tim Hatcheri', 'Timothy Hatcher', 5)
276 self._assert_fuzz_match('timothy', 'Timothy Hatcher', 0)
277 self._assert_fuzz_match('thatcher', 'Timothy Hatcher', 1)
278 self._assert_fuzz_match('xenon', 'Timothy Hatcher', 0)
279 self._assert_fuzz_match('Hatcher', 'Timothy Hatcher', 0)
280 # self._assert_fuzz_match('TimH', 'Timothy Hatcher', 0)
282 self._assert_fuzz_match('Tor Arne', u"Tor Arne Vestb\u00f8", 1) # Matches IRC nickname
283 self._assert_fuzz_match('Vicki', u"Vicki Murley", 0)
284 self._assert_fuzz_match('Zack', 'Zack Rusin', 0)