bug 695274 - unit test timeouts on Mac should print a screenshot r=ted
authorJohn Ford <jhford@mozilla.com>
Fri, 21 Oct 2011 13:09:05 -0700
changeset 80125 a3b0534b657c3a4c5a2753960b0109bc7e92fdb9
parent 80124 b1818463edc1c1acf461eaf76641d84c1cf29a9d
child 80126 2cd25d4a839b2ebff011abbada4dddff3f71672b
push id506
push userclegnitto@mozilla.com
push dateWed, 09 Nov 2011 02:03:18 +0000
treeherdermozilla-aurora@63587fc7bb93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs695274
milestone10.0a1
bug 695274 - unit test timeouts on Mac should print a screenshot r=ted
build/automation.py.in
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -734,42 +734,66 @@ user_pref("camino.use_system_proxy_setti
         # and re-raise any others
         if err.errno == errno.ESRCH or err.errno == errno.ECHILD:
           return False
         raise
 
     def killPid(self, pid):
       os.kill(pid, signal.SIGKILL)
 
-  if UNIXISH:
     def dumpScreen(self, utilityPath):
       self.haveDumpedScreen = True;
 
-      screentopng = os.path.join(utilityPath, "screentopng")
+      # Need to figure out what tool and whether it write to a file or stdout
+      if UNIXISH:
+        utility = [os.path.join(utilityPath, "screentopng")]
+        imgoutput = 'stdout'
+      elif IS_MAC:
+        utility = ['/usr/sbin/screencapture', '-C', '-x', '-t', 'png']
+        imgoutput = 'file'
+      elif IS_WIN32:
+        self.log.info("If you fixed bug 589668, you'd get a screenshot here")
+        return
+
+      # Run the capture correctly for the type of capture
       try:
-        dumper = self.Process([screentopng], bufsize=-1,
-                              stdout=subprocess.PIPE, close_fds=True)
+        if imgoutput == 'file':
+          tmpfd, imgfilename = tempfile.mkstemp(prefix='mozilla-test-fail_')
+          os.close(tmpfd)
+          dumper = self.Process(utility + [imgfilename])
+        elif imgoutput == 'stdout':
+          dumper = self.Process(utility, bufsize=-1,
+                                stdout=subprocess.PIPE, close_fds=True)
       except OSError, err:
         self.log.info("Failed to start %s for screenshot: %s",
-                      screentopng, err.strerror)
+                      utility[0], err.strerror)
+        return
+
+      # Check whether the capture utility ran successfully
+      dumper_out, dumper_err = dumper.communicate()
+      if dumper.returncode != 0:
+        self.log.info("%s exited with code %d", utility, dumper.returncode)
         return
 
-      image = dumper.stdout.read()
-      status = dumper.wait()
-      if status != 0:
-        self.log.info("screentopng exited with code %d", status)
-        return
+      try:
+        if imgoutput == 'stdout':
+          image = dumper_out
+        elif imgoutput == 'file':
+          with open(imgfilename) as imgfile:
+            image = imgfile.read()
+      except IOError, err:
+          self.log.info("Failed to read image from %s", imgoutput)
 
       import base64
       encoded = base64.b64encode(image)
       self.log.info("SCREENSHOT: data:image/png;base64,%s", encoded)
 
   def killAndGetStack(self, proc, utilityPath, debuggerInfo):
     """Kill the process, preferrably in a way that gets us a stack trace."""
-    if self.UNIXISH and not debuggerInfo and not self.haveDumpedScreen:
+    if not debuggerInfo and not self.haveDumpedScreen:
       self.dumpScreen(utilityPath)
 
     if self.CRASHREPORTER and not debuggerInfo:
       if self.UNIXISH:
         # ABRT will get picked up by Breakpad's signal handler
         os.kill(proc.pid, signal.SIGABRT)
         return
       elif self.IS_WIN32:
@@ -815,17 +839,17 @@ user_pref("camino.use_system_proxy_setti
 
       (line, didTimeout) = self.readWithTimeout(logsource, timeout)
       while line != "" and not didTimeout:
         if "TEST-START" in line and "|" in line:
           self.lastTestSeen = line.split("|")[1].strip()
         if stackFixerFunction:
           line = stackFixerFunction(line)
         self.log.info(line.rstrip().decode("UTF-8", "ignore"))
-        if self.UNIXISH and not debuggerInfo and not self.haveDumpedScreen and "TEST-UNEXPECTED-FAIL" in line and "Test timed out" in line:
+        if not debuggerInfo and not self.haveDumpedScreen and "TEST-UNEXPECTED-FAIL" in line and "Test timed out" in line:
           self.dumpScreen(utilityPath)
 
         (line, didTimeout) = self.readWithTimeout(logsource, timeout)
         if not hitMaxTime and maxTime and datetime.now() - startTime > timedelta(seconds = maxTime):
           # Kill the application, but continue reading from stack fixer so as not to deadlock on stackFixerProcess.wait().
           hitMaxTime = True
           self.log.info("TEST-UNEXPECTED-FAIL | %s | application ran for longer than allowed maximum time of %d seconds", self.lastTestSeen, int(maxTime))
           self.killAndGetStack(proc, utilityPath, debuggerInfo)