1 # Copyright (C) 2009 Google Inc. All rights reserved. 2 # 3 # Redistribution and use in source and binary forms, with or without 4 # modification, are permitted provided that the following conditions are 5 # met: 6 # 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 12 # distribution. 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. 16 # 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. 28 29 import unittest 30 31 from webkitpy.committers import CommitterList, Reviewer, Committer 32 from webkitpy.bugzilla import Bugzilla, BugzillaQueries, parse_bug_id, CommitterValidator 33 from webkitpy.outputcapture import OutputCapture 34 from webkitpy.mock import Mock 35 36 from webkitpy.BeautifulSoup import BeautifulSoup 37 38 39 class MockBrowser(object): 40 def open(self, url): 41 pass 42 43 def select_form(self, name): 44 pass 45 46 def __setitem__(self, key, value): 47 pass 48 49 def submit(self): 50 pass 51 52 class CommitterValidatorTest(unittest.TestCase): 53 def test_flag_permission_rejection_message(self): 54 validator = CommitterValidator(bugzilla=None) 55 expected_messsage="""foo (at] foo.com does not have review permissions according to http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/webkitpy/committers.py. 56 57 - If you do not have review rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags. 58 59 - If you have review rights please correct the error in WebKitTools/Scripts/webkitpy/committers.py by adding yourself to the file (no review needed). Due to bug 30084 the commit-queue will require a restart after your change. Please contact eseidel (at] chromium.org to request a commit-queue restart. After restart the commit-queue will correctly respect your review rights.""" 60 self.assertEqual(validator._flag_permission_rejection_message("foo (at] foo.com", "review"), expected_messsage) 61 62 63 class BugzillaTest(unittest.TestCase): 64 _example_attachment = ''' 65 <attachment 66 isobsolete="1" 67 ispatch="1" 68 isprivate="0" 69 > 70 <attachid>33721</attachid> 71 <date>2009-07-29 10:23 PDT</date> 72 <desc>Fixed whitespace issue</desc> 73 <filename>patch</filename> 74 <type>text/plain</type> 75 <size>9719</size> 76 <attacher>christian.plesner.hansen (at] gmail.com</attacher> 77 <flag name="review" 78 id="17931" 79 status="+" 80 setter="one (at] test.com" 81 /> 82 <flag name="commit-queue" 83 id="17932" 84 status="+" 85 setter="two (at] test.com" 86 /> 87 </attachment> 88 ''' 89 _expected_example_attachment_parsing = { 90 'bug_id' : 100, 91 'is_obsolete' : True, 92 'is_patch' : True, 93 'id' : 33721, 94 'url' : "https://bugs.webkit.org/attachment.cgi?id=33721", 95 'name' : "Fixed whitespace issue", 96 'type' : "text/plain", 97 'review' : '+', 98 'reviewer_email' : 'one (at] test.com', 99 'commit-queue' : '+', 100 'committer_email' : 'two (at] test.com', 101 'attacher_email' : 'christian.plesner.hansen (at] gmail.com', 102 } 103 104 def test_parse_bug_id(self): 105 # FIXME: These would be all better as doctests 106 bugs = Bugzilla() 107 self.assertEquals(12345, parse_bug_id("http://webkit.org/b/12345")) 108 self.assertEquals(12345, parse_bug_id("http://bugs.webkit.org/show_bug.cgi?id=12345")) 109 self.assertEquals(12345, parse_bug_id(bugs.short_bug_url_for_bug_id(12345))) 110 self.assertEquals(12345, parse_bug_id(bugs.bug_url_for_bug_id(12345))) 111 self.assertEquals(12345, parse_bug_id(bugs.bug_url_for_bug_id(12345, xml=True))) 112 113 # Our bug parser is super-fragile, but at least we're testing it. 114 self.assertEquals(None, parse_bug_id("http://www.webkit.org/b/12345")) 115 self.assertEquals(None, parse_bug_id("http://bugs.webkit.org/show_bug.cgi?ctype=xml&id=12345")) 116 117 _example_bug = """ 118 <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 119 <!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/bugzilla.dtd"> 120 <bugzilla version="3.2.3" 121 urlbase="https://bugs.webkit.org/" 122 maintainer="admin@webkit.org" 123 exporter="eric@webkit.org" 124 > 125 <bug> 126 <bug_id>32585</bug_id> 127 <creation_ts>2009-12-15 15:17 PST</creation_ts> 128 <short_desc>bug to test webkit-patch and commit-queue failures</short_desc> 129 <delta_ts>2009-12-27 21:04:50 PST</delta_ts> 130 <reporter_accessible>1</reporter_accessible> 131 <cclist_accessible>1</cclist_accessible> 132 <classification_id>1</classification_id> 133 <classification>Unclassified</classification> 134 <product>WebKit</product> 135 <component>Tools / Tests</component> 136 <version>528+ (Nightly build)</version> 137 <rep_platform>PC</rep_platform> 138 <op_sys>Mac OS X 10.5</op_sys> 139 <bug_status>NEW</bug_status> 140 <priority>P2</priority> 141 <bug_severity>Normal</bug_severity> 142 <target_milestone>---</target_milestone> 143 <everconfirmed>1</everconfirmed> 144 <reporter name="Eric Seidel">eric (at] webkit.org</reporter> 145 <assigned_to name="Nobody">webkit-unassigned (at] lists.webkit.org</assigned_to> 146 <cc>foo (at] bar.com</cc> 147 <cc>example (at] example.com</cc> 148 <long_desc isprivate="0"> 149 <who name="Eric Seidel">eric (at] webkit.org</who> 150 <bug_when>2009-12-15 15:17:28 PST</bug_when> 151 <thetext>bug to test webkit-patch and commit-queue failures 152 153 Ignore this bug. Just for testing failure modes of webkit-patch and the commit-queue.</thetext> 154 </long_desc> 155 <attachment 156 isobsolete="0" 157 ispatch="1" 158 isprivate="0" 159 > 160 <attachid>45548</attachid> 161 <date>2009-12-27 23:51 PST</date> 162 <desc>Patch</desc> 163 <filename>bug-32585-20091228005112.patch</filename> 164 <type>text/plain</type> 165 <size>10882</size> 166 <attacher>mjs (at] apple.com</attacher> 167 168 <token>1261988248-dc51409e9c421a4358f365fa8bec8357</token> 169 <data encoding="base64">SW5kZXg6IFdlYktpdC9tYWMvQ2hhbmdlTG9nCj09PT09PT09PT09PT09PT09PT09PT09PT09PT09 170 removed-because-it-was-really-long 171 ZEZpbmlzaExvYWRXaXRoUmVhc29uOnJlYXNvbl07Cit9CisKIEBlbmQKIAogI2VuZGlmCg== 172 </data> 173 174 <flag name="review" 175 id="27602" 176 status="?" 177 setter="mjs@apple.com" 178 /> 179 </attachment> 180 </bug> 181 </bugzilla> 182 """ 183 _expected_example_bug_parsing = { 184 "id" : 32585, 185 "title" : u"bug to test webkit-patch and commit-queue failures", 186 "cc_emails" : ["foo (at] bar.com", "example (at] example.com"], 187 "reporter_email" : "eric (at] webkit.org", 188 "assigned_to_email" : "webkit-unassigned (at] lists.webkit.org", 189 "attachments" : [{ 190 'name': u'Patch', 191 'url' : "https://bugs.webkit.org/attachment.cgi?id=45548", 192 'is_obsolete': False, 193 'review': '?', 194 'is_patch': True, 195 'attacher_email': 'mjs (at] apple.com', 196 'bug_id': 32585, 197 'type': 'text/plain', 198 'id': 45548 199 }], 200 } 201 202 def _assert_dictionaries_equal(self, actual, expected): 203 # Make sure we aren't parsing more or less than we expect 204 self.assertEquals(sorted(actual.keys()), sorted(expected.keys())) 205 206 for key, expected_value in expected.items(): 207 self.assertEquals(actual[key], expected_value, ("Failure for key: %s: Actual='%s' Expected='%s'" % (key, actual[key], expected_value))) 208 209 def test_bug_parsing(self): 210 bug = Bugzilla()._parse_bug_page(self._example_bug) 211 self._assert_dictionaries_equal(bug, self._expected_example_bug_parsing) 212 213 # This could be combined into test_bug_parsing later if desired. 214 def test_attachment_parsing(self): 215 bugzilla = Bugzilla() 216 soup = BeautifulSoup(self._example_attachment) 217 attachment_element = soup.find("attachment") 218 attachment = bugzilla._parse_attachment_element(attachment_element, self._expected_example_attachment_parsing['bug_id']) 219 self.assertTrue(attachment) 220 self._assert_dictionaries_equal(attachment, self._expected_example_attachment_parsing) 221 222 _sample_attachment_detail_page = """ 223 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 224 "http://www.w3.org/TR/html4/loose.dtd"> 225 <html> 226 <head> 227 <title> 228 Attachment 41073 Details for Bug 27314</title> 229 <link rel="Top" href="https://bugs.webkit.org/"> 230 <link rel="Up" href="show_bug.cgi?id=27314"> 231 """ 232 233 def test_attachment_detail_bug_parsing(self): 234 bugzilla = Bugzilla() 235 self.assertEquals(27314, bugzilla._parse_bug_id_from_attachment_page(self._sample_attachment_detail_page)) 236 237 def test_add_cc_to_bug(self): 238 bugzilla = Bugzilla() 239 bugzilla.browser = MockBrowser() 240 bugzilla.authenticate = lambda: None 241 expected_stderr = "Adding ['adam (at] example.com'] to the CC list for bug 42\n" 242 OutputCapture().assert_outputs(self, bugzilla.add_cc_to_bug, [42, ["adam (at] example.com"]], expected_stderr=expected_stderr) 243 244 245 class BugzillaQueriesTest(unittest.TestCase): 246 _sample_request_page = """ 247 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 248 "http://www.w3.org/TR/html4/loose.dtd"> 249 <html> 250 <head> 251 <title>Request Queue</title> 252 </head> 253 <body> 254 255 <h3>Flag: review</h3> 256 <table class="requests" cellspacing="0" cellpadding="4" border="1"> 257 <tr> 258 <th>Requester</th> 259 <th>Requestee</th> 260 <th>Bug</th> 261 <th>Attachment</th> 262 <th>Created</th> 263 </tr> 264 <tr> 265 <td>Shinichiro Hamaji <hamaji@chromium.org></td> 266 <td></td> 267 <td><a href="show_bug.cgi?id=30015">30015: text-transform:capitalize is failing in CSS2.1 test suite</a></td> 268 <td><a href="attachment.cgi?id=40511&action=review"> 269 40511: Patch v0</a></td> 270 <td>2009-10-02 04:58 PST</td> 271 </tr> 272 <tr> 273 <td>Zan Dobersek <zandobersek@gmail.com></td> 274 <td></td> 275 <td><a href="show_bug.cgi?id=26304">26304: [GTK] Add controls for playing html5 video.</a></td> 276 <td><a href="attachment.cgi?id=40722&action=review"> 277 40722: Media controls, the simple approach</a></td> 278 <td>2009-10-06 09:13 PST</td> 279 </tr> 280 <tr> 281 <td>Zan Dobersek <zandobersek@gmail.com></td> 282 <td></td> 283 <td><a href="show_bug.cgi?id=26304">26304: [GTK] Add controls for playing html5 video.</a></td> 284 <td><a href="attachment.cgi?id=40723&action=review"> 285 40723: Adjust the media slider thumb size</a></td> 286 <td>2009-10-06 09:15 PST</td> 287 </tr> 288 </table> 289 </body> 290 </html> 291 """ 292 293 def test_request_page_parsing(self): 294 queries = BugzillaQueries(None) 295 self.assertEquals([40511, 40722, 40723], queries._parse_attachment_ids_request_query(self._sample_request_page)) 296 297 def test_load_query(self): 298 queries = BugzillaQueries(Mock()) 299 queries._load_query("request.cgi?action=queue&type=review&group=type") 300 301 302 if __name__ == '__main__': 303 unittest.main() 304