|
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 os |
|
30 |
|
31 from webkitpy.common.net.bugzilla import Attachment |
|
32 from webkitpy.common.system.outputcapture import OutputCapture |
|
33 from webkitpy.thirdparty.mock import Mock |
|
34 from webkitpy.tool.commands.commandtest import CommandsTest |
|
35 from webkitpy.tool.commands.queues import * |
|
36 from webkitpy.tool.commands.queuestest import QueuesTest |
|
37 from webkitpy.tool.mocktool import MockTool, MockSCM |
|
38 |
|
39 |
|
40 class TestQueue(AbstractPatchQueue): |
|
41 name = "test-queue" |
|
42 |
|
43 |
|
44 class TestReviewQueue(AbstractReviewQueue): |
|
45 name = "test-review-queue" |
|
46 |
|
47 |
|
48 class MockPatch(object): |
|
49 def is_rollout(self): |
|
50 return True |
|
51 |
|
52 def bug_id(self): |
|
53 return 12345 |
|
54 |
|
55 def id(self): |
|
56 return 76543 |
|
57 |
|
58 |
|
59 class AbstractQueueTest(CommandsTest): |
|
60 def _assert_log_progress_output(self, patch_ids, progress_output): |
|
61 OutputCapture().assert_outputs(self, TestQueue().log_progress, [patch_ids], expected_stderr=progress_output) |
|
62 |
|
63 def test_log_progress(self): |
|
64 self._assert_log_progress_output([1,2,3], "3 patches in test-queue [1, 2, 3]\n") |
|
65 self._assert_log_progress_output(["1","2","3"], "3 patches in test-queue [1, 2, 3]\n") |
|
66 self._assert_log_progress_output([1], "1 patch in test-queue [1]\n") |
|
67 |
|
68 def test_log_directory(self): |
|
69 self.assertEquals(TestQueue()._log_directory(), "test-queue-logs") |
|
70 |
|
71 def _assert_run_webkit_patch(self, run_args): |
|
72 queue = TestQueue() |
|
73 tool = MockTool() |
|
74 tool.executive = Mock() |
|
75 queue.bind_to_tool(tool) |
|
76 |
|
77 queue.run_webkit_patch(run_args) |
|
78 expected_run_args = ["echo", "--status-host=example.com"] + run_args |
|
79 tool.executive.run_and_throw_if_fail.assert_called_with(expected_run_args) |
|
80 |
|
81 def test_run_webkit_patch(self): |
|
82 self._assert_run_webkit_patch([1]) |
|
83 self._assert_run_webkit_patch(["one", 2]) |
|
84 |
|
85 def test_iteration_count(self): |
|
86 queue = TestQueue() |
|
87 queue.options = Mock() |
|
88 queue.options.iterations = 3 |
|
89 self.assertTrue(queue.should_continue_work_queue()) |
|
90 self.assertTrue(queue.should_continue_work_queue()) |
|
91 self.assertTrue(queue.should_continue_work_queue()) |
|
92 self.assertFalse(queue.should_continue_work_queue()) |
|
93 |
|
94 def test_no_iteration_count(self): |
|
95 queue = TestQueue() |
|
96 queue.options = Mock() |
|
97 self.assertTrue(queue.should_continue_work_queue()) |
|
98 self.assertTrue(queue.should_continue_work_queue()) |
|
99 self.assertTrue(queue.should_continue_work_queue()) |
|
100 self.assertTrue(queue.should_continue_work_queue()) |
|
101 |
|
102 |
|
103 class AbstractReviewQueueTest(CommandsTest): |
|
104 def test_patch_collection_delegate_methods(self): |
|
105 queue = TestReviewQueue() |
|
106 tool = MockTool() |
|
107 queue.bind_to_tool(tool) |
|
108 self.assertEquals(queue.collection_name(), "test-review-queue") |
|
109 self.assertEquals(queue.fetch_potential_patch_ids(), [103]) |
|
110 queue.status_server() |
|
111 self.assertTrue(queue.is_terminal_status("Pass")) |
|
112 self.assertTrue(queue.is_terminal_status("Fail")) |
|
113 self.assertTrue(queue.is_terminal_status("Error: Your patch exploded")) |
|
114 self.assertFalse(queue.is_terminal_status("Foo")) |
|
115 |
|
116 |
|
117 class CommitQueueTest(QueuesTest): |
|
118 def test_commit_queue(self): |
|
119 expected_stderr = { |
|
120 "begin_work_queue" : "CAUTION: commit-queue will discard all local changes in \"%s\"\nRunning WebKit commit-queue.\n" % MockSCM.fake_checkout_root, |
|
121 "should_proceed_with_work_item": "MOCK: update_status: commit-queue Landing patch\n", |
|
122 # FIXME: The commit-queue warns about bad committers twice. This is due to the fact that we access Attachment.reviewer() twice and it logs each time. |
|
123 "next_work_item" : """Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) |
|
124 Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) |
|
125 MOCK setting flag 'commit-queue' to '-' on attachment '128' with comment 'Rejecting patch 128 from commit-queue.' and additional comment 'non-committer@example.com does not have committer permissions according to http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/webkitpy/common/config/committers.py.\n\n- If you do not have committer rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags.\n\n- If you have committer rights please correct the error in WebKitTools/Scripts/webkitpy/common/config/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@chromium.org to request a commit-queue restart. After restart the commit-queue will correctly respect your committer rights.' |
|
126 MOCK: update_work_items: commit-queue [106, 197] |
|
127 2 patches in commit-queue [106, 197] |
|
128 """, |
|
129 "process_work_item" : "MOCK: update_status: commit-queue Pass\n", |
|
130 "handle_unexpected_error" : "MOCK setting flag 'commit-queue' to '-' on attachment '1234' with comment 'Rejecting patch 1234 from commit-queue.' and additional comment 'Mock error message'\n", |
|
131 "handle_script_error": "MOCK: update_status: commit-queue ScriptError error message\nMOCK setting flag 'commit-queue' to '-' on attachment '1234' with comment 'Rejecting patch 1234 from commit-queue.' and additional comment 'ScriptError error message'\n", |
|
132 } |
|
133 self.assert_queue_outputs(CommitQueue(), expected_stderr=expected_stderr) |
|
134 |
|
135 def test_rollout(self): |
|
136 tool = MockTool(log_executive=True) |
|
137 tool.buildbot.light_tree_on_fire() |
|
138 expected_stderr = { |
|
139 "begin_work_queue" : "CAUTION: commit-queue will discard all local changes in \"%s\"\nRunning WebKit commit-queue.\n" % MockSCM.fake_checkout_root, |
|
140 "should_proceed_with_work_item": "MOCK: update_status: commit-queue Landing patch\n", |
|
141 # FIXME: The commit-queue warns about bad committers twice. This is due to the fact that we access Attachment.reviewer() twice and it logs each time. |
|
142 "next_work_item" : """Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) |
|
143 Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) |
|
144 MOCK setting flag 'commit-queue' to '-' on attachment '128' with comment 'Rejecting patch 128 from commit-queue.' and additional comment 'non-committer@example.com does not have committer permissions according to http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/webkitpy/common/config/committers.py. |
|
145 |
|
146 - If you do not have committer rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags. |
|
147 |
|
148 - If you have committer rights please correct the error in WebKitTools/Scripts/webkitpy/common/config/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@chromium.org to request a commit-queue restart. After restart the commit-queue will correctly respect your committer rights.' |
|
149 MOCK: update_work_items: commit-queue [106, 197] |
|
150 2 patches in commit-queue [106, 197] |
|
151 """, |
|
152 "process_work_item" : "MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'land-attachment', '--force-clean', '--build', '--non-interactive', '--ignore-builders', '--build-style=both', '--quiet', 1234, '--test']\nMOCK: update_status: commit-queue Pass\n", |
|
153 "handle_unexpected_error" : "MOCK setting flag 'commit-queue' to '-' on attachment '1234' with comment 'Rejecting patch 1234 from commit-queue.' and additional comment 'Mock error message'\n", |
|
154 "handle_script_error": "MOCK: update_status: commit-queue ScriptError error message\nMOCK setting flag 'commit-queue' to '-' on attachment '1234' with comment 'Rejecting patch 1234 from commit-queue.' and additional comment 'ScriptError error message'\n", |
|
155 } |
|
156 self.assert_queue_outputs(CommitQueue(), tool=tool, expected_stderr=expected_stderr) |
|
157 |
|
158 def test_rollout_lands(self): |
|
159 tool = MockTool(log_executive=True) |
|
160 tool.buildbot.light_tree_on_fire() |
|
161 rollout_patch = MockPatch() |
|
162 expected_stderr = { |
|
163 "begin_work_queue": "CAUTION: commit-queue will discard all local changes in \"%s\"\nRunning WebKit commit-queue.\n" % MockSCM.fake_checkout_root, |
|
164 "should_proceed_with_work_item": "MOCK: update_status: commit-queue Landing rollout patch\n", |
|
165 # FIXME: The commit-queue warns about bad committers twice. This is due to the fact that we access Attachment.reviewer() twice and it logs each time. |
|
166 "next_work_item": """Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) |
|
167 Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com) |
|
168 MOCK setting flag 'commit-queue' to '-' on attachment '128' with comment 'Rejecting patch 128 from commit-queue.' and additional comment 'non-committer@example.com does not have committer permissions according to http://trac.webkit.org/browser/trunk/WebKitTools/Scripts/webkitpy/common/config/committers.py. |
|
169 |
|
170 - If you do not have committer rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags. |
|
171 |
|
172 - If you have committer rights please correct the error in WebKitTools/Scripts/webkitpy/common/config/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@chromium.org to request a commit-queue restart. After restart the commit-queue will correctly respect your committer rights.' |
|
173 MOCK: update_work_items: commit-queue [106, 197] |
|
174 2 patches in commit-queue [106, 197] |
|
175 """, |
|
176 "process_work_item": "MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'land-attachment', '--force-clean', '--build', '--non-interactive', '--ignore-builders', '--build-style=both', '--quiet', 76543]\nMOCK: update_status: commit-queue Pass\n", |
|
177 "handle_unexpected_error": "MOCK setting flag 'commit-queue' to '-' on attachment '76543' with comment 'Rejecting patch 76543 from commit-queue.' and additional comment 'Mock error message'\n", |
|
178 "handle_script_error": "MOCK: update_status: commit-queue ScriptError error message\nMOCK setting flag 'commit-queue' to '-' on attachment '1234' with comment 'Rejecting patch 1234 from commit-queue.' and additional comment 'ScriptError error message'\n", |
|
179 } |
|
180 self.assert_queue_outputs(CommitQueue(), tool=tool, work_item=rollout_patch, expected_stderr=expected_stderr) |
|
181 |
|
182 def test_can_build_and_test(self): |
|
183 queue = CommitQueue() |
|
184 tool = MockTool() |
|
185 tool.executive = Mock() |
|
186 queue.bind_to_tool(tool) |
|
187 self.assertTrue(queue._can_build_and_test()) |
|
188 expected_run_args = ["echo", "--status-host=example.com", "build-and-test", "--force-clean", "--build", "--test", "--non-interactive", "--no-update", "--build-style=both", "--quiet"] |
|
189 tool.executive.run_and_throw_if_fail.assert_called_with(expected_run_args) |
|
190 |
|
191 def _mock_attachment(self, is_rollout, attach_date): |
|
192 attachment = Mock() |
|
193 attachment.is_rollout = lambda: is_rollout |
|
194 attachment.attach_date = lambda: attach_date |
|
195 return attachment |
|
196 |
|
197 def test_patch_cmp(self): |
|
198 long_ago_date = datetime(1900, 1, 21) |
|
199 recent_date = datetime(2010, 1, 21) |
|
200 attachment1 = self._mock_attachment(is_rollout=False, attach_date=recent_date) |
|
201 attachment2 = self._mock_attachment(is_rollout=False, attach_date=long_ago_date) |
|
202 attachment3 = self._mock_attachment(is_rollout=True, attach_date=recent_date) |
|
203 attachment4 = self._mock_attachment(is_rollout=True, attach_date=long_ago_date) |
|
204 attachments = [attachment1, attachment2, attachment3, attachment4] |
|
205 expected_sort = [attachment4, attachment3, attachment2, attachment1] |
|
206 queue = CommitQueue() |
|
207 attachments.sort(queue._patch_cmp) |
|
208 self.assertEqual(attachments, expected_sort) |
|
209 |
|
210 |
|
211 class RietveldUploadQueueTest(QueuesTest): |
|
212 def test_rietveld_upload_queue(self): |
|
213 expected_stderr = { |
|
214 "begin_work_queue": "CAUTION: rietveld-upload-queue will discard all local changes in \"%s\"\nRunning WebKit rietveld-upload-queue.\n" % MockSCM.fake_checkout_root, |
|
215 "should_proceed_with_work_item": "MOCK: update_status: rietveld-upload-queue Uploading patch\n", |
|
216 "process_work_item": "MOCK: update_status: rietveld-upload-queue Pass\n", |
|
217 "handle_unexpected_error": "Mock error message\nMOCK setting flag 'in-rietveld' to '-' on attachment '1234' with comment 'None' and additional comment 'None'\n", |
|
218 "handle_script_error": "ScriptError error message\nMOCK: update_status: rietveld-upload-queue ScriptError error message\nMOCK setting flag 'in-rietveld' to '-' on attachment '1234' with comment 'None' and additional comment 'None'\n", |
|
219 } |
|
220 self.assert_queue_outputs(RietveldUploadQueue(), expected_stderr=expected_stderr) |
|
221 |
|
222 |
|
223 class StyleQueueTest(QueuesTest): |
|
224 def test_style_queue(self): |
|
225 expected_stderr = { |
|
226 "begin_work_queue" : "CAUTION: style-queue will discard all local changes in \"%s\"\nRunning WebKit style-queue.\n" % MockSCM.fake_checkout_root, |
|
227 "next_work_item": "MOCK: update_work_items: style-queue [103]\n", |
|
228 "should_proceed_with_work_item": "MOCK: update_status: style-queue Checking style\n", |
|
229 "process_work_item" : "MOCK: update_status: style-queue Pass\n", |
|
230 "handle_unexpected_error" : "Mock error message\n", |
|
231 "handle_script_error": "MOCK: update_status: style-queue ScriptError error message\nMOCK bug comment: bug_id=345, cc=[]\n--- Begin comment ---\\Attachment 1234 did not pass style-queue:\n\nScriptError error message\n\nIf any of these errors are false positives, please file a bug against check-webkit-style.\n--- End comment ---\n\n", |
|
232 } |
|
233 expected_exceptions = { |
|
234 "handle_script_error": SystemExit, |
|
235 } |
|
236 self.assert_queue_outputs(StyleQueue(), expected_stderr=expected_stderr, expected_exceptions=expected_exceptions) |