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)"