Title: [125123] trunk/Tools
Revision
125123
Author
[email protected]
Date
2012-08-08 17:19:23 -0700 (Wed, 08 Aug 2012)

Log Message

Add Perf EWS IRC bot
https://bugs.webkit.org/show_bug.cgi?id=92913

Reviewed by Dirk Pranke.

Adds the preliminary implementation of perfalizer, a IRC bot that runs performance tests
based on IRC requests.

* Scripts/webkitpy/common/checkout/scm/scm_mock.py:
(MockSCM.head_svn_revision): The actual implementation returns string, so match that.
(MockSCM.svn_revision): Ditto.
* Scripts/webkitpy/common/net/bugzilla/bugzilla.py:
(Bugzilla.add_attachment_to_bug): Added mimetype.
* Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py:
(MockBugzilla.add_attachment_to_bug): Ditto.
* Scripts/webkitpy/common/system/filesystem.py:
(FileSystem.copytree): Added.
* Scripts/webkitpy/common/system/filesystem_mock.py:
(MockFileSystem.copytree): Added.
* Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py: Rebaselined tests
that had assumed revision numbers were integers.
(test_run_with_json_output):
(test_run_with_description):
(test_run_generates_json_by_default):
(test_run_generates_and_show_results_page):
(test_run_with_json_source):
(test_run_with_multiple_repositories):
* Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py:
* Scripts/webkitpy/tool/commands/__init__.py:
* Scripts/webkitpy/tool/commands/perfalizer.py: Added.
(PerfalizerTask):
(PerfalizerTask.__init__):
(PerfalizerTask._copy_build_product_without_patch):
(PerfalizerTask.run):
(PerfalizerTask.parent_command):
(PerfalizerTask.run_webkit_patch):
(PerfalizerTask._json_path):
(PerfalizerTask._results_page_path):
(PerfalizerTask._run_perf_test):
(PerfalizerTask.run_command):
(PerfalizerTask.command_passed):
(PerfalizerTask.command_failed):
(PerfalizerTask.refetch_patch):
(PerfalizerTask.expected_failures):
(PerfalizerTask.build_style):
(PerfTest): IRC command.
(PerfTest.execute):
(Perfalizer): IRC bot.
(Perfalizer.begin_work_queue):
(Perfalizer.work_item_log_path):
(Perfalizer._is_old_failure):
(Perfalizer.next_work_item):
(Perfalizer.process_work_item):
(Perfalizer.handle_unexpected_error):
(Perfalizer.handle_script_error):
* Scripts/webkitpy/tool/commands/perfalizer_unittest.py: Added.
(PerfalizerTaskTest):
(PerfalizerTaskTest._create_and_run_perfalizer):
(PerfalizerTaskTest._create_and_run_perfalizer.logger):
(PerfalizerTaskTest._create_and_run_perfalizer.run_webkit_patch):
(PerfalizerTaskTest._create_and_run_perfalizer.run_perf_test):
(PerfalizerTaskTest.test_run):
(PerfalizerTaskTest.test_run_with_clean_fails):
(PerfalizerTaskTest.test_run_with_update_fails):
(PerfalizerTaskTest.test_run_with_build_fails):
(PerfalizerTaskTest.test_run_with_perf_test_fails):
(PerfalizerTaskTest.test_run_without_results_page):
* Scripts/webkitpy/tool/commands/queues_unittest.py:
(AbstractPatchQueueTest.test_upload_results_archive_for_patch): Rebaselined.
* Scripts/webkitpy/tool/commands/upload_unittest.py:
(test_attach_to_bug): Ditto.
(test_attach_to_bug_no_description_or_comment): Ditto.

Modified Paths

Added Paths

Diff

Modified: trunk/Tools/ChangeLog (125122 => 125123)


--- trunk/Tools/ChangeLog	2012-08-09 00:18:23 UTC (rev 125122)
+++ trunk/Tools/ChangeLog	2012-08-09 00:19:23 UTC (rev 125123)
@@ -1,3 +1,78 @@
+2012-08-08  Ryosuke Niwa  <[email protected]>
+
+        Add Perf EWS IRC bot
+        https://bugs.webkit.org/show_bug.cgi?id=92913
+
+        Reviewed by Dirk Pranke.
+
+        Adds the preliminary implementation of perfalizer, a IRC bot that runs performance tests
+        based on IRC requests.
+
+        * Scripts/webkitpy/common/checkout/scm/scm_mock.py:
+        (MockSCM.head_svn_revision): The actual implementation returns string, so match that.
+        (MockSCM.svn_revision): Ditto.
+        * Scripts/webkitpy/common/net/bugzilla/bugzilla.py:
+        (Bugzilla.add_attachment_to_bug): Added mimetype.
+        * Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py:
+        (MockBugzilla.add_attachment_to_bug): Ditto.
+        * Scripts/webkitpy/common/system/filesystem.py:
+        (FileSystem.copytree): Added.
+        * Scripts/webkitpy/common/system/filesystem_mock.py:
+        (MockFileSystem.copytree): Added.
+        * Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py: Rebaselined tests
+        that had assumed revision numbers were integers.
+        (test_run_with_json_output):
+        (test_run_with_description):
+        (test_run_generates_json_by_default):
+        (test_run_generates_and_show_results_page):
+        (test_run_with_json_source):
+        (test_run_with_multiple_repositories):
+        * Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py:
+        * Scripts/webkitpy/tool/commands/__init__.py:
+        * Scripts/webkitpy/tool/commands/perfalizer.py: Added.
+        (PerfalizerTask):
+        (PerfalizerTask.__init__):
+        (PerfalizerTask._copy_build_product_without_patch):
+        (PerfalizerTask.run):
+        (PerfalizerTask.parent_command):
+        (PerfalizerTask.run_webkit_patch):
+        (PerfalizerTask._json_path):
+        (PerfalizerTask._results_page_path):
+        (PerfalizerTask._run_perf_test):
+        (PerfalizerTask.run_command):
+        (PerfalizerTask.command_passed):
+        (PerfalizerTask.command_failed):
+        (PerfalizerTask.refetch_patch):
+        (PerfalizerTask.expected_failures):
+        (PerfalizerTask.build_style):
+        (PerfTest): IRC command.
+        (PerfTest.execute):
+        (Perfalizer): IRC bot.
+        (Perfalizer.begin_work_queue):
+        (Perfalizer.work_item_log_path):
+        (Perfalizer._is_old_failure):
+        (Perfalizer.next_work_item):
+        (Perfalizer.process_work_item):
+        (Perfalizer.handle_unexpected_error):
+        (Perfalizer.handle_script_error):
+        * Scripts/webkitpy/tool/commands/perfalizer_unittest.py: Added.
+        (PerfalizerTaskTest):
+        (PerfalizerTaskTest._create_and_run_perfalizer):
+        (PerfalizerTaskTest._create_and_run_perfalizer.logger):
+        (PerfalizerTaskTest._create_and_run_perfalizer.run_webkit_patch):
+        (PerfalizerTaskTest._create_and_run_perfalizer.run_perf_test):
+        (PerfalizerTaskTest.test_run):
+        (PerfalizerTaskTest.test_run_with_clean_fails):
+        (PerfalizerTaskTest.test_run_with_update_fails):
+        (PerfalizerTaskTest.test_run_with_build_fails):
+        (PerfalizerTaskTest.test_run_with_perf_test_fails):
+        (PerfalizerTaskTest.test_run_without_results_page):
+        * Scripts/webkitpy/tool/commands/queues_unittest.py:
+        (AbstractPatchQueueTest.test_upload_results_archive_for_patch): Rebaselined.
+        * Scripts/webkitpy/tool/commands/upload_unittest.py:
+        (test_attach_to_bug): Ditto.
+        (test_attach_to_bug_no_description_or_comment): Ditto.
+
 2012-08-08  Dirk Pranke  <[email protected]>
 
         webkit-patch rebaseline-expectations needs to support multiple expectations files

Modified: trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm_mock.py (125122 => 125123)


--- trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm_mock.py	2012-08-09 00:18:23 UTC (rev 125122)
+++ trunk/Tools/Scripts/webkitpy/common/checkout/scm/scm_mock.py	2012-08-09 00:19:23 UTC (rev 125123)
@@ -69,10 +69,10 @@
         return ["MockFile1"]
 
     def head_svn_revision(self):
-        return 1234
+        return '1234'
 
     def svn_revision(self, path):
-        return 5678
+        return '5678'
 
     def create_patch(self, git_commit, changed_files=None):
         return "Patch1"

Modified: trunk/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py (125122 => 125123)


--- trunk/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py	2012-08-09 00:18:23 UTC (rev 125122)
+++ trunk/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py	2012-08-09 00:19:23 UTC (rev 125123)
@@ -578,19 +578,14 @@
             return file_object.name
         return "bug-%s-%s.%s" % (bug_id, timestamp(), extension)
 
-    def add_attachment_to_bug(self,
-                              bug_id,
-                              file_or_string,
-                              description,
-                              filename=None,
-                              comment_text=None):
+    def add_attachment_to_bug(self, bug_id, file_or_string, description, filename=None, comment_text=None, mimetype=None):
         self.authenticate()
         log('Adding attachment "%s" to %s' % (description, self.bug_url_for_bug_id(bug_id)))
         self.browser.open(self.add_attachment_url(bug_id))
         self.browser.select_form(name="entryform")
         file_object = self._file_object_for_upload(file_or_string)
         filename = filename or self._filename_for_upload(file_object, bug_id)
-        self._fill_attachment_form(description, file_object, filename=filename)
+        self._fill_attachment_form(description, file_object, filename=filename, mimetype=mimetype)
         if comment_text:
             log(comment_text)
             self.browser['comment'] = comment_text

Modified: trunk/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py (125122 => 125123)


--- trunk/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py	2012-08-09 00:18:23 UTC (rev 125122)
+++ trunk/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla_mock.py	2012-08-09 00:19:23 UTC (rev 125123)
@@ -393,13 +393,9 @@
         log("MOCK bug comment: bug_id=%s, cc=%s\n--- Begin comment ---\n%s\n--- End comment ---\n" % (
             bug_id, cc, comment_text))
 
-    def add_attachment_to_bug(self,
-                              bug_id,
-                              file_or_string,
-                              description,
-                              filename=None,
-                              comment_text=None):
-        log("MOCK add_attachment_to_bug: bug_id=%s, description=%s filename=%s" % (bug_id, description, filename))
+    def add_attachment_to_bug(self, bug_id, file_or_string, description, filename=None, comment_text=None, mimetype=None):
+        log("MOCK add_attachment_to_bug: bug_id=%s, description=%s filename=%s mimetype=%s" %
+            (bug_id, description, filename, mimetype))
         if comment_text:
             log("-- Begin comment --")
             log(comment_text)

Modified: trunk/Tools/Scripts/webkitpy/common/system/filesystem.py (125122 => 125123)


--- trunk/Tools/Scripts/webkitpy/common/system/filesystem.py	2012-08-09 00:18:23 UTC (rev 125122)
+++ trunk/Tools/Scripts/webkitpy/common/system/filesystem.py	2012-08-09 00:19:23 UTC (rev 125123)
@@ -262,6 +262,9 @@
         """Delete the directory rooted at path, whether empty or not."""
         shutil.rmtree(path, ignore_errors=True)
 
+    def copytree(self, source, destination):
+        shutil.copytree(source, destination)
+
     def split(self, path):
         """Return (dirname, basename + '.' + ext)"""
         return os.path.split(path)

Modified: trunk/Tools/Scripts/webkitpy/common/system/filesystem_mock.py (125122 => 125123)


--- trunk/Tools/Scripts/webkitpy/common/system/filesystem_mock.py	2012-08-09 00:18:23 UTC (rev 125122)
+++ trunk/Tools/Scripts/webkitpy/common/system/filesystem_mock.py	2012-08-09 00:19:23 UTC (rev 125123)
@@ -378,6 +378,16 @@
 
         self.dirs = set(filter(lambda d: not d.startswith(path), self.dirs))
 
+    def copytree(self, source, destination):
+        source = self.normpath(source)
+        destination = self.normpath(destination)
+
+        for source_file in self.files:
+            if source_file.startswith(source):
+                destination_path = self.join(destination, self.relpath(source_file, source))
+                self.maybe_make_directory(self.dirname(destination_path))
+                self.files[destination_path] = self.files[source_file]
+
     def split(self, path):
         idx = path.rfind(self.sep)
         if idx == -1:

Modified: trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py (125122 => 125123)


--- trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py	2012-08-09 00:18:23 UTC (rev 125122)
+++ trunk/Tools/Scripts/webkitpy/performance_tests/perftestsrunner_unittest.py	2012-08-09 00:19:23 UTC (rev 125123)
@@ -268,7 +268,7 @@
             "timestamp": 123456789, "results":
             {"Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
             "inspector/pass.html:group_name:test_name": 42},
-            "webkit-revision": 5678, "branch": "webkit-trunk"})
+            "webkit-revision": "5678", "branch": "webkit-trunk"})
 
     def test_run_with_description(self):
         runner, port = self.create_runner(args=['--output-json-path=/mock-checkout/output.json',
@@ -278,7 +278,7 @@
             "timestamp": 123456789, "description": "some description", "results":
             {"Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
             "inspector/pass.html:group_name:test_name": 42},
-            "webkit-revision": 5678, "branch": "webkit-trunk"})
+            "webkit-revision": "5678", "branch": "webkit-trunk"})
 
     def create_runner_and_setup_results_template(self, args=[]):
         runner, port = self.create_runner(args)
@@ -310,7 +310,7 @@
             "timestamp": 123456789, "results":
             {"Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
             "inspector/pass.html:group_name:test_name": 42},
-            "webkit-revision": 5678, "branch": "webkit-trunk"}])
+            "webkit-revision": "5678", "branch": "webkit-trunk"}])
 
         self.assertTrue(filesystem.isfile(output_json_path))
         self.assertTrue(filesystem.isfile(results_page_path))
@@ -324,7 +324,7 @@
 
         expected_entry = {"timestamp": 123456789, "results": {"Bindings/event-target-wrapper":
             {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
-            "inspector/pass.html:group_name:test_name": 42}, "webkit-revision": 5678, "branch": "webkit-trunk"}
+            "inspector/pass.html:group_name:test_name": 42}, "webkit-revision": "5678", "branch": "webkit-trunk"}
 
         self.maxDiff = None
         json_output = port.host.filesystem.read_text_file('/mock-checkout/output.json')
@@ -373,7 +373,7 @@
             "timestamp": 123456789, "results":
             {"Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
             "inspector/pass.html:group_name:test_name": 42},
-            "webkit-revision": 5678, "branch": "webkit-trunk",
+            "webkit-revision": "5678", "branch": "webkit-trunk",
             "key": "value"})
 
     def test_run_with_bad_json_source(self):
@@ -394,7 +394,7 @@
             "timestamp": 123456789, "results":
             {"Bindings/event-target-wrapper": {"max": 1510, "avg": 1489.05, "median": 1487, "min": 1471, "stdev": 14.46, "unit": "ms"},
             "inspector/pass.html:group_name:test_name": 42.0},
-            "webkit-revision": 5678, "some-revision": 5678, "branch": "webkit-trunk"})
+            "webkit-revision": "5678", "some-revision": "5678", "branch": "webkit-trunk"})
 
     def test_run_with_upload_json(self):
         runner, port = self.create_runner(args=['--output-json-path=/mock-checkout/output.json',

Modified: trunk/Tools/Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py (125122 => 125123)


--- trunk/Tools/Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py	2012-08-09 00:18:23 UTC (rev 125122)
+++ trunk/Tools/Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py	2012-08-09 00:19:23 UTC (rev 125123)
@@ -125,7 +125,7 @@
 component: Tools / Tests
 cc: [email protected]
 blocked: 50856
-MOCK add_attachment_to_bug: bug_id=60001, description=Failure diff from mock-bot-id filename=failure.diff
+MOCK add_attachment_to_bug: bug_id=60001, description=Failure diff from mock-bot-id filename=failure.diff mimetype=None
 MOCK bug comment: bug_id=50000, cc=None
 --- Begin comment ---
 The dummy-queue encountered the following flaky tests while processing attachment 10000:

Modified: trunk/Tools/Scripts/webkitpy/tool/commands/__init__.py (125122 => 125123)


--- trunk/Tools/Scripts/webkitpy/tool/commands/__init__.py	2012-08-09 00:18:23 UTC (rev 125122)
+++ trunk/Tools/Scripts/webkitpy/tool/commands/__init__.py	2012-08-09 00:19:23 UTC (rev 125123)
@@ -12,6 +12,7 @@
 from webkitpy.tool.commands.findusers import FindUsers
 from webkitpy.tool.commands.gardenomatic import GardenOMatic
 from webkitpy.tool.commands.openbugs import OpenBugs
+from webkitpy.tool.commands.perfalizer import Perfalizer
 from webkitpy.tool.commands.prettydiff import PrettyDiff
 from webkitpy.tool.commands.queries import *
 from webkitpy.tool.commands.queues import *

Added: trunk/Tools/Scripts/webkitpy/tool/commands/perfalizer.py (0 => 125123)


--- trunk/Tools/Scripts/webkitpy/tool/commands/perfalizer.py	                        (rev 0)
+++ trunk/Tools/Scripts/webkitpy/tool/commands/perfalizer.py	2012-08-09 00:19:23 UTC (rev 125123)
@@ -0,0 +1,215 @@
+# Copyright (c) 2012 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.deprecated_logging import log
+from webkitpy.tool.bot.expectedfailures import ExpectedFailures
+from webkitpy.tool.bot.irc_command import IRCCommand
+from webkitpy.tool.bot.irc_command import Help
+from webkitpy.tool.bot.irc_command import Hi
+from webkitpy.tool.bot.irc_command import Restart
+from webkitpy.tool.bot.ircbot import IRCBot
+from webkitpy.tool.bot.patchanalysistask import PatchAnalysisTask, PatchAnalysisTaskDelegate, UnableToApplyPatch
+from webkitpy.tool.bot.sheriff import Sheriff
+from webkitpy.tool.commands.queues import AbstractQueue
+from webkitpy.tool.commands.stepsequence import StepSequenceErrorHandler
+
+
+class PerfalizerTask(PatchAnalysisTask):
+    def __init__(self, tool, patch, logger):
+        PatchAnalysisTask.__init__(self, self, patch)
+        self._port = tool.port_factory.get()
+        self._tool = tool
+        self._logger = logger
+
+    def _copy_build_product_without_patch(self):
+        filesystem = self._tool.filesystem
+        configuration = filesystem.basename(self._port._build_path())
+        self._build_directory = filesystem.dirname(self._port._build_path())
+        self._build_directory_without_patch = self._build_directory + 'WithoutPatch'
+
+        try:
+            filesystem.rmtree(self._build_directory_without_patch)
+            filesystem.copytree(filesystem.join(self._build_directory, configuration),
+                filesystem.join(self._build_directory_without_patch, configuration))
+            return True
+        except:
+            return False
+
+    def run(self):
+        if not self._patch.committer() and not self._patch.attacher().can_commit:
+            self._logger('The patch %d is not authorized by a commmitter' % self._patch.id())
+            return False
+
+        self._logger('Preparing to run performance tests for the attachment %d...' % self._patch.id())
+        if not self._clean() or not self._update():
+            return False
+
+        head_revision = self._tool.scm().head_svn_revision()
+
+        self._logger('Building WebKit at r%s without the patch' % head_revision)
+        if not self._build():
+            return False
+
+        if not self._port.check_build(needs_http=False):
+            self._logger('Failed to build DumpRenderTree.')
+            return False
+
+        if not self._copy_build_product_without_patch():
+            self._logger('Failed to copy the build product from %s to %s' % (self._build_directory, self._build_directory_without_patch))
+            return False
+
+        self._logger('Building WebKit at r%s with the patch' % head_revision)
+        if not self._apply() or not self._build():
+            return False
+
+        if not self._port.check_build(needs_http=False):
+            self._logger('Failed to build DumpRenderTree.')
+            return False
+
+        filesystem = self._tool.filesystem
+        if filesystem.exists(self._json_path()):
+            filesystem.remove(self._json_path())
+
+        self._logger("Running performance tests...")
+        if self._run_perf_test(self._build_directory_without_patch) < 0:
+            self._logger('Failed to run performance tests without the patch.')
+            return False
+
+        if self._run_perf_test(self._build_directory) < 0:
+            self._logger('Failed to run performance tests with the patch.')
+            return False
+
+        if not filesystem.exists(self._results_page_path()):
+            self._logger('Failed to generate the results page.')
+            return False
+
+        results_page = filesystem.read_text_file(self._results_page_path())
+        self._tool.bugs.add_attachment_to_bug(self._patch.bug_id(), results_page,
+            description="Performance tests results for %d" % self._patch.id(), mimetype='text/html')
+
+        self._logger("Uploaded the results on the bug %d" % self._patch.bug_id())
+        return True
+
+    def parent_command(self):
+        return "perfalizer"
+
+    def run_webkit_patch(self, args):
+        webkit_patch_args = [self._tool.path()]
+        webkit_patch_args.extend(args)
+        return self._tool.executive.run_and_throw_if_fail(webkit_patch_args, cwd=self._tool.scm().checkout_root)
+
+    def _json_path(self):
+        return self._tool.filesystem.join(self._build_directory, 'PerformanceTestResults.json')
+
+    def _results_page_path(self):
+        return self._tool.filesystem.join(self._build_directory, 'PerformanceTestResults.html')
+
+    def _run_perf_test(self, build_path):
+        filesystem = self._tool.filesystem
+        script_path = filesystem.join(filesystem.dirname(self._tool.path()), 'run-perf-tests')
+        perf_test_runner_args = [script_path, '--no-build', '--no-show-results', '--build-directory', build_path,
+            '--output-json-path', self._json_path()]
+        return self._tool.executive.run_and_throw_if_fail(perf_test_runner_args, cwd=self._tool.scm().checkout_root)
+
+    def run_command(self, command):
+        self.run_webkit_patch(command)
+
+    def command_passed(self, message, patch):
+        pass
+
+    def command_failed(self, message, script_error, patch):
+        self._logger(message)
+
+    def refetch_patch(self, patch):
+        return self._tool.bugs.fetch_attachment(patch.id())
+
+    def expected_failures(self):
+        return ExpectedFailures()
+
+    def build_style(self):
+        return "release"
+
+
+class PerfTest(IRCCommand):
+    def execute(self, nick, args, tool, sheriff):
+        if not args:
+            tool.irc().post(nick + ": Please specify an attachment/patch id")
+            return
+
+        patch_id = args[0]
+        patch = tool.bugs.fetch_attachment(patch_id)
+        if not patch:
+            tool.irc().post(nick + ": Could not fetch the patch")
+            return
+
+        task = PerfalizerTask(tool, patch, lambda message: tool.irc().post('%s: %s' % (nick, message)))
+        task.run()
+
+
+class Perfalizer(AbstractQueue, StepSequenceErrorHandler):
+    name = "perfalizer"
+    watchers = AbstractQueue.watchers + ["[email protected]"]
+
+    _commands = {
+        "help": Help,
+        "hi": Hi,
+        "restart": Restart,
+        "test": PerfTest,
+    }
+
+    # AbstractQueue methods
+
+    def begin_work_queue(self):
+        AbstractQueue.begin_work_queue(self)
+        self._sheriff = Sheriff(self._tool, self)
+        self._irc_bot = IRCBot("perfalizer", self._tool, self._sheriff, self._commands)
+        self._tool.ensure_irc_connected(self._irc_bot.irc_delegate())
+
+    def work_item_log_path(self, failure_map):
+        return None
+
+    def _is_old_failure(self, revision):
+        return self._tool.status_server.svn_revision(revision)
+
+    def next_work_item(self):
+        self._irc_bot.process_pending_messages()
+        return
+
+    def process_work_item(self, failure_map):
+        return True
+
+    def handle_unexpected_error(self, failure_map, message):
+        log(message)
+
+    # StepSequenceErrorHandler methods
+
+    @classmethod
+    def handle_script_error(cls, tool, state, script_error):
+        # Ideally we would post some information to IRC about what went wrong
+        # here, but we don't have the IRC password in the child process.
+        pass

Added: trunk/Tools/Scripts/webkitpy/tool/commands/perfalizer_unittest.py (0 => 125123)


--- trunk/Tools/Scripts/webkitpy/tool/commands/perfalizer_unittest.py	                        (rev 0)
+++ trunk/Tools/Scripts/webkitpy/tool/commands/perfalizer_unittest.py	2012-08-09 00:19:23 UTC (rev 125123)
@@ -0,0 +1,111 @@
+# Copyright (C) 2012 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.common.net.buildbot import Builder
+from webkitpy.common.system.executive import ScriptError
+from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.layout_tests.port.test import TestPort
+from webkitpy.tool.commands.perfalizer import PerfalizerTask
+from webkitpy.tool.mocktool import MockTool
+
+
+class PerfalizerTaskTest(unittest.TestCase):
+    def _create_and_run_perfalizer(self, commands_to_fail=[]):
+        tool = MockTool()
+        patch = tool.bugs.fetch_attachment(10000)
+
+        logs = []
+
+        def logger(message):
+            logs.append(message)
+
+        def run_webkit_patch(args):
+            if args[0] in commands_to_fail:
+                raise ScriptError
+
+        def run_perf_test(build_path):
+            if 'run-perf-tests' in commands_to_fail:
+                return -1
+            if 'results-page' not in commands_to_fail:
+                tool.filesystem.write_text_file(tool.filesystem.join(build_path, 'PerformanceTestResults.html'), 'results page')
+            return 0
+
+        perfalizer = PerfalizerTask(tool, patch, logger)
+        perfalizer._port = TestPort(tool)
+        perfalizer.run_webkit_patch = run_webkit_patch
+        perfalizer._run_perf_test = run_perf_test
+
+        capture = OutputCapture()
+        capture.capture_output()
+
+        if commands_to_fail:
+            self.assertFalse(perfalizer.run())
+        else:
+            self.assertTrue(perfalizer.run())
+
+        capture.restore_output()
+
+        return logs
+
+    def test_run(self):
+        self.assertEqual(self._create_and_run_perfalizer(), [
+            'Preparing to run performance tests for the attachment 10000...',
+            'Building WebKit at r1234 without the patch',
+            'Building WebKit at r1234 with the patch',
+            'Running performance tests...',
+            'Uploaded the results on the bug 50000'])
+
+    def test_run_with_clean_fails(self):
+        self.assertEqual(self._create_and_run_perfalizer(['clean']), [
+            'Preparing to run performance tests for the attachment 10000...',
+            'Unable to clean working directory'])
+
+    def test_run_with_update_fails(self):
+        logs = self._create_and_run_perfalizer(['update'])
+        self.assertEqual(len(logs), 2)
+        self.assertEqual(logs[-1], 'Unable to update working directory')
+
+    def test_run_with_build_fails(self):
+        logs = self._create_and_run_perfalizer(['build'])
+        self.assertEqual(len(logs), 3)
+
+    def test_run_with_build_fails(self):
+        logs = self._create_and_run_perfalizer(['apply-attachment'])
+        self.assertEqual(len(logs), 4)
+
+    def test_run_with_perf_test_fails(self):
+        logs = self._create_and_run_perfalizer(['run-perf-tests'])
+        self.assertEqual(len(logs), 5)
+        self.assertEqual(logs[-1], 'Failed to run performance tests without the patch.')
+
+    def test_run_without_results_page(self):
+        logs = self._create_and_run_perfalizer(['results-page'])
+        self.assertEqual(len(logs), 5)
+        self.assertEqual(logs[-1], 'Failed to generate the results page.')

Modified: trunk/Tools/Scripts/webkitpy/tool/commands/queues_unittest.py (125122 => 125123)


--- trunk/Tools/Scripts/webkitpy/tool/commands/queues_unittest.py	2012-08-09 00:18:23 UTC (rev 125122)
+++ trunk/Tools/Scripts/webkitpy/tool/commands/queues_unittest.py	2012-08-09 00:19:23 UTC (rev 125123)
@@ -173,7 +173,7 @@
         queue._options = Mock()
         queue._options.port = None
         patch = queue._tool.bugs.fetch_attachment(10001)
-        expected_stderr = """MOCK add_attachment_to_bug: bug_id=50000, description=Archive of layout-test-results from bot filename=layout-test-results.zip
+        expected_stderr = """MOCK add_attachment_to_bug: bug_id=50000, description=Archive of layout-test-results from bot filename=layout-test-results.zip mimetype=None
 -- Begin comment --
 The attached test failures were seen while running run-webkit-tests on the mock-queue.
 Port: MockPort  Platform: MockPlatform 1.0
@@ -405,14 +405,14 @@
 Port: MockPort  Platform: MockPlatform 1.0
 --- End comment ---
 
-MOCK add_attachment_to_bug: bug_id=50002, description=Failure diff from bot filename=failure.diff
+MOCK add_attachment_to_bug: bug_id=50002, description=Failure diff from bot filename=failure.diff mimetype=None
 MOCK bug comment: bug_id=50002, cc=None
 --- Begin comment ---
 The commit-queue just saw bar/baz.html flake (Text diff mismatch) while processing attachment 10000 on bug 50000.
 Port: MockPort  Platform: MockPlatform 1.0
 --- End comment ---
 
-MOCK add_attachment_to_bug: bug_id=50002, description=Archive of layout-test-results from bot filename=layout-test-results.zip
+MOCK add_attachment_to_bug: bug_id=50002, description=Archive of layout-test-results from bot filename=layout-test-results.zip mimetype=None
 MOCK bug comment: bug_id=50000, cc=None
 --- Begin comment ---
 The commit-queue encountered the following flaky tests while processing attachment 10000:

Modified: trunk/Tools/Scripts/webkitpy/tool/commands/upload_unittest.py (125122 => 125123)


--- trunk/Tools/Scripts/webkitpy/tool/commands/upload_unittest.py	2012-08-09 00:18:23 UTC (rev 125122)
+++ trunk/Tools/Scripts/webkitpy/tool/commands/upload_unittest.py	2012-08-09 00:19:23 UTC (rev 125123)
@@ -79,7 +79,7 @@
         options = MockOptions()
         options.comment = "extra comment"
         options.description = "file description"
-        expected_stderr = """MOCK add_attachment_to_bug: bug_id=50000, description=file description filename=None
+        expected_stderr = """MOCK add_attachment_to_bug: bug_id=50000, description=file description filename=None mimetype=None
 -- Begin comment --
 extra comment
 -- End comment --
@@ -90,7 +90,7 @@
         options = MockOptions()
         options.comment = None
         options.description = None
-        expected_stderr = """MOCK add_attachment_to_bug: bug_id=50000, description=file.txt filename=None
+        expected_stderr = """MOCK add_attachment_to_bug: bug_id=50000, description=file.txt filename=None mimetype=None
 """
         self.assert_execute_outputs(AttachToBug(), [50000, "path/to/file.txt"], options=options, expected_stderr=expected_stderr)
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to