bug 563745 - Make automationutils.py's minidump processing able to send minidumps to minidump-stackwalk-cgi. r=catlee
authorTed Mielczarek <ted.mielczarek@gmail.com>
Thu, 06 May 2010 08:06:09 -0400
changeset 41990 8b482a58dd47a0c51c52d018ee0d0b8fccb5c657
parent 41989 ee0ba861b40953358d7b74782291927049a9e526
child 41991 dd9dc6d4bdb06341760d466aae45fc19b9bcd738
push idunknown
push userunknown
push dateunknown
reviewerscatlee
bugs563745
milestone1.9.3a5pre
bug 563745 - Make automationutils.py's minidump processing able to send minidumps to minidump-stackwalk-cgi. r=catlee
build/automationutils.py
build/poster.zip
layout/tools/reftest/Makefile.in
layout/tools/reftest/runreftest.py
testing/mochitest/Makefile.in
testing/mochitest/runtests.py.in
testing/xpcshell/Makefile.in
--- a/build/automationutils.py
+++ b/build/automationutils.py
@@ -33,21 +33,23 @@
 # and other provisions required by the GPL or the LGPL. If you do not delete
 # the provisions above, a recipient may use your version of this file under
 # the terms of any one of the MPL, the GPL or the LGPL.
 #
 # ***** END LICENSE BLOCK ***** */
 
 import glob, logging, os, shutil, subprocess, sys
 import re
+from urlparse import urlparse
 
 __all__ = [
   "addCommonOptions",
   "checkForCrashes",
   "dumpLeakLog",
+  "isURL",
   "processLeakLog",
   "getDebuggerInfo",
   "DEBUGGER_INFO",
   "replaceBackSlashes",
   ]
 
 # Map of debugging programs to information about them, like default arguments
 # and whether or not they are interactive.
@@ -64,66 +66,91 @@ DEBUGGER_INFO = {
   "valgrind": {
     "interactive": False,
     "args": "--leak-check=full"
   }
 }
 
 log = logging.getLogger()
 
+def isURL(thing):
+  """Return True if |thing| looks like a URL."""
+  return urlparse(thing).scheme != ''
+
 def addCommonOptions(parser, defaults={}):
   parser.add_option("--xre-path",
                     action = "store", type = "string", dest = "xrePath",
                     # individual scripts will set a sane default
                     default = None,
                     help = "absolute path to directory containing XRE (probably xulrunner)")
   if 'SYMBOLS_PATH' not in defaults:
     defaults['SYMBOLS_PATH'] = None
   parser.add_option("--symbols-path",
                     action = "store", type = "string", dest = "symbolsPath",
                     default = defaults['SYMBOLS_PATH'],
-                    help = "absolute path to directory containing breakpad symbols")
+                    help = "absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols")
   parser.add_option("--debugger",
                     action = "store", dest = "debugger",
                     help = "use the given debugger to launch the application")
   parser.add_option("--debugger-args",
                     action = "store", dest = "debuggerArgs",
                     help = "pass the given args to the debugger _before_ "
                            "the application on the command line")
   parser.add_option("--debugger-interactive",
                     action = "store_true", dest = "debuggerInteractive",
                     help = "prevents the test harness from redirecting "
                         "stdout and stderr for interactive debuggers")
 
 def checkForCrashes(dumpDir, symbolsPath, testName=None):
   stackwalkPath = os.environ.get('MINIDUMP_STACKWALK', None)
+  stackwalkCGI = os.environ.get('MINIDUMP_STACKWALK_CGI', None)
   # try to get the caller's filename if no test name is given
   if testName is None:
     try:
       testName = os.path.basename(sys._getframe(1).f_code.co_filename)
     except:
       testName = "unknown"
 
   foundCrash = False
   dumps = glob.glob(os.path.join(dumpDir, '*.dmp'))
   for d in dumps:
     log.info("PROCESS-CRASH | %s | application crashed (minidump found)", testName)
     if symbolsPath and stackwalkPath and os.path.exists(stackwalkPath):
       nullfd = open(os.devnull, 'w')
       # eat minidump_stackwalk errors
       subprocess.call([stackwalkPath, d, symbolsPath], stderr=nullfd)
       nullfd.close()
+    elif stackwalkCGI and symbolsPath and isURL(symbolsPath):
+      f = None
+      try:
+        f = open(d, "rb")
+        sys.path.append(os.path.join(os.path.dirname(__file__), "poster.zip"))
+        from poster.encode import multipart_encode
+        from poster.streaminghttp import register_openers
+        import urllib2
+        register_openers()
+        datagen, headers = multipart_encode({"minidump": f,
+                                             "symbols": symbolsPath})
+        request = urllib2.Request(stackwalkCGI, datagen, headers)
+        print urllib2.urlopen(request).read()
+      finally:
+        if f:
+          f.close()
     else:
       if not symbolsPath:
         print "No symbols path given, can't process dump."
-      if not stackwalkPath:
-        print "MINIDUMP_STACKWALK not set, can't process dump."
+      if not stackwalkPath and not stackwalkCGI:
+        print "Neither MINIDUMP_STACKWALK nor MINIDUMP_STACKWALK_CGI is set, can't process dump."
       else:
-        if not os.path.exists(stackwalkPath):
+        if stackwalkPath and not os.path.exists(stackwalkPath):
           print "MINIDUMP_STACKWALK binary not found: %s" % stackwalkPath
+        elif stackwalkCGI and not isURL(stackwalkCGI):
+          print "MINIDUMP_STACKWALK_CGI is not a URL: %s" % stackwalkCGI
+        elif symbolsPath and not isURL(symbolsPath):
+          print "symbolsPath is not a URL: %s" % symbolsPath
     dumpSavePath = os.environ.get('MINIDUMP_SAVE_PATH', None)
     if dumpSavePath:
       shutil.move(d, dumpSavePath)
       print "Saved dump as %s" % os.path.join(dumpSavePath,
                                               os.path.basename(d))
     else:
       os.remove(d)
     extra = os.path.splitext(d)[0] + ".extra"
new file mode 100644
index 0000000000000000000000000000000000000000..122b4acd4698a52d208293a904130c5310851ab9
GIT binary patch
literal 14900
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
--- a/layout/tools/reftest/Makefile.in
+++ b/layout/tools/reftest/Makefile.in
@@ -73,16 +73,17 @@ libs:: copy-harness
 endif
 
 _HARNESS_FILES = \
   $(srcdir)/runreftest.py \
   $(srcdir)/remotereftest.py \
   automation.py \
   $(topsrcdir)/build/mobile/devicemanager.py \
   $(topsrcdir)/build/automationutils.py \
+  $(topsrcdir)/build/poster.zip \
   $(NULL)
 
 $(_DEST_DIR):
 	$(NSINSTALL) -D $@
 
 $(_HARNESS_FILES): $(_DEST_DIR)
 
 # copy harness and the reftest extension bits to $(_DEST_DIR)
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -243,17 +243,17 @@ Are you executing $objdir/_tests/reftest
     sys.exit(1)
 
   if options.xrePath is None:
     options.xrePath = os.path.dirname(options.app)
   else:
     # allow relative paths
     options.xrePath = reftest.getFullPath(options.xrePath)
 
-  if options.symbolsPath:
+  if options.symbolsPath and not isURL(options.symbolsPath):
     options.symbolsPath = reftest.getFullPath(options.symbolsPath)
   options.utilityPath = reftest.getFullPath(options.utilityPath)
 
   if options.totalChunks is not None and options.thisChunk is None:
     print "thisChunk must be specified when totalChunks is specified"
     sys.exit(1)
 
   if options.totalChunks:
--- a/testing/mochitest/Makefile.in
+++ b/testing/mochitest/Makefile.in
@@ -59,16 +59,17 @@ include $(topsrcdir)/build/automation-bu
 
 # files that get copied into $objdir/_tests/
 _SERV_FILES = 	\
 		runtests.py \
 		automation.py \
 		runtestsremote.py \
 		$(topsrcdir)/build/mobile/devicemanager.py \
 		$(topsrcdir)/build/automationutils.py \
+		$(topsrcdir)/build/poster.zip \
 		gen_template.pl \
 		server.js \
 		harness-a11y.xul \
 		harness-overlay.xul \
 		harness.xul \
 		browser-test-overlay.xul \
 		browser-test.js \
 		browser-harness.xul \
--- a/testing/mochitest/runtests.py.in
+++ b/testing/mochitest/runtests.py.in
@@ -220,17 +220,16 @@ class MochitestOptions(optparse.OptionPa
     usage = """\
 Usage instructions for runtests.py.
 All arguments are optional.
 If --chrome is specified, chrome tests will be run instead of web content tests.
 If --browser-chrome is specified, browser-chrome tests will be run instead of web content tests.
 See <http://mochikit.com/doc/html/MochiKit/Logging.html> for details on the logging levels."""
     self.set_usage(usage)
 
-
   def verifyOptions(self, options, mochitest):
     """ verify correct options and cleanup paths """
 
     if options.totalChunks is not None and options.thisChunk is None:
       self.error("thisChunk must be specified when totalChunks is specified")
 
     if options.totalChunks:
       if not 1 <= options.thisChunk <= options.totalChunks:
@@ -255,17 +254,17 @@ See <http://mochikit.com/doc/html/MochiK
       msg = """\
       Error: Path %(app)s doesn't exist.
       Are you executing $objdir/_tests/testing/mochitest/runtests.py?"""
       print msg % {"app": options.app}
       return None
 
     options.utilityPath = mochitest.getFullPath(options.utilityPath)
     options.certPath = mochitest.getFullPath(options.certPath)
-    if options.symbolsPath:
+    if options.symbolsPath and not isURL(options.symbolsPath):
       options.symbolsPath = mochitest.getFullPath(options.symbolsPath)
 
     options.webServer = self._automation.DEFAULT_WEB_SERVER
     options.httpPort = self._automation.DEFAULT_HTTP_PORT
     options.sslPort = self._automation.DEFAULT_SSL_PORT
 
     if options.vmwareRecording:
       if not self._automation.IS_WIN32:
@@ -683,16 +682,16 @@ def main():
   options, args = parser.parse_args()
 
   options = parser.verifyOptions(options, mochitest)
   if options == None:
     sys.exit(1)
 
   options.utilityPath = mochitest.getFullPath(options.utilityPath)
   options.certPath = mochitest.getFullPath(options.certPath)
-  if options.symbolsPath:
+  if options.symbolsPath and not isURL(options.symbolsPath):
     options.symbolsPath = mochitest.getFullPath(options.symbolsPath)
 
   automation.setServerInfo(options.webServer, options.httpPort, options.sslPort)
   sys.exit(mochitest.runTests(options))
 
 if __name__ == "__main__":
   main()
--- a/testing/xpcshell/Makefile.in
+++ b/testing/xpcshell/Makefile.in
@@ -58,16 +58,17 @@ TEST_HARNESS_FILES := \
   runxpcshelltests.py \
   remotexpcshelltests.py \
   head.js \
   $(NULL)
 
 # Extra files needed from $(topsrcdir)/build
 EXTRA_BUILD_FILES := \
   automationutils.py \
+  poster.zip \
   $(NULL)
 
 # And files for running xpcshell remotely from $(topsrcdir)/build/mobile
 MOBILE_BUILD_FILES := \
   devicemanager.py \
   $(NULL)
 
 # Components / typelibs that don't get packaged with