Remove use of deprecated logging from webkitpy.common and webkitpy.layout_tests
[WebKit-https.git] / Tools / Scripts / webkitpy / tool / commands / queues_unittest.py
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 import StringIO
31
32 from webkitpy.common.checkout.scm import CheckoutNeedsUpdate
33 from webkitpy.common.checkout.scm.scm_mock import MockSCM
34 from webkitpy.common.net.bugzilla import Attachment
35 from webkitpy.common.system.outputcapture import OutputCapture
36 from webkitpy.layout_tests.models import test_results
37 from webkitpy.layout_tests.models import test_failures
38 from webkitpy.thirdparty.mock import Mock
39 from webkitpy.tool.commands.commandtest import CommandsTest
40 from webkitpy.tool.commands.queues import *
41 from webkitpy.tool.commands.queuestest import QueuesTest
42 from webkitpy.tool.commands.stepsequence import StepSequence
43 from webkitpy.common.net.statusserver_mock import MockStatusServer
44 from webkitpy.tool.mocktool import MockTool, MockOptions
45
46
47 class TestCommitQueue(CommitQueue):
48     def __init__(self, tool=None):
49         CommitQueue.__init__(self)
50         if tool:
51             self.bind_to_tool(tool)
52         self._options = MockOptions(confirm=False, parent_command="commit-queue", port=None)
53
54     def begin_work_queue(self):
55         output_capture = OutputCapture()
56         output_capture.capture_output()
57         CommitQueue.begin_work_queue(self)
58         output_capture.restore_output()
59
60
61 class TestQueue(AbstractPatchQueue):
62     name = "test-queue"
63
64
65 class TestReviewQueue(AbstractReviewQueue):
66     name = "test-review-queue"
67
68
69 class TestFeederQueue(FeederQueue):
70     _sleep_duration = 0
71
72
73 class AbstractQueueTest(CommandsTest):
74     def test_log_directory(self):
75         self.assertEqual(TestQueue()._log_directory(), os.path.join("..", "test-queue-logs"))
76
77     def _assert_run_webkit_patch(self, run_args, port=None):
78         queue = TestQueue()
79         tool = MockTool()
80         tool.status_server.bot_id = "gort"
81         tool.executive = Mock()
82         queue.bind_to_tool(tool)
83         queue._options = Mock()
84         queue._options.port = port
85
86         queue.run_webkit_patch(run_args)
87         expected_run_args = ["echo", "--status-host=example.com", "--bot-id=gort"]
88         if port:
89             expected_run_args.append("--port=%s" % port)
90         expected_run_args.extend(run_args)
91         tool.executive.run_and_throw_if_fail.assert_called_with(expected_run_args, cwd='/mock-checkout')
92
93     def test_run_webkit_patch(self):
94         self._assert_run_webkit_patch([1])
95         self._assert_run_webkit_patch(["one", 2])
96         self._assert_run_webkit_patch([1], port="mockport")
97
98     def test_iteration_count(self):
99         queue = TestQueue()
100         queue._options = Mock()
101         queue._options.iterations = 3
102         self.assertTrue(queue.should_continue_work_queue())
103         self.assertTrue(queue.should_continue_work_queue())
104         self.assertTrue(queue.should_continue_work_queue())
105         self.assertFalse(queue.should_continue_work_queue())
106
107     def test_no_iteration_count(self):
108         queue = TestQueue()
109         queue._options = Mock()
110         self.assertTrue(queue.should_continue_work_queue())
111         self.assertTrue(queue.should_continue_work_queue())
112         self.assertTrue(queue.should_continue_work_queue())
113         self.assertTrue(queue.should_continue_work_queue())
114
115     def _assert_log_message(self, script_error, log_message):
116         failure_log = AbstractQueue._log_from_script_error_for_upload(script_error, output_limit=10)
117         self.assertTrue(failure_log.read(), log_message)
118
119     def test_log_from_script_error_for_upload(self):
120         self._assert_log_message(ScriptError("test"), "test")
121         unicode_tor = u"WebKit \u2661 Tor Arne Vestb\u00F8!"
122         utf8_tor = unicode_tor.encode("utf-8")
123         self._assert_log_message(ScriptError(unicode_tor), utf8_tor)
124         script_error = ScriptError(unicode_tor, output=unicode_tor)
125         expected_output = "%s\nLast %s characters of output:\n%s" % (utf8_tor, 10, utf8_tor[-10:])
126         self._assert_log_message(script_error, expected_output)
127
128
129 class FeederQueueTest(QueuesTest):
130     def test_feeder_queue(self):
131         queue = TestFeederQueue()
132         tool = MockTool(log_executive=True)
133         expected_logs = {
134             "begin_work_queue": self._default_begin_work_queue_logs("feeder-queue"),
135             "process_work_item": """Warning, attachment 10001 on bug 50000 has invalid committer (non-committer@example.com)
136 Warning, attachment 10001 on bug 50000 has invalid committer (non-committer@example.com)
137 MOCK setting flag 'commit-queue' to '-' on attachment '10001' with comment 'Rejecting attachment 10001 from commit-queue.' and additional comment 'non-committer@example.com does not have committer permissions according to http://trac.webkit.org/browser/trunk/Tools/Scripts/webkitpy/common/config/committers.py.
138
139 - If you do not have committer rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags.
140
141 - If you have committer rights please correct the error in Tools/Scripts/webkitpy/common/config/committers.py by adding yourself to the file (no review needed).  The commit-queue restarts itself every 2 hours.  After restart the commit-queue will correctly respect your committer rights.'
142 MOCK: update_work_items: commit-queue [10005, 10000]
143 Feeding commit-queue items [10005, 10000]
144 Feeding EWS (1 r? patch, 1 new)
145 MOCK: submit_to_ews: 10002
146 """,
147             "handle_unexpected_error": "Mock error message\n",
148         }
149         self.assert_queue_outputs(queue, tool=tool, expected_logs=expected_logs)
150
151
152 class AbstractPatchQueueTest(CommandsTest):
153     def test_next_patch(self):
154         queue = AbstractPatchQueue()
155         tool = MockTool()
156         queue.bind_to_tool(tool)
157         queue._options = Mock()
158         queue._options.port = None
159         self.assertEqual(queue._next_patch(), None)
160         tool.status_server = MockStatusServer(work_items=[2, 10000, 10001])
161         expected_stdout = "MOCK: fetch_attachment: 2 is not a known attachment id\n"  # A mock-only message to prevent us from making mistakes.
162         expected_logs = "MOCK: release_work_item: None 2\n"
163         patch = OutputCapture().assert_outputs(self, queue._next_patch, expected_stdout=expected_stdout, expected_logs=expected_logs)
164         # The patch.id() == 2 is ignored because it doesn't exist.
165         self.assertEqual(patch.id(), 10000)
166         self.assertEqual(queue._next_patch().id(), 10001)
167         self.assertEqual(queue._next_patch(), None)    # When the queue is empty
168
169     def test_upload_results_archive_for_patch(self):
170         queue = AbstractPatchQueue()
171         queue.name = "mock-queue"
172         tool = MockTool()
173         queue.bind_to_tool(tool)
174         queue._options = Mock()
175         queue._options.port = None
176         patch = queue._tool.bugs.fetch_attachment(10001)
177         expected_logs = """MOCK add_attachment_to_bug: bug_id=50000, description=Archive of layout-test-results from bot filename=layout-test-results.zip mimetype=None
178 -- Begin comment --
179 The attached test failures were seen while running run-webkit-tests on the mock-queue.
180 Port: MockPort  Platform: MockPlatform 1.0
181 -- End comment --
182 """
183         OutputCapture().assert_outputs(self, queue._upload_results_archive_for_patch, [patch, Mock()], expected_logs=expected_logs)
184
185
186 class NeedsUpdateSequence(StepSequence):
187     def _run(self, tool, options, state):
188         raise CheckoutNeedsUpdate([], 1, "", None)
189
190
191 class AlwaysCommitQueueTool(object):
192     def __init__(self):
193         self.status_server = MockStatusServer()
194
195     def command_by_name(self, name):
196         return CommitQueue
197
198
199 class SecondThoughtsCommitQueue(TestCommitQueue):
200     def __init__(self, tool=None):
201         self._reject_patch = False
202         TestCommitQueue.__init__(self, tool)
203
204     def run_command(self, command):
205         # We want to reject the patch after the first validation,
206         # so wait to reject it until after some other command has run.
207         self._reject_patch = True
208         return CommitQueue.run_command(self, command)
209
210     def refetch_patch(self, patch):
211         if not self._reject_patch:
212             return self._tool.bugs.fetch_attachment(patch.id())
213
214         attachment_dictionary = {
215             "id": patch.id(),
216             "bug_id": patch.bug_id(),
217             "name": "Rejected",
218             "is_obsolete": True,
219             "is_patch": False,
220             "review": "-",
221             "reviewer_email": "foo@bar.com",
222             "commit-queue": "-",
223             "committer_email": "foo@bar.com",
224             "attacher_email": "Contributer1",
225         }
226         return Attachment(attachment_dictionary, None)
227
228
229 class CommitQueueTest(QueuesTest):
230     def _mock_test_result(self, testname):
231         return test_results.TestResult(testname, [test_failures.FailureTextMismatch()])
232
233     def test_commit_queue(self):
234         tool = MockTool()
235         tool.filesystem.write_text_file('/tmp/layout-test-results/full_results.json', '')  # Otherwise the commit-queue will hit a KeyError trying to read the results from the MockFileSystem.
236         tool.filesystem.write_text_file('/tmp/layout-test-results/webkit_unit_tests_output.xml', '')
237         expected_logs = {
238             "begin_work_queue": self._default_begin_work_queue_logs("commit-queue"),
239             "process_work_item": """MOCK: update_status: commit-queue Cleaned working directory
240 MOCK: update_status: commit-queue Updated working directory
241 MOCK: update_status: commit-queue Applied patch
242 MOCK: update_status: commit-queue ChangeLog validated
243 MOCK: update_status: commit-queue Built patch
244 MOCK: update_status: commit-queue Passed tests
245 MOCK: update_status: commit-queue Landed patch
246 MOCK: update_status: commit-queue Pass
247 MOCK: release_work_item: commit-queue 10000
248 """,
249             "handle_script_error": "ScriptError error message\n\nMOCK output\n",
250             "handle_unexpected_error": "MOCK setting flag 'commit-queue' to '-' on attachment '10000' with comment 'Rejecting attachment 10000 from commit-queue.' and additional comment 'Mock error message'\n",
251         }
252         self.assert_queue_outputs(CommitQueue(), tool=tool, expected_logs=expected_logs)
253
254     def test_commit_queue_failure(self):
255         expected_logs = {
256             "begin_work_queue": self._default_begin_work_queue_logs("commit-queue"),
257             "process_work_item": """MOCK: update_status: commit-queue Cleaned working directory
258 MOCK: update_status: commit-queue Updated working directory
259 MOCK: update_status: commit-queue Patch does not apply
260 MOCK setting flag 'commit-queue' to '-' on attachment '10000' with comment 'Rejecting attachment 10000 from commit-queue.' and additional comment 'MOCK script error
261 Full output: http://dummy_url'
262 MOCK: update_status: commit-queue Fail
263 MOCK: release_work_item: commit-queue 10000
264 """,
265             "handle_script_error": "ScriptError error message\n\nMOCK output\n",
266             "handle_unexpected_error": "MOCK setting flag 'commit-queue' to '-' on attachment '10000' with comment 'Rejecting attachment 10000 from commit-queue.' and additional comment 'Mock error message'\n",
267         }
268         queue = CommitQueue()
269
270         def mock_run_webkit_patch(command):
271             if command[0] == 'clean' or command[0] == 'update':
272                 # We want cleaning to succeed so we can error out on a step
273                 # that causes the commit-queue to reject the patch.
274                 return
275             raise ScriptError('MOCK script error')
276
277         queue.run_webkit_patch = mock_run_webkit_patch
278         self.assert_queue_outputs(queue, expected_logs=expected_logs)
279
280     def test_commit_queue_failure_with_failing_tests(self):
281         expected_logs = {
282             "begin_work_queue": self._default_begin_work_queue_logs("commit-queue"),
283             "process_work_item": """MOCK: update_status: commit-queue Cleaned working directory
284 MOCK: update_status: commit-queue Updated working directory
285 MOCK: update_status: commit-queue Patch does not apply
286 MOCK setting flag 'commit-queue' to '-' on attachment '10000' with comment 'Rejecting attachment 10000 from commit-queue.' and additional comment 'New failing tests:
287 mock_test_name.html
288 another_test_name.html
289 Full output: http://dummy_url'
290 MOCK: update_status: commit-queue Fail
291 MOCK: release_work_item: commit-queue 10000
292 """,
293             "handle_script_error": "ScriptError error message\n\nMOCK output\n",
294             "handle_unexpected_error": "MOCK setting flag 'commit-queue' to '-' on attachment '10000' with comment 'Rejecting attachment 10000 from commit-queue.' and additional comment 'Mock error message'\n",
295         }
296         queue = CommitQueue()
297
298         def mock_run_webkit_patch(command):
299             if command[0] == 'clean' or command[0] == 'update':
300                 # We want cleaning to succeed so we can error out on a step
301                 # that causes the commit-queue to reject the patch.
302                 return
303             queue._expected_failures.unexpected_failures_observed = lambda results: ["mock_test_name.html", "another_test_name.html"]
304             raise ScriptError('MOCK script error')
305
306         queue.run_webkit_patch = mock_run_webkit_patch
307         self.assert_queue_outputs(queue, expected_logs=expected_logs)
308
309     def test_rollout(self):
310         tool = MockTool(log_executive=True)
311         tool.filesystem.write_text_file('/tmp/layout-test-results/full_results.json', '')  # Otherwise the commit-queue will hit a KeyError trying to read the results from the MockFileSystem.
312         tool.filesystem.write_text_file('/tmp/layout-test-results/webkit_unit_tests_output.xml', '')
313         tool.buildbot.light_tree_on_fire()
314         expected_logs = {
315             "begin_work_queue": self._default_begin_work_queue_logs("commit-queue"),
316             "process_work_item": """MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'clean', '--port=%(port_name)s'], cwd=/mock-checkout
317 MOCK: update_status: commit-queue Cleaned working directory
318 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'update', '--port=%(port_name)s'], cwd=/mock-checkout
319 MOCK: update_status: commit-queue Updated working directory
320 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'apply-attachment', '--no-update', '--non-interactive', 10000, '--port=%(port_name)s'], cwd=/mock-checkout
321 MOCK: update_status: commit-queue Applied patch
322 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'validate-changelog', '--non-interactive', 10000, '--port=%(port_name)s'], cwd=/mock-checkout
323 MOCK: update_status: commit-queue ChangeLog validated
324 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'build', '--no-clean', '--no-update', '--build-style=release', '--port=%(port_name)s'], cwd=/mock-checkout
325 MOCK: update_status: commit-queue Built patch
326 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive', '--port=%(port_name)s'], cwd=/mock-checkout
327 MOCK: update_status: commit-queue Passed tests
328 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'land-attachment', '--force-clean', '--non-interactive', '--parent-command=commit-queue', 10000, '--port=%(port_name)s'], cwd=/mock-checkout
329 MOCK: update_status: commit-queue Landed patch
330 MOCK: update_status: commit-queue Pass
331 MOCK: release_work_item: commit-queue 10000
332 """ % {"port_name": CommitQueue.port_name},
333             "handle_script_error": "ScriptError error message\n\nMOCK output\n",
334             "handle_unexpected_error": "MOCK setting flag 'commit-queue' to '-' on attachment '10000' with comment 'Rejecting attachment 10000 from commit-queue.' and additional comment 'Mock error message'\n",
335         }
336         self.assert_queue_outputs(CommitQueue(), tool=tool, expected_logs=expected_logs)
337
338     def test_rollout_lands(self):
339         tool = MockTool(log_executive=True)
340         tool.buildbot.light_tree_on_fire()
341         rollout_patch = tool.bugs.fetch_attachment(10005)  # _patch6, a rollout patch.
342         assert(rollout_patch.is_rollout())
343         expected_logs = {
344             "begin_work_queue": self._default_begin_work_queue_logs("commit-queue"),
345             "process_work_item": """MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'clean', '--port=%(port_name)s'], cwd=/mock-checkout
346 MOCK: update_status: commit-queue Cleaned working directory
347 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'update', '--port=%(port_name)s'], cwd=/mock-checkout
348 MOCK: update_status: commit-queue Updated working directory
349 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'apply-attachment', '--no-update', '--non-interactive', 10005, '--port=%(port_name)s'], cwd=/mock-checkout
350 MOCK: update_status: commit-queue Applied patch
351 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'validate-changelog', '--non-interactive', 10005, '--port=%(port_name)s'], cwd=/mock-checkout
352 MOCK: update_status: commit-queue ChangeLog validated
353 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'land-attachment', '--force-clean', '--non-interactive', '--parent-command=commit-queue', 10005, '--port=%(port_name)s'], cwd=/mock-checkout
354 MOCK: update_status: commit-queue Landed patch
355 MOCK: update_status: commit-queue Pass
356 MOCK: release_work_item: commit-queue 10005
357 """ % {"port_name": CommitQueue.port_name},
358             "handle_script_error": "ScriptError error message\n\nMOCK output\n",
359             "handle_unexpected_error": "MOCK setting flag 'commit-queue' to '-' on attachment '10005' with comment 'Rejecting attachment 10005 from commit-queue.' and additional comment 'Mock error message'\n",
360         }
361         self.assert_queue_outputs(CommitQueue(), tool=tool, work_item=rollout_patch, expected_logs=expected_logs)
362
363     def test_auto_retry(self):
364         queue = CommitQueue()
365         options = Mock()
366         options.parent_command = "commit-queue"
367         tool = AlwaysCommitQueueTool()
368         sequence = NeedsUpdateSequence(None)
369
370         expected_logs = """Commit failed because the checkout is out of date. Please update and try again.
371 MOCK: update_status: commit-queue Tests passed, but commit failed (checkout out of date).  Updating, then landing without building or re-running tests.
372 """
373         state = {'patch': None}
374         OutputCapture().assert_outputs(self, sequence.run_and_handle_errors, [tool, options, state], expected_exception=TryAgain, expected_logs=expected_logs)
375
376         self.assertEqual(options.update, True)
377         self.assertEqual(options.build, False)
378         self.assertEqual(options.test, False)
379
380     def test_manual_reject_during_processing(self):
381         queue = SecondThoughtsCommitQueue(MockTool())
382         queue.begin_work_queue()
383         queue._tool.filesystem.write_text_file('/tmp/layout-test-results/full_results.json', '')  # Otherwise the commit-queue will hit a KeyError trying to read the results from the MockFileSystem.
384         queue._tool.filesystem.write_text_file('/tmp/layout-test-results/webkit_unit_tests_output.xml', '')
385         queue._options = Mock()
386         queue._options.port = None
387         expected_logs = """MOCK: update_status: commit-queue Cleaned working directory
388 MOCK: update_status: commit-queue Updated working directory
389 MOCK: update_status: commit-queue Applied patch
390 MOCK: update_status: commit-queue ChangeLog validated
391 MOCK: update_status: commit-queue Built patch
392 MOCK: update_status: commit-queue Passed tests
393 MOCK: update_status: commit-queue Retry
394 MOCK: release_work_item: commit-queue 10000
395 """
396         OutputCapture().assert_outputs(self, queue.process_work_item, [QueuesTest.mock_work_item], expected_logs=expected_logs)
397
398     def test_report_flaky_tests(self):
399         queue = TestCommitQueue(MockTool())
400         expected_logs = """MOCK bug comment: bug_id=50002, cc=None
401 --- Begin comment ---
402 The commit-queue just saw foo/bar.html flake (text diff) while processing attachment 10000 on bug 50000.
403 Port: MockPort  Platform: MockPlatform 1.0
404 --- End comment ---
405
406 MOCK add_attachment_to_bug: bug_id=50002, description=Failure diff from bot filename=failure.diff mimetype=None
407 MOCK bug comment: bug_id=50002, cc=None
408 --- Begin comment ---
409 The commit-queue just saw bar/baz.html flake (text diff) while processing attachment 10000 on bug 50000.
410 Port: MockPort  Platform: MockPlatform 1.0
411 --- End comment ---
412
413 bar/baz-diffs.txt does not exist in results archive, uploading entire archive.
414 MOCK add_attachment_to_bug: bug_id=50002, description=Archive of layout-test-results from bot filename=layout-test-results.zip mimetype=None
415 MOCK bug comment: bug_id=50000, cc=None
416 --- Begin comment ---
417 The commit-queue encountered the following flaky tests while processing attachment 10000:
418
419 foo/bar.html bug 50002 (author: abarth@webkit.org)
420 bar/baz.html bug 50002 (author: abarth@webkit.org)
421 The commit-queue is continuing to process your patch.
422 --- End comment ---
423
424 """
425         test_names = ["foo/bar.html", "bar/baz.html"]
426         test_results = [self._mock_test_result(name) for name in test_names]
427
428         class MockZipFile(object):
429             def __init__(self):
430                 self.fp = StringIO()
431
432             def read(self, path):
433                 return ""
434
435             def namelist(self):
436                 # This is intentionally missing one diffs.txt to exercise the "upload the whole zip" codepath.
437                 return ['foo/bar-diffs.txt']
438
439         OutputCapture().assert_outputs(self, queue.report_flaky_tests, [QueuesTest.mock_work_item, test_results, MockZipFile()], expected_logs=expected_logs)
440
441     def test_did_pass_testing_ews(self):
442         tool = MockTool()
443         patch = tool.bugs.fetch_attachment(10000)
444         queue = TestCommitQueue(tool)
445         self.assertFalse(queue.did_pass_testing_ews(patch))
446
447
448 class StyleQueueTest(QueuesTest):
449     def test_style_queue_with_style_exception(self):
450         expected_logs = {
451             "begin_work_queue": self._default_begin_work_queue_logs("style-queue"),
452             "process_work_item": """MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'clean'], cwd=/mock-checkout
453 MOCK: update_status: style-queue Cleaned working directory
454 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'update'], cwd=/mock-checkout
455 MOCK: update_status: style-queue Updated working directory
456 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'apply-attachment', '--no-update', '--non-interactive', 10000], cwd=/mock-checkout
457 MOCK: update_status: style-queue Applied patch
458 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'apply-watchlist-local', 50000], cwd=/mock-checkout
459 MOCK: update_status: style-queue Watchlist applied
460 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'check-style-local', '--non-interactive', '--quiet'], cwd=/mock-checkout
461 MOCK: update_status: style-queue Style checked
462 MOCK: update_status: style-queue Pass
463 MOCK: release_work_item: style-queue 10000
464 """,
465             "handle_unexpected_error": "Mock error message\n",
466             "handle_script_error": "MOCK output\n",
467         }
468         tool = MockTool(log_executive=True, executive_throws_when_run=set(['check-style']))
469         self.assert_queue_outputs(StyleQueue(), expected_logs=expected_logs, tool=tool)
470
471     def test_style_queue_with_watch_list_exception(self):
472         expected_logs = {
473             "begin_work_queue": self._default_begin_work_queue_logs("style-queue"),
474             "process_work_item": """MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'clean'], cwd=/mock-checkout
475 MOCK: update_status: style-queue Cleaned working directory
476 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'update'], cwd=/mock-checkout
477 MOCK: update_status: style-queue Updated working directory
478 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'apply-attachment', '--no-update', '--non-interactive', 10000], cwd=/mock-checkout
479 MOCK: update_status: style-queue Applied patch
480 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'apply-watchlist-local', 50000], cwd=/mock-checkout
481 MOCK: update_status: style-queue Unabled to apply watchlist
482 MOCK run_and_throw_if_fail: ['echo', '--status-host=example.com', 'check-style-local', '--non-interactive', '--quiet'], cwd=/mock-checkout
483 MOCK: update_status: style-queue Style checked
484 MOCK: update_status: style-queue Pass
485 MOCK: release_work_item: style-queue 10000
486 """,
487             "handle_unexpected_error": "Mock error message\n",
488             "handle_script_error": "MOCK output\n",
489         }
490         tool = MockTool(log_executive=True, executive_throws_when_run=set(['apply-watchlist-local']))
491         self.assert_queue_outputs(StyleQueue(), expected_logs=expected_logs, tool=tool)