Title: [89843] trunk/Tools
Revision
89843
Author
[email protected]
Date
2011-06-27 11:47:44 -0700 (Mon, 27 Jun 2011)

Log Message

2011-06-27  Adam Barth  <[email protected]>

        Reviewed by Eric Seidel.

        webkitpy should understand crash logs
        https://bugs.webkit.org/show_bug.cgi?id=63468

        We're planning to use this functionality to upload crash logs along
        with test results for new-run-webkit-tests.

        * Scripts/webkitpy/common/system/crashlog.py: Added.
        * Scripts/webkitpy/common/system/crashlog_unittest.py: Added.
        * Scripts/webkitpy/common/system/executive.py:
        * Scripts/webkitpy/common/system/executive_unittest.py:
        * Scripts/webkitpy/common/system/filesystem.py:
        * Scripts/webkitpy/common/system/filesystem_mock.py:
        * Scripts/webkitpy/tool/commands/queries.py:

Modified Paths

Added Paths

Diff

Modified: trunk/Tools/ChangeLog (89842 => 89843)


--- trunk/Tools/ChangeLog	2011-06-27 18:40:18 UTC (rev 89842)
+++ trunk/Tools/ChangeLog	2011-06-27 18:47:44 UTC (rev 89843)
@@ -1,3 +1,21 @@
+2011-06-27  Adam Barth  <[email protected]>
+
+        Reviewed by Eric Seidel.
+
+        webkitpy should understand crash logs
+        https://bugs.webkit.org/show_bug.cgi?id=63468
+
+        We're planning to use this functionality to upload crash logs along
+        with test results for new-run-webkit-tests.
+
+        * Scripts/webkitpy/common/system/crashlog.py: Added.
+        * Scripts/webkitpy/common/system/crashlog_unittest.py: Added.
+        * Scripts/webkitpy/common/system/executive.py:
+        * Scripts/webkitpy/common/system/executive_unittest.py:
+        * Scripts/webkitpy/common/system/filesystem.py:
+        * Scripts/webkitpy/common/system/filesystem_mock.py:
+        * Scripts/webkitpy/tool/commands/queries.py:
+
 2011-06-27  Adam Roben  <[email protected]>
 
         Make LayoutTestResultsLoader cache whether old-run-webkit-tests exited early due to too many

Added: trunk/Tools/Scripts/webkitpy/common/system/crashlogs.py (0 => 89843)


--- trunk/Tools/Scripts/webkitpy/common/system/crashlogs.py	                        (rev 0)
+++ trunk/Tools/Scripts/webkitpy/common/system/crashlogs.py	2011-06-27 18:47:44 UTC (rev 89843)
@@ -0,0 +1,66 @@
+# Copyright (c) 2011, 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 re
+import sys
+
+
+def _is_crash_reporter(process_name):
+    return re.match(r"ReportCrash", process_name)
+
+
+class CrashLogs(object):
+    def __init__(self, executive, filesystem):
+        self._executive = executive
+        self._filesystem = filesystem
+
+    def find_newest_log(self, process_name):
+        if sys.platform == "darwin":
+            return self._find_newest_log_darwin(process_name)
+
+    def _log_directory_darwin(self):
+        log_directory = self._filesystem.expanduser("~")
+        log_directory = os.path.join(log_directory, "Library", "Logs")
+        if self._filesystem.exists(os.path.join(log_directory, "DiagnosticReports")):
+            log_directory = os.path.join(log_directory, "DiagnosticReports")
+        else:
+            log_directory = os.path.join(log_directory, "CrashReporter")
+        return log_directory
+
+    def _find_newest_log_darwin(self, process_name):
+        def is_crash_log(fs, dirpath, basename):
+            return basename.startswith(process_name + "_") and basename.endswith(".crash")
+
+        log_directory = self._log_directory_darwin()
+        logs = self._filesystem.files_under(log_directory, file_filter=is_crash_log)
+        if not logs:
+            return
+
+        self._executive.wait_newest(_is_crash_reporter)
+        return self._filesystem.read_text_file(sorted(logs)[-1])

Added: trunk/Tools/Scripts/webkitpy/common/system/crashlogs_unittest.py (0 => 89843)


--- trunk/Tools/Scripts/webkitpy/common/system/crashlogs_unittest.py	                        (rev 0)
+++ trunk/Tools/Scripts/webkitpy/common/system/crashlogs_unittest.py	2011-06-27 18:47:44 UTC (rev 89843)
@@ -0,0 +1,42 @@
+# Copyright (C) 2011 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:
+#
+# 1.  Redistributions of source code must retain the above copyright
+#     notice, this list of conditions and the following disclaimer.
+# 2.  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.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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 sys
+
+from webkitpy.common.system.crashlogs import *
+from webkitpy.common.system.filesystem_mock import MockFileSystem
+from webkitpy.thirdparty.mock import Mock
+
+
+class CrashLogsTest(unittest.TestCase):
+    def test_find_log_darwin(self):
+        if sys.platform != "darwin":
+            return
+        mock_crash_report = "Mock Crash Report"
+        files = {}
+        files['/Users/mock/Library/Logs/DiagnosticReports/TextMate_2011-06-13-150719_quadzen.crash'] = mock_crash_report
+        filesystem = MockFileSystem(files)
+        crash_logs = CrashLogs(Mock(), filesystem)
+        log = crash_logs.find_newest_log("TextMate")
+        self.assertTrue(log, mock_crash_report)

Modified: trunk/Tools/Scripts/webkitpy/common/system/executive.py (89842 => 89843)


--- trunk/Tools/Scripts/webkitpy/common/system/executive.py	2011-06-27 18:40:18 UTC (rev 89842)
+++ trunk/Tools/Scripts/webkitpy/common/system/executive.py	2011-06-27 18:47:44 UTC (rev 89843)
@@ -289,6 +289,39 @@
 
         assert(False)
 
+    def running_pids(self, process_name_filter=None):
+        if not process_name_filter:
+            process_name_filter = lambda process_name: True
+
+        running_pids = []
+
+        if sys.platform in ("win32", "cygwin"):
+            raise NotImplemented()
+
+        ps_process = self.popen(['ps', '-eo', 'pid,comm'], stdout=self.PIPE, stderr=self.PIPE)
+        stdout, _ = ps_process.communicate()
+        for line in stdout.splitlines():
+            try:
+                pid, process_name = line.split(' ', 1)
+                if process_name_filter(process_name):
+                    running_pids.append(int(pid))
+            except ValueError, e:
+                pass
+
+        return sorted(running_pids)
+
+    def wait_newest(self, process_name_filter=None):
+        if not process_name_filter:
+            process_name_filter = lambda process_name: True
+
+        running_pids = self.running_pids(process_name_filter)
+        if not running_pids:
+            return
+        pid = running_pids[-1]
+
+        while self.check_running_pid(pid):
+            time.sleep(0.25)
+
     def _windows_image_name(self, process_name):
         name, extension = os.path.splitext(process_name)
         if not extension:

Modified: trunk/Tools/Scripts/webkitpy/common/system/executive_unittest.py (89842 => 89843)


--- trunk/Tools/Scripts/webkitpy/common/system/executive_unittest.py	2011-06-27 18:40:18 UTC (rev 89842)
+++ trunk/Tools/Scripts/webkitpy/common/system/executive_unittest.py	2011-06-27 18:47:44 UTC (rev 89843)
@@ -199,3 +199,11 @@
         self.assertTrue(executive.check_running_pid(os.getpid()))
         # Maximum pid number on Linux is 32768 by default
         self.assertFalse(executive.check_running_pid(100000))
+
+    def test_running_pids(self):
+        if sys.platform in ("win32", "cygwin"):
+            return  # This function isn't implemented on Windows yet.
+
+        executive = Executive()
+        pids = executive.running_pids()
+        self.assertTrue(os.getpid() in pids)

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


--- trunk/Tools/Scripts/webkitpy/common/system/filesystem.py	2011-06-27 18:40:18 UTC (rev 89842)
+++ trunk/Tools/Scripts/webkitpy/common/system/filesystem.py	2011-06-27 18:47:44 UTC (rev 89843)
@@ -57,12 +57,13 @@
     def abspath(self, path):
         return os.path.abspath(path)
 
+    def expanduser(self, path):
+        return os.path.expanduser(path)
+
     def basename(self, path):
-        """Wraps os.path.basename()."""
         return os.path.basename(path)
 
     def chdir(self, path):
-        """Wraps os.chdir()."""
         return os.chdir(path)
 
     def copyfile(self, source, destination):

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


--- trunk/Tools/Scripts/webkitpy/common/system/filesystem_mock.py	2011-06-27 18:40:18 UTC (rev 89842)
+++ trunk/Tools/Scripts/webkitpy/common/system/filesystem_mock.py	2011-06-27 18:47:44 UTC (rev 89843)
@@ -70,6 +70,15 @@
     def basename(self, path):
         return self._split(path)[1]
 
+    def expanduser(self, path):
+        if path[0] != "~":
+            return path
+        parts = path.split(self.sep, 1)
+        home_directory = self.sep + "Users" + self.sep + "mock"
+        if len(parts) == 1:
+            return home_directory
+        return home_directory + self.sep + parts[1]
+
     def chdir(self, path):
         path = self.normpath(path)
         if not self.isdir(path):

Modified: trunk/Tools/Scripts/webkitpy/tool/commands/queries.py (89842 => 89843)


--- trunk/Tools/Scripts/webkitpy/tool/commands/queries.py	2011-06-27 18:40:18 UTC (rev 89842)
+++ trunk/Tools/Scripts/webkitpy/tool/commands/queries.py	2011-06-27 18:47:44 UTC (rev 89843)
@@ -36,13 +36,13 @@
 from webkitpy.common.config.committers import CommitterList
 from webkitpy.common.net.buildbot import BuildBot
 from webkitpy.common.net.regressionwindow import RegressionWindow
+from webkitpy.common.system.crashlogs import CrashLogs
 from webkitpy.common.system.user import User
 from webkitpy.tool.grammar import pluralize
 from webkitpy.tool.multicommandtool import AbstractDeclarativeCommand
 from webkitpy.common.system.deprecated_logging import log
 from webkitpy.layout_tests import port
 
-
 class SuggestReviewers(AbstractDeclarativeCommand):
     name = "suggest-reviewers"
     help_text = "Suggest reviewers for a patch based on recent changes to the modified files."
@@ -368,6 +368,15 @@
             print "%s : %s" % (status_string.ljust(4), builder["name"])
 
 
+class CrashLog(AbstractDeclarativeCommand):
+    name = "crash-log"
+    argument_names = "PROCESS_NAME"
+
+    def execute(self, options, args, tool):
+        crash_logs = CrashLogs(tool.executive, tool.filesystem)
+        print crash_logs.find_newest_log(args[0])
+
+
 class SkippedPorts(AbstractDeclarativeCommand):
     name = "skipped-ports"
     help_text = "Print the list of ports skipping the given layout test(s)"
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to