[SCM] WebKit Debian packaging branch, webkit-1.3, updated. upstream/1.3.7-4207-g178b198

eric at webkit.org eric at webkit.org
Sun Feb 20 22:46:23 UTC 2011


The following commit has been merged in the webkit-1.3 branch:
commit db8ed3e67d53c6d0bb0c0fd83db9cd1a11007b70
Author: eric at webkit.org <eric at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Jan 11 10:36:36 2011 +0000

    2011-01-11  Eric Seidel  <eric at webkit.org>
    
            Reviewed by Adam Barth.
    
            commit-queue should know how to upload archived results (for test flakes or general failures)
            https://bugs.webkit.org/show_bug.cgi?id=52048
    
            Now the queue will always upload results.  Either the entire zip, or just
            the diffs.txt in the case of text failures.
    
            This should make understanding flakes much easier, and paves the way
            for having the EWS run layout tests (and upload failures).
    
            In order to upload .zip files I had to teach bugzilla.py to autodetect
            mime types from the filename.  Since mimetypes.py doesn't include a mapping
            for .patch files, I have it add one before calling guess_type.
    
            We may find that always uploading the whole zip instead of just the -diffs.txt
            file is preferable, but for now I'm keeping the old behavior because it makes
            quickly understanding text failures easy.
    
            * Scripts/webkitpy/common/net/bugzilla/bugzilla.py:
            * Scripts/webkitpy/common/system/workspace.py: Added.
            * Scripts/webkitpy/common/system/workspace_unittest.py: Added.
            * Scripts/webkitpy/tool/bot/commitqueuetask.py:
            * Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py:
            * Scripts/webkitpy/tool/bot/flakytestreporter.py:
            * Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py:
            * Scripts/webkitpy/tool/commands/queues.py:
            * Scripts/webkitpy/tool/commands/queues_unittest.py:
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@75480 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/Tools/ChangeLog b/Tools/ChangeLog
index 4c9e506..ab39509 100644
--- a/Tools/ChangeLog
+++ b/Tools/ChangeLog
@@ -1,3 +1,34 @@
+2011-01-11  Eric Seidel  <eric at webkit.org>
+
+        Reviewed by Adam Barth.
+
+        commit-queue should know how to upload archived results (for test flakes or general failures)
+        https://bugs.webkit.org/show_bug.cgi?id=52048
+
+        Now the queue will always upload results.  Either the entire zip, or just
+        the diffs.txt in the case of text failures.
+
+        This should make understanding flakes much easier, and paves the way
+        for having the EWS run layout tests (and upload failures).
+
+        In order to upload .zip files I had to teach bugzilla.py to autodetect
+        mime types from the filename.  Since mimetypes.py doesn't include a mapping
+        for .patch files, I have it add one before calling guess_type.
+
+        We may find that always uploading the whole zip instead of just the -diffs.txt
+        file is preferable, but for now I'm keeping the old behavior because it makes
+        quickly understanding text failures easy.
+
+        * Scripts/webkitpy/common/net/bugzilla/bugzilla.py:
+        * Scripts/webkitpy/common/system/workspace.py: Added.
+        * Scripts/webkitpy/common/system/workspace_unittest.py: Added.
+        * Scripts/webkitpy/tool/bot/commitqueuetask.py:
+        * Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py:
+        * Scripts/webkitpy/tool/bot/flakytestreporter.py:
+        * Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py:
+        * Scripts/webkitpy/tool/commands/queues.py:
+        * Scripts/webkitpy/tool/commands/queues_unittest.py:
+
 2011-01-10  Sheriff Bot  <webkit.review.bot at gmail.com>
 
         Unreviewed, rolling out r75464.
diff --git a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
index d6210d5..17a8515 100644
--- a/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
+++ b/Tools/Scripts/webkitpy/common/net/bugzilla/bugzilla.py
@@ -30,6 +30,7 @@
 #
 # WebKit's Python module for interacting with Bugzilla
 
+import mimetypes
 import os.path
 import re
 import StringIO
@@ -441,7 +442,11 @@ class Bugzilla(object):
         self.browser['flag_type-3'] = (self._commit_queue_flag(mark_for_landing, mark_for_commit_queue),)
 
         filename = filename or "%s.patch" % timestamp()
-        mimetype = mimetype or "text/plain"
+        if not mimetype:
+            mimetypes.add_type('text/plain', '.patch')  # Make sure mimetypes knows about .patch
+            mimetype, _ = mimetypes.guess_type(filename)
+        if not mimetype:
+            mimetype = "text/plain"  # Bugzilla might auto-guess for us and we might not need this?
         self.browser.add_file(file_object, mimetype, filename, 'data')
 
     def _file_object_for_upload(self, file_or_string):
diff --git a/Tools/Scripts/webkitpy/common/system/workspace.py b/Tools/Scripts/webkitpy/common/system/workspace.py
new file mode 100644
index 0000000..4126053
--- /dev/null
+++ b/Tools/Scripts/webkitpy/common/system/workspace.py
@@ -0,0 +1,59 @@
+# 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.
+
+# A home for file logic which should sit above FileSystem, but
+# below more complicated objects.
+
+
+class Workspace(object):
+    def __init__(self, filesystem, executive):
+        self._filesystem = filesystem
+        self._executive = executive  # FIXME: Remove if create_zip is moved to python.
+
+    def find_unused_filename(self, directory, name, extension, search_limit=10):
+        for count in range(search_limit):
+            if count:
+                target_name = "%s-%s.%s" % (name, count, extension)
+            else:
+                target_name = "%s.%s" % (name, extension)
+            target_path = self._filesystem.join(directory, target_name)
+            if not self._filesystem.exists(target_path):
+                return target_path
+        # If we can't find an unused name in search_limit tries, just give up.
+        return None
+
+    def create_zip(self, zip_path, source_path):
+        # It's possible to create zips with Python:
+        # zip_file = ZipFile(zip_path, 'w')
+        # for root, dirs, files in os.walk(source_path):
+        #     for path in files:
+        #         absolute_path = os.path.join(root, path)
+        #         zip_file.write(os.path.relpath(path, source_path))
+        # However, getting the paths, encoding and compression correct could be non-trivial.
+        # So, for now we depend on the environment having "zip" installed (likely fails on Win32)
+        self._executive.run_command(['zip', zip_path, source_path])
diff --git a/Tools/Scripts/webkitpy/common/system/workspace_unittest.py b/Tools/Scripts/webkitpy/common/system/workspace_unittest.py
new file mode 100644
index 0000000..6348e83
--- /dev/null
+++ b/Tools/Scripts/webkitpy/common/system/workspace_unittest.py
@@ -0,0 +1,51 @@
+# 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.common.system.filesystem_mock import MockFileSystem
+from webkitpy.common.system.outputcapture import OutputCapture
+from webkitpy.common.system.workspace import Workspace
+from webkitpy.tool.mocktool import MockExecutive
+
+
+class WorkspaceTest(unittest.TestCase):
+
+    def test_find_unused_filename(self):
+        filesystem = MockFileSystem({
+            "dir/foo.jpg": "",
+            "dir/foo-1.jpg": "",
+        })
+        workspace = Workspace(filesystem, None)
+        self.assertEqual(workspace.find_unused_filename("bar", "bar", "bar"), "bar/bar.bar")
+        self.assertEqual(workspace.find_unused_filename("dir", "foo", "jpg"), "dir/foo-2.jpg")
+
+    def test_create_zip(self):
+        workspace = Workspace(None, MockExecutive(should_log=True))
+        expected_stderr = "MOCK run_command: ['zip', '/zip/path', '/source/path']\n"
+        OutputCapture().assert_outputs(self, workspace.create_zip, ["/zip/path", "/source/path"], expected_stderr=expected_stderr)
diff --git a/Tools/Scripts/webkitpy/tool/bot/commitqueuetask.py b/Tools/Scripts/webkitpy/tool/bot/commitqueuetask.py
index f99267a..3be2556 100644
--- a/Tools/Scripts/webkitpy/tool/bot/commitqueuetask.py
+++ b/Tools/Scripts/webkitpy/tool/bot/commitqueuetask.py
@@ -46,7 +46,11 @@ class CommitQueueTaskDelegate(object):
     def layout_test_results(self):
         raise NotImplementedError("subclasses must implement")
 
-    def report_flaky_tests(self, patch, flaky_tests):
+    def archive_last_layout_test_results(self, patch):
+        raise NotImplementedError("subclasses must implement")
+
+    # We could make results_archive optional, but for now it's required.
+    def report_flaky_tests(self, patch, flaky_tests, results_archive):
         raise NotImplementedError("subclasses must implement")
 
 
@@ -170,8 +174,8 @@ class CommitQueueTask(object):
         "Landed patch",
         "Unable to land patch")
 
-    def _report_flaky_tests(self, flaky_test_results):
-        self._delegate.report_flaky_tests(self._patch, flaky_test_results)
+    def _report_flaky_tests(self, flaky_test_results, results_archive):
+        self._delegate.report_flaky_tests(self._patch, flaky_test_results, results_archive)
 
     def _test_patch(self):
         if self._patch.is_rollout():
@@ -179,14 +183,15 @@ class CommitQueueTask(object):
         if self._test():
             return True
 
-        first_failing_results = self._failing_results_from_last_run()
-        first_failing_tests = [result.filename for result in first_failing_results]
+        first_results = self._failing_results_from_last_run()
+        first_failing_tests = [result.filename for result in first_results]
+        first_results_archive = self._delegate.archive_last_layout_test_results(self._patch)
         if self._test():
-            self._report_flaky_tests(first_failing_results)
+            self._report_flaky_tests(first_results, first_results_archive)
             return True
 
-        second_failing_results = self._failing_results_from_last_run()
-        second_failing_tests = [result.filename for result in second_failing_results]
+        second_results = self._failing_results_from_last_run()
+        second_failing_tests = [result.filename for result in second_results]
         if first_failing_tests != second_failing_tests:
             # We could report flaky tests here, but since run-webkit-tests
             # is run with --exit-after-N-failures=1, we would need to
diff --git a/Tools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py b/Tools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py
index d70c32b..26231ae 100644
--- a/Tools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py
+++ b/Tools/Scripts/webkitpy/tool/bot/commitqueuetask_unittest.py
@@ -65,9 +65,15 @@ class MockCommitQueue(CommitQueueTaskDelegate):
     def layout_test_results(self):
         return None
 
-    def report_flaky_tests(self, patch, flaky_results):
+    def report_flaky_tests(self, patch, flaky_results, results_archive):
         flaky_tests = [result.filename for result in flaky_results]
-        log("report_flaky_tests: patch='%s' flaky_tests='%s'" % (patch.id(), flaky_tests))
+        log("report_flaky_tests: patch='%s' flaky_tests='%s' archive='%s'" % (patch.id(), flaky_tests, results_archive.filename))
+
+    def archive_last_layout_test_results(self, patch):
+        log("archive_last_layout_test_results: patch='%s'" % patch.id())
+        archive = Mock()
+        archive.filename = "mock-archive-%s.zip" % patch.id()
+        return archive
 
 
 class CommitQueueTaskTest(unittest.TestCase):
@@ -194,9 +200,10 @@ 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'
+archive_last_layout_test_results: 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='[]'
+report_flaky_tests: patch='197' flaky_tests='[]' archive='mock-archive-197.zip'
 run_webkit_patch: ['land-attachment', '--force-clean', '--ignore-builders', '--non-interactive', '--parent-command=commit-queue', 197]
 command_passed: success_message='Landed patch' patch='197'
 """
@@ -226,6 +233,7 @@ 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'
+archive_last_layout_test_results: 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'
 """
@@ -263,6 +271,7 @@ 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'
+archive_last_layout_test_results: 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']
@@ -290,6 +299,7 @@ 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'
+archive_last_layout_test_results: 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']
diff --git a/Tools/Scripts/webkitpy/tool/bot/flakytestreporter.py b/Tools/Scripts/webkitpy/tool/bot/flakytestreporter.py
index 91fcb85..69a74d1 100644
--- a/Tools/Scripts/webkitpy/tool/bot/flakytestreporter.py
+++ b/Tools/Scripts/webkitpy/tool/bot/flakytestreporter.py
@@ -131,13 +131,10 @@ If you would like to track this test fix with another bug, please close this bug
         flake_message = "The %s just saw %s flake (%s) while processing attachment %s on bug %s." % (self._bot_name, flaky_result.filename, ", ".join(failure_messages), patch.id(), patch.bug_id())
         return "%s\n%s" % (flake_message, self._bot_information())
 
-    def _results_diff_path_for_test(self, flaky_test):
+    def _results_diff_path_for_test(self, test_path):
         # FIXME: This is a big hack.  We should get this path from results.json
         # except that old-run-webkit-tests doesn't produce a results.json
         # so we just guess at the file path.
-        results_path = self._tool.port().layout_tests_results_path()
-        results_directory = os.path.dirname(results_path)
-        test_path = os.path.join(results_directory, flaky_test)
         (test_path_root, _) = os.path.splitext(test_path)
         return "%s-diffs.txt" % test_path_root
 
@@ -153,7 +150,23 @@ If you would like to track this test fix with another bug, please close this bug
         else:
             self._tool.bugs.post_comment_to_bug(bug.id(), latest_flake_message)
 
-    def report_flaky_tests(self, flaky_test_results, patch):
+    def _attach_failure_diff(self, flake_bug_id, flaky_test, results_archive):
+        results_diff_path = self._results_diff_path_for_test(flaky_test)
+        # Check to make sure that the path makes sense.
+        # Since we're not actually getting this path from the results.html
+        # there is a chance it's wrong.
+        bot_id = self._tool.status_server.bot_id or "bot"
+        if results_diff_path in results_archive.namelist():
+            results_diff = results_archive.read(results_diff_path)
+            description = "Failure diff from %s" % bot_id
+            self._tool.bugs.add_attachment_to_bug(flake_bug_id, results_diff, description, filename="failure.diff")
+        else:
+            _log.warn("%s does not exist in results archive, uploading entire archive." % results_diff_path)
+            description = "Archive of layout-test-results from %s" % bot_id
+            # results_archive is a ZipFile object, grab the File object (.fp) to pass to Mechanize for uploading.
+            self._tool.bugs.add_attachment_to_bug(flake_bug_id, results_archive.fp, description, filename="layout-test-results.zip")
+
+    def report_flaky_tests(self, patch, flaky_test_results, results_archive):
         message = "The %s encountered the following flaky tests while processing attachment %s:\n\n" % (self._bot_name, patch.id())
         for flaky_result in flaky_test_results:
             flaky_test = flaky_result.filename
@@ -165,20 +178,12 @@ If you would like to track this test fix with another bug, please close this bug
                 flake_bug_id = self._create_bug_for_flaky_test(flaky_test, author_emails, latest_flake_message)
             else:
                 bug = self._follow_duplicate_chain(bug)
+                # FIXME: Ideally we'd only make one comment per flake, not two.  But that's not possible
+                # in all cases (e.g. when reopening), so for now file attachment and comment are separate.
                 self._update_bug_for_flaky_test(bug, latest_flake_message)
                 flake_bug_id = bug.id()
-            # FIXME: Ideally we'd only make one comment per flake, not two.  But that's not possible
-            # in all cases (e.g. when reopening), so for now we do the attachment in a second step.
-            results_diff_path = self._results_diff_path_for_test(flaky_test)
-            # Check to make sure that the path makes sense.
-            # Since we're not actually getting this path from the results.html
-            # there is a high probaility it's totally wrong.
-            if self._tool.filesystem.exists(results_diff_path):
-                results_diff = self._tool.filesystem.read_binary_file(results_diff_path)
-                bot_id = self._tool.status_server.bot_id or "bot"
-                self._tool.bugs.add_attachment_to_bug(flake_bug_id, results_diff, "Failure diff from %s" % bot_id, filename="failure.diff")
-            else:
-                _log.error("%s does not exist as expected, not uploading." % results_diff_path)
+
+            self._attach_failure_diff(flake_bug_id, flaky_test, results_archive)
             message += "%s bug %s%s\n" % (flaky_test, flake_bug_id, self._optional_author_string(author_emails))
 
         message += "The %s is continuing to process your patch." % self._bot_name
diff --git a/Tools/Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py b/Tools/Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py
index 631f8d1..6635e60 100644
--- a/Tools/Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py
+++ b/Tools/Scripts/webkitpy/tool/bot/flakytestreporter_unittest.py
@@ -33,6 +33,7 @@ from webkitpy.common.system.filesystem_mock import MockFileSystem
 from webkitpy.common.system.outputcapture import OutputCapture
 from webkitpy.layout_tests.layout_package import test_results
 from webkitpy.layout_tests.layout_package import test_failures
+from webkitpy.thirdparty.mock import Mock
 from webkitpy.tool.bot.flakytestreporter import FlakyTestReporter
 from webkitpy.tool.mocktool import MockTool, MockStatusServer
 
@@ -140,7 +141,15 @@ The dummy-queue is continuing to process your patch.
 
 """
         test_results = [self._mock_test_result('foo/bar.html')]
-        OutputCapture().assert_outputs(self, reporter.report_flaky_tests, [test_results, patch], expected_stderr=expected_stderr)
+
+        class MockZipFile(object):
+            def read(self, path):
+                return ""
+
+            def namelist(self):
+                return ['foo/bar-diffs.txt']
+
+        OutputCapture().assert_outputs(self, reporter.report_flaky_tests, [patch, test_results, MockZipFile()], expected_stderr=expected_stderr)
 
     def test_optional_author_string(self):
         reporter = FlakyTestReporter(MockTool(), 'dummy-queue')
@@ -150,6 +159,6 @@ The dummy-queue is continuing to process your patch.
 
     def test_results_diff_path_for_test(self):
         reporter = FlakyTestReporter(MockTool(), 'dummy-queue')
-        self.assertEqual(reporter._results_diff_path_for_test("test.html"), "/mock/test-diffs.txt")
+        self.assertEqual(reporter._results_diff_path_for_test("test.html"), "test-diffs.txt")
 
     # report_flaky_tests is also tested by queues_unittest
diff --git a/Tools/Scripts/webkitpy/tool/commands/queues.py b/Tools/Scripts/webkitpy/tool/commands/queues.py
index 5628543..62a8096 100644
--- a/Tools/Scripts/webkitpy/tool/commands/queues.py
+++ b/Tools/Scripts/webkitpy/tool/commands/queues.py
@@ -309,12 +309,29 @@ class CommitQueue(AbstractPatchQueue, StepSequenceErrorHandler, CommitQueueTaskD
             return None
         return LayoutTestResults.results_from_string(results_html)
 
+    def _results_directory(self):
+        results_path = self._tool.port().layout_tests_results_path()
+        # FIXME: This is wrong in two ways:
+        # 1. It assumes that results.html is at the top level of the results tree.
+        # 2. This uses the "old" ports.py infrastructure instead of the new layout_tests/port
+        # which will not support Chromium.  However the new arch doesn't work with old-run-webkit-tests
+        # so we have to use this for now.
+        return os.path.dirname(results_path)
+
+    def archive_last_layout_test_results(self, patch):
+        results_directory = self._results_directory()
+        results_name, _ = os.path.splitext(os.path.basename(results_directory))
+        # Note: We name the zip with the bug_id instead of patch_id to match work_item_log_path().
+        zip_path = self._tool.workspace.find_unused_filename(self._log_directory(), "%s-%s" % (patch.bug_id(), results_name), "zip")
+        self._tool.workspace.create_zip(zip_path, results_directory)
+        return zip_path
+
     def refetch_patch(self, patch):
         return self._tool.bugs.fetch_attachment(patch.id())
 
-    def report_flaky_tests(self, patch, flaky_test_results):
+    def report_flaky_tests(self, patch, flaky_test_results, results_archive=None):
         reporter = FlakyTestReporter(self._tool, self.name)
-        reporter.report_flaky_tests(flaky_test_results, patch)
+        reporter.report_flaky_tests(patch, flaky_test_results, results_archive)
 
     # StepSequenceErrorHandler methods
 
diff --git a/Tools/Scripts/webkitpy/tool/commands/queues_unittest.py b/Tools/Scripts/webkitpy/tool/commands/queues_unittest.py
index 34a6a64..8f5c9e6 100644
--- a/Tools/Scripts/webkitpy/tool/commands/queues_unittest.py
+++ b/Tools/Scripts/webkitpy/tool/commands/queues_unittest.py
@@ -27,9 +27,11 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import os
+import StringIO
 
 from webkitpy.common.checkout.scm import CheckoutNeedsUpdate
 from webkitpy.common.net.bugzilla import Attachment
+from webkitpy.common.system.filesystem_mock import MockFileSystem
 from webkitpy.common.system.outputcapture import OutputCapture
 from webkitpy.layout_tests.layout_package import test_results
 from webkitpy.layout_tests.layout_package import test_failures
@@ -342,12 +344,14 @@ The commit-queue just saw foo/bar.html flake (Text diff mismatch) while processi
 Port: MockPort  Platform: MockPlatform 1.0
 --- End comment ---
 
+MOCK add_attachment_to_bug: bug_id=76, description=Failure diff from bot filename=failure.diff
 MOCK bug comment: bug_id=76, cc=None
 --- Begin comment ---
 The commit-queue just saw bar/baz.html flake (Text diff mismatch) while processing attachment 197 on bug 42.
 Port: MockPort  Platform: MockPlatform 1.0
 --- End comment ---
 
+MOCK add_attachment_to_bug: bug_id=76, description=Archive of layout-test-results from bot filename=layout-test-results.zip
 MOCK bug comment: bug_id=42, cc=None
 --- Begin comment ---
 The commit-queue encountered the following flaky tests while processing attachment 197:
@@ -360,7 +364,19 @@ The commit-queue is continuing to process your patch.
 """
         test_names = ["foo/bar.html", "bar/baz.html"]
         test_results = [self._mock_test_result(name) for name in test_names]
-        OutputCapture().assert_outputs(self, queue.report_flaky_tests, [QueuesTest.mock_work_item, test_results], expected_stderr=expected_stderr)
+
+        class MockZipFile(object):
+            def __init__(self):
+                self.fp = StringIO()
+
+            def read(self, path):
+                return ""
+
+            def namelist(self):
+                # This is intentionally missing one diffs.txt to exercise the "upload the whole zip" codepath.
+                return ['foo/bar-diffs.txt']
+
+        OutputCapture().assert_outputs(self, queue.report_flaky_tests, [QueuesTest.mock_work_item, test_results, MockZipFile()], expected_stderr=expected_stderr)
 
     def test_layout_test_results(self):
         queue = CommitQueue()
@@ -370,6 +386,12 @@ The commit-queue is continuing to process your patch.
         queue._read_file_contents = lambda path: ""
         self.assertEquals(queue.layout_test_results(), None)
 
+    def test_archive_last_layout_test_results(self):
+        queue = CommitQueue()
+        queue.bind_to_tool(MockTool())
+        patch = queue._tool.bugs.fetch_attachment(128)
+        queue.archive_last_layout_test_results(patch)
+
 
 class StyleQueueTest(QueuesTest):
     def test_style_queue(self):
diff --git a/Tools/Scripts/webkitpy/tool/main.py b/Tools/Scripts/webkitpy/tool/main.py
index 0006e87..cad5a2a 100755
--- a/Tools/Scripts/webkitpy/tool/main.py
+++ b/Tools/Scripts/webkitpy/tool/main.py
@@ -40,10 +40,7 @@ from webkitpy.common.net.bugzilla import Bugzilla
 from webkitpy.common.net.buildbot import BuildBot
 from webkitpy.common.net.irc.ircproxy import IRCProxy
 from webkitpy.common.net.statusserver import StatusServer
-from webkitpy.common.system.executive import Executive
-from webkitpy.common.system.filesystem import FileSystem
-from webkitpy.common.system.platforminfo import PlatformInfo
-from webkitpy.common.system.user import User
+from webkitpy.common.system import executive, filesystem, platforminfo, user, workspace
 from webkitpy.layout_tests import port
 from webkitpy.tool.multicommandtool import MultiCommandTool
 import webkitpy.tool.commands as commands
@@ -70,16 +67,17 @@ class WebKitPatch(MultiCommandTool):
         # manual getter functions (e.g. scm()).
         self.bugs = Bugzilla()
         self.buildbot = BuildBot()
-        self.executive = Executive()
+        self.executive = executive.Executive()
         self._irc = None
-        self.filesystem = FileSystem()
+        self.filesystem = filesystem.FileSystem()
+        self.workspace = workspace.Workspace(self.filesystem, self.executive)
         self._port = None
-        self.user = User()
+        self.user = user.User()
         self._scm = None
         self._checkout = None
         self.status_server = StatusServer()
         self.port_factory = port.factory
-        self.platform = PlatformInfo()
+        self.platform = platforminfo.PlatformInfo()
 
     def scm(self):
         # Lazily initialize SCM to not error-out before command line parsing (or when running non-scm commands).
diff --git a/Tools/Scripts/webkitpy/tool/mocktool.py b/Tools/Scripts/webkitpy/tool/mocktool.py
index eb7c248..d8c8ff0 100644
--- a/Tools/Scripts/webkitpy/tool/mocktool.py
+++ b/Tools/Scripts/webkitpy/tool/mocktool.py
@@ -686,6 +686,14 @@ class MockPlatformInfo(object):
         return "MockPlatform 1.0"
 
 
+class MockWorkspace(object):
+    def find_unused_filename(self, directory, name, extension, search_limit=10):
+        return "%s/%s.%s" % (directory, name, extension)
+
+    def create_zip(self, zip_path, source_path):
+        pass
+
+
 class MockTool(object):
 
     def __init__(self, log_executive=False):
@@ -694,6 +702,7 @@ class MockTool(object):
         self.buildbot = MockBuildBot()
         self.executive = MockExecutive(should_log=log_executive)
         self.filesystem = MockFileSystem()
+        self.workspace = MockWorkspace()
         self._irc = None
         self.user = MockUser()
         self._scm = MockSCM()

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list