Bug 808410 - Callers of checkForCrashes should use its return value to ensure shutdown crashes actually make the run fail; r=jmaher f=gps
authorEd Morley <emorley@mozilla.com>
Tue, 20 Nov 2012 15:24:28 +0000
changeset 113780 470669b03c2f8af132192e39ee976c7f4eefc57e
parent 113779 966b4616dfac55f5fd6910206bc7fe555fea7936
child 113781 5cdd053b27881e2ec35b2ba554511a20e24df31d
push id23890
push userryanvm@gmail.com
push dateWed, 21 Nov 2012 02:43:32 +0000
treeherdermozilla-central@4f19e7fd8bea [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmaher
bugs808410
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 808410 - Callers of checkForCrashes should use its return value to ensure shutdown crashes actually make the run fail; r=jmaher f=gps
build/automation.py.in
build/mobile/b2gautomation.py
build/mobile/remoteautomation.py
testing/xpcshell/runxpcshelltests.py
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -993,17 +993,17 @@ user_pref("camino.use_system_proxy_setti
 
       for processPID in processList:
         self.log.info("INFO | automation.py | Checking for orphan process with PID: %d", processPID)
         if self.isPidAlive(processPID):
           self.log.info("TEST-UNEXPECTED-FAIL | automation.py | child process %d still alive after shutdown", processPID)
           self.killPid(processPID)
 
   def checkForCrashes(self, profileDir, symbolsPath):
-    automationutils.checkForCrashes(os.path.join(profileDir, "minidumps"), symbolsPath, self.lastTestSeen)
+    return automationutils.checkForCrashes(os.path.join(profileDir, "minidumps"), symbolsPath, self.lastTestSeen)
 
   def runApp(self, testURL, env, app, profileDir, extraArgs,
              runSSLTunnel = False, utilityPath = None,
              xrePath = None, certPath = None,
              debuggerInfo = None, symbolsPath = None,
              timeout = -1, maxTime = None):
     """
     Run the app, log the duration it took to execute, return the status code.
@@ -1061,17 +1061,21 @@ user_pref("camino.use_system_proxy_setti
                  stderr = subprocess.STDOUT)
     self.log.info("INFO | automation.py | Application pid: %d", proc.pid)
 
     status = self.waitForFinish(proc, utilityPath, timeout, maxTime, startTime, debuggerInfo, symbolsPath)
     self.log.info("INFO | automation.py | Application ran for: %s", str(datetime.now() - startTime))
 
     # Do a final check for zombie child processes.
     self.checkForZombies(processLog)
-    self.checkForCrashes(profileDir, symbolsPath)
+
+    crashed = self.checkForCrashes(profileDir, symbolsPath)
+
+    if crashed:
+      status = 1
 
     if os.path.exists(processLog):
       os.unlink(processLog)
 
     if self.IS_TEST_BUILD and runSSLTunnel:
       ssltunnelProcess.kill()
 
     return status
--- a/build/mobile/b2gautomation.py
+++ b/build/mobile/b2gautomation.py
@@ -94,21 +94,22 @@ class B2GRemoteAutomation(Automation):
             time.sleep(1)
         return active
 
     def checkForCrashes(self, directory, symbolsPath):
         # XXX: This will have to be updated after crash reporting on b2g
         # is in place.
         dumpDir = tempfile.mkdtemp()
         self._devicemanager.getDirectory(self._remoteProfile + '/minidumps/', dumpDir)
-        automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
+        crashed = automationutils.checkForCrashes(dumpDir, symbolsPath, self.lastTestSeen)
         try:
           shutil.rmtree(dumpDir)
         except:
           print "WARNING: unable to remove directory: %s" % (dumpDir)
+        return crashed
 
     def initializeProfile(self, profileDir, extraPrefs = [], useServerLocations = False):
         # add b2g specific prefs
         extraPrefs.extend(["browser.manifestURL='dummy (bug 772307)'"])
         return Automation.initializeProfile(self, profileDir, extraPrefs, useServerLocations)
 
     def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
         # if remote profile is specified, use that instead
--- a/build/mobile/remoteautomation.py
+++ b/build/mobile/remoteautomation.py
@@ -80,31 +80,32 @@ class RemoteAutomation(Automation):
             print "TEST-UNEXPECTED-FAIL | %s | application ran for longer than " \
                   "allowed maximum time of %d seconds" % (self.lastTestSeen, int(maxTime))
             proc.kill()
 
         return status
 
     def checkForCrashes(self, directory, symbolsPath):
         remoteCrashDir = self._remoteProfile + '/minidumps/'
-        if self._devicemanager.dirExists(remoteCrashDir):
-            dumpDir = tempfile.mkdtemp()
-            self._devicemanager.getDirectory(remoteCrashDir, dumpDir)
-            automationutils.checkForCrashes(dumpDir, symbolsPath,
-                                            self.lastTestSeen)
-            try:
-                shutil.rmtree(dumpDir)
-            except:
-                print "WARNING: unable to remove directory: %s" % dumpDir
-        else:
+        if not self._devicemanager.dirExists(remoteCrashDir):
             # As of this writing, the minidumps directory is automatically
             # created when fennec (first) starts, so its lack of presence
             # is a hint that something went wrong.
-            print "WARNING: No crash directory (%s) on remote " \
-                "device" % remoteCrashDir
+            print "Automation Error: No crash directory (%s) found on remote device" % remoteCrashDir
+            # Whilst no crash was found, the run should still display as a failure
+            return True
+        dumpDir = tempfile.mkdtemp()
+        self._devicemanager.getDirectory(remoteCrashDir, dumpDir)
+        crashed = automationutils.checkForCrashes(dumpDir, symbolsPath,
+                                        self.lastTestSeen)
+        try:
+            shutil.rmtree(dumpDir)
+        except:
+            print "WARNING: unable to remove directory: %s" % dumpDir
+        return crashed
 
     def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
         # If remote profile is specified, use that instead
         if (self._remoteProfile):
             profileDir = self._remoteProfile
 
         # Hack for robocop, if app & testURL == None and extraArgs contains the rest of the stuff, lets
         # assume extraArgs is all we need
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -865,17 +865,26 @@ class XPCShellTests(object):
           xunitResult["passed"] = True
 
           if expected:
             self.passCount += 1
           else:
             self.todoCount += 1
             xunitResult["todo"] = True
 
-        checkForCrashes(testdir, self.symbolsPath, testName=name)
+        if checkForCrashes(testdir, self.symbolsPath, testName=name):
+          message = "PROCESS-CRASH | %s | application crashed" % name
+          self.failCount += 1
+          xunitResult["passed"] = False
+          xunitResult["failure"] = {
+            "type": "PROCESS-CRASH",
+            "message": message,
+            "text": stdout
+          }
+
         # Find child process(es) leak log(s), if any: See InitLog() in
         # xpcom/base/nsTraceRefcntImpl.cpp for logfile naming logic
         leakLogs = [self.leakLogFile]
         for childLog in glob(os.path.join(self.profileDir, "runxpcshelltests_leaks_*_pid*.log")):
           if os.path.isfile(childLog):
             leakLogs += [childLog]
         for log in leakLogs:
           dumpLeakLog(log, True)