summaryrefslogtreecommitdiffstats
path: root/WebKitTools/Scripts/webkitpy/tool/bot
diff options
context:
space:
mode:
Diffstat (limited to 'WebKitTools/Scripts/webkitpy/tool/bot')
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/__init__.py1
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask.py196
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py204
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/feeders.py90
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/feeders_unittest.py70
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/irc_command.py109
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/irc_command_unittest.py38
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py165
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py209
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/sheriff.py91
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py90
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/sheriffircbot.py83
-rw-r--r--WebKitTools/Scripts/webkitpy/tool/bot/sheriffircbot_unittest.py95
13 files changed, 0 insertions, 1441 deletions
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/__init__.py b/WebKitTools/Scripts/webkitpy/tool/bot/__init__.py
deleted file mode 100644
index ef65bee..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-# Required for Python to search this directory for module files
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask.py b/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask.py
deleted file mode 100644
index ea12702..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask.py
+++ /dev/null
@@ -1,196 +0,0 @@
-# Copyright (c) 2010 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.
-
-from webkitpy.common.system.executive import ScriptError
-from webkitpy.common.net.layouttestresults import LayoutTestResults
-
-
-class CommitQueueTaskDelegate(object):
- def run_command(self, command):
- raise NotImplementedError("subclasses must implement")
-
- def command_passed(self, message, patch):
- raise NotImplementedError("subclasses must implement")
-
- def command_failed(self, message, script_error, patch):
- raise NotImplementedError("subclasses must implement")
-
- def refetch_patch(self, patch):
- raise NotImplementedError("subclasses must implement")
-
- def layout_test_results(self):
- raise NotImplementedError("subclasses must implement")
-
- def report_flaky_tests(self, patch, flaky_tests):
- raise NotImplementedError("subclasses must implement")
-
-
-class CommitQueueTask(object):
- def __init__(self, delegate, patch):
- self._delegate = delegate
- self._patch = patch
- self._script_error = None
-
- def _validate(self):
- # Bugs might get closed, or patches might be obsoleted or r-'d while the
- # commit-queue is processing.
- self._patch = self._delegate.refetch_patch(self._patch)
- if self._patch.is_obsolete():
- return False
- if self._patch.bug().is_closed():
- return False
- if not self._patch.committer():
- return False
- # Reviewer is not required. Missing reviewers will be caught during
- # the ChangeLog check during landing.
- return True
-
- def _run_command(self, command, success_message, failure_message):
- try:
- self._delegate.run_command(command)
- self._delegate.command_passed(success_message, patch=self._patch)
- return True
- except ScriptError, e:
- self._script_error = e
- self.failure_status_id = self._delegate.command_failed(failure_message, script_error=self._script_error, patch=self._patch)
- return False
-
- def _apply(self):
- return self._run_command([
- "apply-attachment",
- "--force-clean",
- "--non-interactive",
- self._patch.id(),
- ],
- "Applied patch",
- "Patch does not apply")
-
- def _build(self):
- return self._run_command([
- "build",
- "--no-clean",
- "--no-update",
- "--build-style=both",
- ],
- "Built patch",
- "Patch does not build")
-
- def _build_without_patch(self):
- return self._run_command([
- "build",
- "--force-clean",
- "--no-update",
- "--build-style=both",
- ],
- "Able to build without patch",
- "Unable to build without patch")
-
- def _test(self):
- return self._run_command([
- "build-and-test",
- "--no-clean",
- "--no-update",
- # Notice that we don't pass --build, which means we won't build!
- "--test",
- "--non-interactive",
- ],
- "Passed tests",
- "Patch does not pass tests")
-
- def _build_and_test_without_patch(self):
- return self._run_command([
- "build-and-test",
- "--force-clean",
- "--no-update",
- "--build",
- "--test",
- "--non-interactive",
- ],
- "Able to pass tests without patch",
- "Unable to pass tests without patch (tree is red?)")
-
- def _failing_tests_from_last_run(self):
- results = self._delegate.layout_test_results()
- if not results:
- return None
- return results.failing_tests()
-
- def _land(self):
- # Unclear if this should pass --quiet or not. If --parent-command always does the reporting, then it should.
- return self._run_command([
- "land-attachment",
- "--force-clean",
- "--ignore-builders",
- "--non-interactive",
- "--parent-command=commit-queue",
- self._patch.id(),
- ],
- "Landed patch",
- "Unable to land patch")
-
- def _report_flaky_tests(self, flaky_tests):
- self._delegate.report_flaky_tests(self._patch, flaky_tests)
-
- def _test_patch(self):
- if self._patch.is_rollout():
- return True
- if self._test():
- return True
-
- first_failing_tests = self._failing_tests_from_last_run()
- if self._test():
- self._report_flaky_tests(first_failing_tests)
- return True
-
- second_failing_tests = self._failing_tests_from_last_run()
- if first_failing_tests != second_failing_tests:
- self._report_flaky_tests(first_failing_tests + second_failing_tests)
- return False
-
- if self._build_and_test_without_patch():
- raise self._script_error # The error from the previous ._test() run is real, report it.
- return False # Tree must be red, just retry later.
-
- def run(self):
- if not self._validate():
- return False
- if not self._apply():
- raise self._script_error
- if not self._build():
- if not self._build_without_patch():
- return False
- raise self._script_error
- if not self._test_patch():
- return False
- # Make sure the patch is still valid before landing (e.g., make sure
- # no one has set commit-queue- since we started working on the patch.)
- if not self._validate():
- return False
- if not self._land():
- raise self._script_error
- return True
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py
deleted file mode 100644
index 15a4a6b..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py
+++ /dev/null
@@ -1,204 +0,0 @@
-# Copyright (c) 2010 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.
-
-from datetime import datetime
-import unittest
-
-from webkitpy.common.system.deprecated_logging import error, log
-from webkitpy.common.system.outputcapture import OutputCapture
-from webkitpy.thirdparty.mock import Mock
-from webkitpy.tool.bot.commitqueuetask import *
-from webkitpy.tool.mocktool import MockTool
-
-
-class MockCommitQueue(CommitQueueTaskDelegate):
- def __init__(self, error_plan):
- self._error_plan = error_plan
-
- def run_command(self, command):
- log("run_webkit_patch: %s" % command)
- if self._error_plan:
- error = self._error_plan.pop(0)
- if error:
- raise error
-
- def command_passed(self, success_message, patch):
- log("command_passed: success_message='%s' patch='%s'" % (
- success_message, patch.id()))
-
- def command_failed(self, failure_message, script_error, patch):
- log("command_failed: failure_message='%s' script_error='%s' patch='%s'" % (
- failure_message, script_error, patch.id()))
- return 3947
-
- def refetch_patch(self, patch):
- return patch
-
- def layout_test_results(self):
- return None
-
- def report_flaky_tests(self, patch, flaky_tests):
- log("report_flaky_tests: patch='%s' flaky_tests='%s'" % (patch.id(), flaky_tests))
-
-
-class CommitQueueTaskTest(unittest.TestCase):
- def _run_through_task(self, commit_queue, expected_stderr, expected_exception=None):
- tool = MockTool(log_executive=True)
- patch = tool.bugs.fetch_attachment(197)
- task = CommitQueueTask(commit_queue, patch)
- OutputCapture().assert_outputs(self, task.run, expected_stderr=expected_stderr, expected_exception=expected_exception)
-
- def test_success_case(self):
- commit_queue = MockCommitQueue([])
- expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', 197]
-command_passed: success_message='Applied patch' patch='197'
-run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']
-command_passed: success_message='Built patch' patch='197'
-run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']
-command_passed: success_message='Passed tests' patch='197'
-run_webkit_patch: ['land-attachment', '--force-clean', '--ignore-builders', '--non-interactive', '--parent-command=commit-queue', 197]
-command_passed: success_message='Landed patch' patch='197'
-"""
- self._run_through_task(commit_queue, expected_stderr)
-
- def test_apply_failure(self):
- commit_queue = MockCommitQueue([
- ScriptError("MOCK apply failure"),
- ])
- expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', 197]
-command_failed: failure_message='Patch does not apply' script_error='MOCK apply failure' patch='197'
-"""
- self._run_through_task(commit_queue, expected_stderr, ScriptError)
-
- def test_build_failure(self):
- commit_queue = MockCommitQueue([
- None,
- ScriptError("MOCK build failure"),
- ])
- expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', 197]
-command_passed: success_message='Applied patch' patch='197'
-run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']
-command_failed: failure_message='Patch does not build' script_error='MOCK build failure' patch='197'
-run_webkit_patch: ['build', '--force-clean', '--no-update', '--build-style=both']
-command_passed: success_message='Able to build without patch' patch='197'
-"""
- self._run_through_task(commit_queue, expected_stderr, ScriptError)
-
- def test_red_build_failure(self):
- commit_queue = MockCommitQueue([
- None,
- ScriptError("MOCK build failure"),
- ScriptError("MOCK clean build failure"),
- ])
- expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', 197]
-command_passed: success_message='Applied patch' patch='197'
-run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']
-command_failed: failure_message='Patch does not build' script_error='MOCK build failure' patch='197'
-run_webkit_patch: ['build', '--force-clean', '--no-update', '--build-style=both']
-command_failed: failure_message='Unable to build without patch' script_error='MOCK clean build failure' patch='197'
-"""
- self._run_through_task(commit_queue, expected_stderr)
-
- def test_flaky_test_failure(self):
- commit_queue = MockCommitQueue([
- None,
- None,
- ScriptError("MOCK tests failure"),
- ])
- expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', 197]
-command_passed: success_message='Applied patch' patch='197'
-run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']
-command_passed: success_message='Built patch' patch='197'
-run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']
-command_failed: failure_message='Patch does not pass tests' script_error='MOCK tests failure' patch='197'
-run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']
-command_passed: success_message='Passed tests' patch='197'
-report_flaky_tests: patch='197' flaky_tests='None'
-run_webkit_patch: ['land-attachment', '--force-clean', '--ignore-builders', '--non-interactive', '--parent-command=commit-queue', 197]
-command_passed: success_message='Landed patch' patch='197'
-"""
- self._run_through_task(commit_queue, expected_stderr)
-
- def test_test_failure(self):
- commit_queue = MockCommitQueue([
- None,
- None,
- ScriptError("MOCK test failure"),
- ScriptError("MOCK test failure again"),
- ])
- expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', 197]
-command_passed: success_message='Applied patch' patch='197'
-run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']
-command_passed: success_message='Built patch' patch='197'
-run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']
-command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure' patch='197'
-run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']
-command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure again' patch='197'
-run_webkit_patch: ['build-and-test', '--force-clean', '--no-update', '--build', '--test', '--non-interactive']
-command_passed: success_message='Able to pass tests without patch' patch='197'
-"""
- self._run_through_task(commit_queue, expected_stderr, ScriptError)
-
- def test_red_test_failure(self):
- commit_queue = MockCommitQueue([
- None,
- None,
- ScriptError("MOCK test failure"),
- ScriptError("MOCK test failure again"),
- ScriptError("MOCK clean test failure"),
- ])
- expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', 197]
-command_passed: success_message='Applied patch' patch='197'
-run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']
-command_passed: success_message='Built patch' patch='197'
-run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']
-command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure' patch='197'
-run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']
-command_failed: failure_message='Patch does not pass tests' script_error='MOCK test failure again' patch='197'
-run_webkit_patch: ['build-and-test', '--force-clean', '--no-update', '--build', '--test', '--non-interactive']
-command_failed: failure_message='Unable to pass tests without patch (tree is red?)' script_error='MOCK clean test failure' patch='197'
-"""
- self._run_through_task(commit_queue, expected_stderr)
-
- def test_land_failure(self):
- commit_queue = MockCommitQueue([
- None,
- None,
- None,
- ScriptError("MOCK land failure"),
- ])
- expected_stderr = """run_webkit_patch: ['apply-attachment', '--force-clean', '--non-interactive', 197]
-command_passed: success_message='Applied patch' patch='197'
-run_webkit_patch: ['build', '--no-clean', '--no-update', '--build-style=both']
-command_passed: success_message='Built patch' patch='197'
-run_webkit_patch: ['build-and-test', '--no-clean', '--no-update', '--test', '--non-interactive']
-command_passed: success_message='Passed tests' patch='197'
-run_webkit_patch: ['land-attachment', '--force-clean', '--ignore-builders', '--non-interactive', '--parent-command=commit-queue', 197]
-command_failed: failure_message='Unable to land patch' script_error='MOCK land failure' patch='197'
-"""
- self._run_through_task(commit_queue, expected_stderr, ScriptError)
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py b/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py
deleted file mode 100644
index 046c4c1..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/feeders.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# Copyright (c) 2010 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.
-
-from webkitpy.common.config.committervalidator import CommitterValidator
-from webkitpy.common.system.deprecated_logging import log
-from webkitpy.tool.grammar import pluralize
-
-
-class AbstractFeeder(object):
- def __init__(self, tool):
- self._tool = tool
-
- def feed(self):
- raise NotImplementedError("subclasses must implement")
-
-
-class CommitQueueFeeder(AbstractFeeder):
- queue_name = "commit-queue"
-
- def __init__(self, tool):
- AbstractFeeder.__init__(self, tool)
- self.committer_validator = CommitterValidator(self._tool.bugs)
-
- def _update_work_items(self, item_ids):
- # FIXME: This is the last use of update_work_items, the commit-queue
- # should move to feeding patches one at a time like the EWS does.
- self._tool.status_server.update_work_items(self.queue_name, item_ids)
- log("Feeding %s items %s" % (self.queue_name, item_ids))
-
- def feed(self):
- patches = self._validate_patches()
- patches = sorted(patches, self._patch_cmp)
- patch_ids = [patch.id() for patch in patches]
- self._update_work_items(patch_ids)
-
- def _patches_for_bug(self, bug_id):
- return self._tool.bugs.fetch_bug(bug_id).commit_queued_patches(include_invalid=True)
-
- def _validate_patches(self):
- # Not using BugzillaQueries.fetch_patches_from_commit_queue() so we can reject patches with invalid committers/reviewers.
- bug_ids = self._tool.bugs.queries.fetch_bug_ids_from_commit_queue()
- all_patches = sum([self._patches_for_bug(bug_id) for bug_id in bug_ids], [])
- return self.committer_validator.patches_after_rejecting_invalid_commiters_and_reviewers(all_patches)
-
- def _patch_cmp(self, a, b):
- # Sort first by is_rollout, then by attach_date.
- # Reversing the order so that is_rollout is first.
- rollout_cmp = cmp(b.is_rollout(), a.is_rollout())
- if rollout_cmp != 0:
- return rollout_cmp
- return cmp(a.attach_date(), b.attach_date())
-
-
-class EWSFeeder(AbstractFeeder):
- def __init__(self, tool):
- self._ids_sent_to_server = set()
- AbstractFeeder.__init__(self, tool)
-
- def feed(self):
- ids_needing_review = set(self._tool.bugs.queries.fetch_attachment_ids_from_review_queue())
- new_ids = ids_needing_review.difference(self._ids_sent_to_server)
- log("Feeding EWS (%s, %s new)" % (pluralize("r? patch", len(ids_needing_review)), len(new_ids)))
- for attachment_id in new_ids: # Order doesn't really matter for the EWS.
- self._tool.status_server.submit_to_ews(attachment_id)
- self._ids_sent_to_server.add(attachment_id)
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/feeders_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/feeders_unittest.py
deleted file mode 100644
index 5ce00b4..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/feeders_unittest.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# Copyright (c) 2010 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.
-
-from datetime import datetime
-import unittest
-
-from webkitpy.common.system.outputcapture import OutputCapture
-from webkitpy.thirdparty.mock import Mock
-from webkitpy.tool.bot.feeders import *
-from webkitpy.tool.mocktool import MockTool
-
-
-class FeedersTest(unittest.TestCase):
- def test_commit_queue_feeder(self):
- feeder = CommitQueueFeeder(MockTool())
- expected_stderr = u"""Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com)
-Warning, attachment 128 on bug 42 has invalid committer (non-committer@example.com)
-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.
-
-- If you do not have committer rights please read http://webkit.org/coding/contributing.html for instructions on how to use bugzilla flags.
-
-- 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). The commit-queue restarts itself every 2 hours. After restart the commit-queue will correctly respect your committer rights.'
-MOCK: update_work_items: commit-queue [106, 197]
-Feeding commit-queue items [106, 197]
-"""
- OutputCapture().assert_outputs(self, feeder.feed, expected_stderr=expected_stderr)
-
- def _mock_attachment(self, is_rollout, attach_date):
- attachment = Mock()
- attachment.is_rollout = lambda: is_rollout
- attachment.attach_date = lambda: attach_date
- return attachment
-
- def test_patch_cmp(self):
- long_ago_date = datetime(1900, 1, 21)
- recent_date = datetime(2010, 1, 21)
- attachment1 = self._mock_attachment(is_rollout=False, attach_date=recent_date)
- attachment2 = self._mock_attachment(is_rollout=False, attach_date=long_ago_date)
- attachment3 = self._mock_attachment(is_rollout=True, attach_date=recent_date)
- attachment4 = self._mock_attachment(is_rollout=True, attach_date=long_ago_date)
- attachments = [attachment1, attachment2, attachment3, attachment4]
- expected_sort = [attachment4, attachment3, attachment2, attachment1]
- queue = CommitQueueFeeder(MockTool())
- attachments.sort(queue._patch_cmp)
- self.assertEqual(attachments, expected_sort)
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/irc_command.py b/WebKitTools/Scripts/webkitpy/tool/bot/irc_command.py
deleted file mode 100644
index a848472..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/irc_command.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# Copyright (c) 2010 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 random
-import webkitpy.common.config.irc as config_irc
-
-from webkitpy.common.checkout.changelog import view_source_url
-from webkitpy.tool.bot.queueengine import TerminateQueue
-from webkitpy.common.net.bugzilla import parse_bug_id
-from webkitpy.common.system.executive import ScriptError
-
-# FIXME: Merge with Command?
-class IRCCommand(object):
- def execute(self, nick, args, tool, sheriff):
- raise NotImplementedError, "subclasses must implement"
-
-
-class LastGreenRevision(IRCCommand):
- def execute(self, nick, args, tool, sheriff):
- return "%s: %s" % (nick,
- view_source_url(tool.buildbot.last_green_revision()))
-
-
-class Restart(IRCCommand):
- def execute(self, nick, args, tool, sheriff):
- tool.irc().post("Restarting...")
- raise TerminateQueue()
-
-
-class Rollout(IRCCommand):
- def execute(self, nick, args, tool, sheriff):
- if len(args) < 2:
- tool.irc().post("%s: Usage: SVN_REVISION REASON" % nick)
- return
- svn_revision = args[0].lstrip("r")
- rollout_reason = " ".join(args[1:])
- tool.irc().post("Preparing rollout for r%s..." % svn_revision)
- try:
- complete_reason = "%s (Requested by %s on %s)." % (
- rollout_reason, nick, config_irc.channel)
- bug_id = sheriff.post_rollout_patch(svn_revision, complete_reason)
- bug_url = tool.bugs.bug_url_for_bug_id(bug_id)
- tool.irc().post("%s: Created rollout: %s" % (nick, bug_url))
- except ScriptError, e:
- tool.irc().post("%s: Failed to create rollout patch:" % nick)
- tool.irc().post("%s" % e)
- bug_id = parse_bug_id(e.output)
- if bug_id:
- tool.irc().post("Ugg... Might have created %s" %
- tool.bugs.bug_url_for_bug_id(bug_id))
-
-
-class Help(IRCCommand):
- def execute(self, nick, args, tool, sheriff):
- return "%s: Available commands: %s" % (nick, ", ".join(commands.keys()))
-
-
-class Hi(IRCCommand):
- def execute(self, nick, args, tool, sheriff):
- quips = tool.bugs.quips()
- quips.append('"Only you can prevent forest fires." -- Smokey the Bear')
- return random.choice(quips)
-
-
-class Eliza(IRCCommand):
- therapist = None
-
- def __init__(self):
- if not self.therapist:
- import webkitpy.thirdparty.autoinstalled.eliza as eliza
- Eliza.therapist = eliza.eliza()
-
- def execute(self, nick, args, tool, sheriff):
- return "%s: %s" % (nick, self.therapist.respond(" ".join(args)))
-
-
-# FIXME: Lame. We should have an auto-registering CommandCenter.
-commands = {
- "last-green-revision": LastGreenRevision,
- "restart": Restart,
- "rollout": Rollout,
- "help": Help,
- "hi": Hi,
-}
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/irc_command_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/irc_command_unittest.py
deleted file mode 100644
index 7aeb6a0..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/irc_command_unittest.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (c) 2010 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 unittest
-
-from webkitpy.tool.bot.irc_command import *
-
-
-class IRCCommandTest(unittest.TestCase):
- def test_eliza(self):
- eliza = Eliza()
- eliza.execute("tom", "hi", None, None)
- eliza.execute("tom", "bye", None, None)
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py
deleted file mode 100644
index 8b016e8..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine.py
+++ /dev/null
@@ -1,165 +0,0 @@
-# Copyright (c) 2009 Google Inc. All rights reserved.
-# Copyright (c) 2009 Apple 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 os
-import time
-import traceback
-
-from datetime import datetime, timedelta
-
-from webkitpy.common.system.executive import ScriptError
-from webkitpy.common.system.deprecated_logging import log, OutputTee
-
-
-class TerminateQueue(Exception):
- pass
-
-
-class QueueEngineDelegate:
- def queue_log_path(self):
- raise NotImplementedError, "subclasses must implement"
-
- def work_item_log_path(self, work_item):
- raise NotImplementedError, "subclasses must implement"
-
- def begin_work_queue(self):
- raise NotImplementedError, "subclasses must implement"
-
- def should_continue_work_queue(self):
- raise NotImplementedError, "subclasses must implement"
-
- def next_work_item(self):
- raise NotImplementedError, "subclasses must implement"
-
- def should_proceed_with_work_item(self, work_item):
- # returns (safe_to_proceed, waiting_message, patch)
- raise NotImplementedError, "subclasses must implement"
-
- def process_work_item(self, work_item):
- raise NotImplementedError, "subclasses must implement"
-
- def handle_unexpected_error(self, work_item, message):
- raise NotImplementedError, "subclasses must implement"
-
-
-class QueueEngine:
- def __init__(self, name, delegate, wakeup_event):
- self._name = name
- self._delegate = delegate
- self._wakeup_event = wakeup_event
- self._output_tee = OutputTee()
-
- log_date_format = "%Y-%m-%d %H:%M:%S"
- sleep_duration_text = "2 mins" # This could be generated from seconds_to_sleep
- seconds_to_sleep = 120
- handled_error_code = 2
-
- # Child processes exit with a special code to the parent queue process can detect the error was handled.
- @classmethod
- def exit_after_handled_error(cls, error):
- log(error)
- exit(cls.handled_error_code)
-
- def run(self):
- self._begin_logging()
-
- self._delegate.begin_work_queue()
- while (self._delegate.should_continue_work_queue()):
- try:
- self._ensure_work_log_closed()
- work_item = self._delegate.next_work_item()
- if not work_item:
- self._sleep("No work item.")
- continue
- if not self._delegate.should_proceed_with_work_item(work_item):
- self._sleep("Not proceeding with work item.")
- continue
-
- # FIXME: Work logs should not depend on bug_id specificaly.
- # This looks fixed, no?
- self._open_work_log(work_item)
- try:
- if not self._delegate.process_work_item(work_item):
- log("Unable to process work item.")
- continue
- except ScriptError, e:
- # Use a special exit code to indicate that the error was already
- # handled in the child process and we should just keep looping.
- if e.exit_code == self.handled_error_code:
- continue
- message = "Unexpected failure when processing patch! Please file a bug against webkit-patch.\n%s" % e.message_with_output()
- self._delegate.handle_unexpected_error(work_item, message)
- except TerminateQueue, e:
- self._stopping("TerminateQueue exception received.")
- return 0
- except KeyboardInterrupt, e:
- self._stopping("User terminated queue.")
- return 1
- except Exception, e:
- traceback.print_exc()
- # Don't try tell the status bot, in case telling it causes an exception.
- self._sleep("Exception while preparing queue")
- self._stopping("Delegate terminated queue.")
- return 0
-
- def _stopping(self, message):
- log("\n%s" % message)
- self._delegate.stop_work_queue(message)
- # Be careful to shut down our OutputTee or the unit tests will be unhappy.
- self._ensure_work_log_closed()
- self._output_tee.remove_log(self._queue_log)
-
- def _begin_logging(self):
- self._queue_log = self._output_tee.add_log(self._delegate.queue_log_path())
- self._work_log = None
-
- def _open_work_log(self, work_item):
- work_item_log_path = self._delegate.work_item_log_path(work_item)
- if not work_item_log_path:
- return
- self._work_log = self._output_tee.add_log(work_item_log_path)
-
- def _ensure_work_log_closed(self):
- # If we still have a bug log open, close it.
- if self._work_log:
- self._output_tee.remove_log(self._work_log)
- self._work_log = None
-
- def _now(self):
- """Overriden by the unit tests to allow testing _sleep_message"""
- return datetime.now()
-
- def _sleep_message(self, message):
- wake_time = self._now() + timedelta(seconds=self.seconds_to_sleep)
- return "%s Sleeping until %s (%s)." % (message, wake_time.strftime(self.log_date_format), self.sleep_duration_text)
-
- def _sleep(self, message):
- log(self._sleep_message(message))
- self._wakeup_event.wait(self.seconds_to_sleep)
- self._wakeup_event.clear()
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py
deleted file mode 100644
index 37d8502..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/queueengine_unittest.py
+++ /dev/null
@@ -1,209 +0,0 @@
-# Copyright (c) 2009 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 datetime
-import os
-import shutil
-import tempfile
-import threading
-import unittest
-
-from webkitpy.common.system.executive import ScriptError
-from webkitpy.common.system.outputcapture import OutputCapture
-from webkitpy.tool.bot.queueengine import QueueEngine, QueueEngineDelegate, TerminateQueue
-
-
-class LoggingDelegate(QueueEngineDelegate):
- def __init__(self, test):
- self._test = test
- self._callbacks = []
- self._run_before = False
- self.stop_message = None
-
- expected_callbacks = [
- 'queue_log_path',
- 'begin_work_queue',
- 'should_continue_work_queue',
- 'next_work_item',
- 'should_proceed_with_work_item',
- 'work_item_log_path',
- 'process_work_item',
- 'should_continue_work_queue',
- 'stop_work_queue',
- ]
-
- def record(self, method_name):
- self._callbacks.append(method_name)
-
- def queue_log_path(self):
- self.record("queue_log_path")
- return os.path.join(self._test.temp_dir, "queue_log_path")
-
- def work_item_log_path(self, work_item):
- self.record("work_item_log_path")
- return os.path.join(self._test.temp_dir, "work_log_path", "%s.log" % work_item)
-
- def begin_work_queue(self):
- self.record("begin_work_queue")
-
- def should_continue_work_queue(self):
- self.record("should_continue_work_queue")
- if not self._run_before:
- self._run_before = True
- return True
- return False
-
- def next_work_item(self):
- self.record("next_work_item")
- return "work_item"
-
- def should_proceed_with_work_item(self, work_item):
- self.record("should_proceed_with_work_item")
- self._test.assertEquals(work_item, "work_item")
- fake_patch = { 'bug_id' : 42 }
- return (True, "waiting_message", fake_patch)
-
- def process_work_item(self, work_item):
- self.record("process_work_item")
- self._test.assertEquals(work_item, "work_item")
- return True
-
- def handle_unexpected_error(self, work_item, message):
- self.record("handle_unexpected_error")
- self._test.assertEquals(work_item, "work_item")
-
- def stop_work_queue(self, message):
- self.record("stop_work_queue")
- self.stop_message = message
-
-
-class RaisingDelegate(LoggingDelegate):
- def __init__(self, test, exception):
- LoggingDelegate.__init__(self, test)
- self._exception = exception
-
- def process_work_item(self, work_item):
- self.record("process_work_item")
- raise self._exception
-
-
-class NotSafeToProceedDelegate(LoggingDelegate):
- def should_proceed_with_work_item(self, work_item):
- self.record("should_proceed_with_work_item")
- self._test.assertEquals(work_item, "work_item")
- return False
-
-
-class FastQueueEngine(QueueEngine):
- def __init__(self, delegate):
- QueueEngine.__init__(self, "fast-queue", delegate, threading.Event())
-
- # No sleep for the wicked.
- seconds_to_sleep = 0
-
- def _sleep(self, message):
- pass
-
-
-class QueueEngineTest(unittest.TestCase):
- def test_trivial(self):
- delegate = LoggingDelegate(self)
- self._run_engine(delegate)
- self.assertEquals(delegate.stop_message, "Delegate terminated queue.")
- self.assertEquals(delegate._callbacks, LoggingDelegate.expected_callbacks)
- self.assertTrue(os.path.exists(os.path.join(self.temp_dir, "queue_log_path")))
- self.assertTrue(os.path.exists(os.path.join(self.temp_dir, "work_log_path", "work_item.log")))
-
- def test_unexpected_error(self):
- delegate = RaisingDelegate(self, ScriptError(exit_code=3))
- self._run_engine(delegate)
- expected_callbacks = LoggingDelegate.expected_callbacks[:]
- work_item_index = expected_callbacks.index('process_work_item')
- # The unexpected error should be handled right after process_work_item starts
- # but before any other callback. Otherwise callbacks should be normal.
- expected_callbacks.insert(work_item_index + 1, 'handle_unexpected_error')
- self.assertEquals(delegate._callbacks, expected_callbacks)
-
- def test_handled_error(self):
- delegate = RaisingDelegate(self, ScriptError(exit_code=QueueEngine.handled_error_code))
- self._run_engine(delegate)
- self.assertEquals(delegate._callbacks, LoggingDelegate.expected_callbacks)
-
- def _run_engine(self, delegate, engine=None, termination_message=None):
- if not engine:
- engine = QueueEngine("test-queue", delegate, threading.Event())
- if not termination_message:
- termination_message = "Delegate terminated queue."
- expected_stderr = "\n%s\n" % termination_message
- OutputCapture().assert_outputs(self, engine.run, [], expected_stderr=expected_stderr)
-
- def _test_terminating_queue(self, exception, termination_message):
- work_item_index = LoggingDelegate.expected_callbacks.index('process_work_item')
- # The terminating error should be handled right after process_work_item.
- # There should be no other callbacks after stop_work_queue.
- expected_callbacks = LoggingDelegate.expected_callbacks[:work_item_index + 1]
- expected_callbacks.append("stop_work_queue")
-
- delegate = RaisingDelegate(self, exception)
- self._run_engine(delegate, termination_message=termination_message)
-
- self.assertEquals(delegate._callbacks, expected_callbacks)
- self.assertEquals(delegate.stop_message, termination_message)
-
- def test_terminating_error(self):
- self._test_terminating_queue(KeyboardInterrupt(), "User terminated queue.")
- self._test_terminating_queue(TerminateQueue(), "TerminateQueue exception received.")
-
- def test_not_safe_to_proceed(self):
- delegate = NotSafeToProceedDelegate(self)
- self._run_engine(delegate, engine=FastQueueEngine(delegate))
- expected_callbacks = LoggingDelegate.expected_callbacks[:]
- expected_callbacks.remove('work_item_log_path')
- expected_callbacks.remove('process_work_item')
- self.assertEquals(delegate._callbacks, expected_callbacks)
-
- def test_now(self):
- """Make sure there are no typos in the QueueEngine.now() method."""
- engine = QueueEngine("test", None, None)
- self.assertTrue(isinstance(engine._now(), datetime.datetime))
-
- def test_sleep_message(self):
- engine = QueueEngine("test", None, None)
- engine._now = lambda: datetime.datetime(2010, 1, 1)
- expected_sleep_message = "MESSAGE Sleeping until 2010-01-01 00:02:00 (2 mins)."
- self.assertEqual(engine._sleep_message("MESSAGE"), expected_sleep_message)
-
- def setUp(self):
- self.temp_dir = tempfile.mkdtemp(suffix="work_queue_test_logs")
-
- def tearDown(self):
- shutil.rmtree(self.temp_dir)
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/sheriff.py b/WebKitTools/Scripts/webkitpy/tool/bot/sheriff.py
deleted file mode 100644
index da506bc..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/sheriff.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright (c) 2010 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.
-
-from webkitpy.common.checkout.changelog import view_source_url
-from webkitpy.common.net.bugzilla import parse_bug_id
-from webkitpy.common.system.deprecated_logging import log
-from webkitpy.common.system.executive import ScriptError
-from webkitpy.tool.grammar import join_with_separators
-
-
-class Sheriff(object):
- def __init__(self, tool, sheriffbot):
- self._tool = tool
- self._sheriffbot = sheriffbot
-
- def post_irc_warning(self, commit_info, builders):
- irc_nicknames = sorted([party.irc_nickname for
- party in commit_info.responsible_parties()
- if party.irc_nickname])
- irc_prefix = ": " if irc_nicknames else ""
- irc_message = "%s%s%s might have broken %s" % (
- ", ".join(irc_nicknames),
- irc_prefix,
- view_source_url(commit_info.revision()),
- join_with_separators([builder.name() for builder in builders]))
-
- self._tool.irc().post(irc_message)
-
- def post_rollout_patch(self, svn_revision, rollout_reason):
- # Ensure that svn_revision is a number (and not an option to
- # create-rollout).
- try:
- svn_revision = int(svn_revision)
- except:
- raise ScriptError(message="Invalid svn revision number \"%s\"."
- % svn_revision)
-
- if rollout_reason.startswith("-"):
- raise ScriptError(message="The rollout reason may not begin "
- "with - (\"%s\")." % rollout_reason)
-
- output = self._sheriffbot.run_webkit_patch([
- "create-rollout",
- "--force-clean",
- # In principle, we should pass --non-interactive here, but it
- # turns out that create-rollout doesn't need it yet. We can't
- # pass it prophylactically because we reject unrecognized command
- # line switches.
- "--parent-command=sheriff-bot",
- svn_revision,
- rollout_reason,
- ])
- return parse_bug_id(output)
-
- def post_blame_comment_on_bug(self, commit_info, builders, tests):
- if not commit_info.bug_id():
- return
- comment = "%s might have broken %s" % (
- view_source_url(commit_info.revision()),
- join_with_separators([builder.name() for builder in builders]))
- if tests:
- comment += "\nThe following tests are not passing:\n"
- comment += "\n".join(tests)
- self._tool.bugs.post_comment_to_bug(commit_info.bug_id(),
- comment,
- cc=self._sheriffbot.watchers)
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py
deleted file mode 100644
index 690af1f..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/sheriff_unittest.py
+++ /dev/null
@@ -1,90 +0,0 @@
-# Copyright (C) 2010 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 os
-import unittest
-
-from webkitpy.common.net.buildbot import Builder
-from webkitpy.common.system.outputcapture import OutputCapture
-from webkitpy.thirdparty.mock import Mock
-from webkitpy.tool.bot.sheriff import Sheriff
-from webkitpy.tool.mocktool import MockTool
-
-
-class MockSheriffBot(object):
- name = "mock-sheriff-bot"
- watchers = [
- "watcher@example.com",
- ]
-
- def run_webkit_patch(self, args):
- return "Created bug https://bugs.webkit.org/show_bug.cgi?id=36936\n"
-
-
-class SheriffTest(unittest.TestCase):
- def test_post_blame_comment_on_bug(self):
- def run():
- sheriff = Sheriff(MockTool(), MockSheriffBot())
- builders = [
- Builder("Foo", None),
- Builder("Bar", None),
- ]
- commit_info = Mock()
- commit_info.bug_id = lambda: None
- commit_info.revision = lambda: 4321
- # Should do nothing with no bug_id
- sheriff.post_blame_comment_on_bug(commit_info, builders, [])
- sheriff.post_blame_comment_on_bug(commit_info, builders, ["mock-test-1", "mock-test-2"])
- # Should try to post a comment to the bug, but MockTool.bugs does nothing.
- commit_info.bug_id = lambda: 1234
- sheriff.post_blame_comment_on_bug(commit_info, builders, [])
- sheriff.post_blame_comment_on_bug(commit_info, builders, ["mock-test-1"])
- sheriff.post_blame_comment_on_bug(commit_info, builders, ["mock-test-1", "mock-test-2"])
-
- expected_stderr = u"""MOCK bug comment: bug_id=1234, cc=['watcher@example.com']
---- Begin comment ---
-http://trac.webkit.org/changeset/4321 might have broken Foo and Bar
---- End comment ---
-
-MOCK bug comment: bug_id=1234, cc=['watcher@example.com']
---- Begin comment ---
-http://trac.webkit.org/changeset/4321 might have broken Foo and Bar
-The following tests are not passing:
-mock-test-1
---- End comment ---
-
-MOCK bug comment: bug_id=1234, cc=['watcher@example.com']
---- Begin comment ---
-http://trac.webkit.org/changeset/4321 might have broken Foo and Bar
-The following tests are not passing:
-mock-test-1
-mock-test-2
---- End comment ---
-
-"""
- OutputCapture().assert_outputs(self, run, expected_stderr=expected_stderr)
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/sheriffircbot.py b/WebKitTools/Scripts/webkitpy/tool/bot/sheriffircbot.py
deleted file mode 100644
index de77222..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/sheriffircbot.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# Copyright (c) 2010 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 webkitpy.tool.bot.irc_command as irc_command
-
-from webkitpy.common.net.irc.ircbot import IRCBotDelegate
-from webkitpy.common.thread.threadedmessagequeue import ThreadedMessageQueue
-
-
-class _IRCThreadTearoff(IRCBotDelegate):
- def __init__(self, password, message_queue, wakeup_event):
- self._password = password
- self._message_queue = message_queue
- self._wakeup_event = wakeup_event
-
- # IRCBotDelegate methods
-
- def irc_message_received(self, nick, message):
- self._message_queue.post([nick, message])
- self._wakeup_event.set()
-
- def irc_nickname(self):
- return "sheriffbot"
-
- def irc_password(self):
- return self._password
-
-
-class SheriffIRCBot(object):
- def __init__(self, tool, sheriff):
- self._tool = tool
- self._sheriff = sheriff
- self._message_queue = ThreadedMessageQueue()
-
- def irc_delegate(self):
- return _IRCThreadTearoff(self._tool.irc_password,
- self._message_queue,
- self._tool.wakeup_event)
-
- def process_message(self, message):
- (nick, request) = message
- tokenized_request = request.strip().split(" ")
- if not tokenized_request:
- return
- command = irc_command.commands.get(tokenized_request[0])
- args = tokenized_request[1:]
- if not command:
- # Give the peoples someone to talk with.
- command = irc_command.Eliza
- args = tokenized_request
- response = command().execute(nick, args, self._tool, self._sheriff)
- if response:
- self._tool.irc().post(response)
-
- def process_pending_messages(self):
- (messages, is_running) = self._message_queue.take_all()
- for message in messages:
- self.process_message(message)
diff --git a/WebKitTools/Scripts/webkitpy/tool/bot/sheriffircbot_unittest.py b/WebKitTools/Scripts/webkitpy/tool/bot/sheriffircbot_unittest.py
deleted file mode 100644
index 08023bd..0000000
--- a/WebKitTools/Scripts/webkitpy/tool/bot/sheriffircbot_unittest.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# Copyright (c) 2010 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 unittest
-import random
-
-from webkitpy.common.system.outputcapture import OutputCapture
-from webkitpy.tool.bot.sheriff import Sheriff
-from webkitpy.tool.bot.sheriffircbot import SheriffIRCBot
-from webkitpy.tool.bot.sheriff_unittest import MockSheriffBot
-from webkitpy.tool.mocktool import MockTool
-
-
-def run(message):
- tool = MockTool()
- tool.ensure_irc_connected(None)
- bot = SheriffIRCBot(tool, Sheriff(tool, MockSheriffBot()))
- bot._message_queue.post(["mock_nick", message])
- bot.process_pending_messages()
-
-
-class SheriffIRCBotTest(unittest.TestCase):
- def test_hi(self):
- random.seed(23324)
- expected_stderr = 'MOCK: irc.post: "Only you can prevent forest fires." -- Smokey the Bear\n'
- OutputCapture().assert_outputs(self, run, args=["hi"], expected_stderr=expected_stderr)
-
- def test_help(self):
- expected_stderr = "MOCK: irc.post: mock_nick: Available commands: rollout, hi, help, restart, last-green-revision\n"
- OutputCapture().assert_outputs(self, run, args=["help"], expected_stderr=expected_stderr)
-
- def test_lgr(self):
- expected_stderr = "MOCK: irc.post: mock_nick: http://trac.webkit.org/changeset/9479\n"
- OutputCapture().assert_outputs(self, run, args=["last-green-revision"], expected_stderr=expected_stderr)
-
- def test_rollout(self):
- expected_stderr = "MOCK: irc.post: Preparing rollout for r21654...\nMOCK: irc.post: mock_nick: Created rollout: http://example.com/36936\n"
- OutputCapture().assert_outputs(self, run, args=["rollout 21654 This patch broke the world"], expected_stderr=expected_stderr)
-
- def test_rollout_with_r_in_svn_revision(self):
- expected_stderr = "MOCK: irc.post: Preparing rollout for r21654...\nMOCK: irc.post: mock_nick: Created rollout: http://example.com/36936\n"
- OutputCapture().assert_outputs(self, run, args=["rollout r21654 This patch broke the world"], expected_stderr=expected_stderr)
-
- def test_rollout_bananas(self):
- expected_stderr = "MOCK: irc.post: mock_nick: Usage: SVN_REVISION REASON\n"
- OutputCapture().assert_outputs(self, run, args=["rollout bananas"], expected_stderr=expected_stderr)
-
- def test_rollout_invalidate_revision(self):
- expected_stderr = ("MOCK: irc.post: Preparing rollout for r--component=Tools...\n"
- "MOCK: irc.post: mock_nick: Failed to create rollout patch:\n"
- "MOCK: irc.post: Invalid svn revision number \"--component=Tools\".\n")
- OutputCapture().assert_outputs(self, run,
- args=["rollout "
- "--component=Tools 21654"],
- expected_stderr=expected_stderr)
-
- def test_rollout_invalidate_reason(self):
- expected_stderr = ("MOCK: irc.post: Preparing rollout for "
- "r21654...\nMOCK: irc.post: mock_nick: Failed to "
- "create rollout patch:\nMOCK: irc.post: The rollout"
- " reason may not begin with - (\"-bad (Requested "
- "by mock_nick on #webkit).\").\n")
- OutputCapture().assert_outputs(self, run,
- args=["rollout "
- "21654 -bad"],
- expected_stderr=expected_stderr)
-
- def test_rollout_no_reason(self):
- expected_stderr = "MOCK: irc.post: mock_nick: Usage: SVN_REVISION REASON\n"
- OutputCapture().assert_outputs(self, run, args=["rollout 21654"], expected_stderr=expected_stderr)