Bug 812514 - Make b2g emulator unittests save logcat for easier debugging, r=jgriffin, a=NPOTB,test-only
authorAndrew Halberstadt <ahalberstadt@mozilla.com>
Tue, 20 Nov 2012 13:29:30 -0500
changeset 117026 80afbd9cf1e53727f80b97a528ad9abe430cdb6f
parent 117025 0465c9eba02b41e540fd04bfe3b6046f00151971
child 117027 9e7aeb6be40a95f4b2ac96f27132c72f794408ac
push id1716
push userahalberstadt@mozilla.com
push dateTue, 20 Nov 2012 18:30:59 +0000
treeherdermozilla-beta@80afbd9cf1e5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgriffin, NPOTB, test-only
bugs812514
milestone18.0
Bug 812514 - Make b2g emulator unittests save logcat for easier debugging, r=jgriffin, a=NPOTB,test-only
layout/tools/reftest/runreftestb2g.py
testing/marionette/client/marionette/emulator.py
testing/marionette/client/setup.py
testing/mochitest/runtestsb2g.py
--- a/layout/tools/reftest/runreftestb2g.py
+++ b/layout/tools/reftest/runreftestb2g.py
@@ -100,16 +100,20 @@ class B2GOptions(ReftestOptions):
                     type = "string", dest = "pidFile",
                     help = "name of the pidfile to generate")
         defaults["pidFile"] = ""
         self.add_option("--gecko-path", action="store",
                         type="string", dest="geckoPath",
                         help="the path to a gecko distribution that should "
                         "be installed on the emulator prior to test")
         defaults["geckoPath"] = None
+        self.add_option("--logcat-dir", action="store",
+                        type="string", dest="logcat_dir",
+                        help="directory to store logcat dump files")
+        defaults["logcat_dir"] = None
         defaults["remoteTestRoot"] = None
         defaults["logFile"] = "reftest.log"
         defaults["autorun"] = True
         defaults["closeWhenDone"] = True
         defaults["testPath"] = ""
 
         self.set_defaults(**defaults)
 
@@ -128,16 +132,19 @@ class B2GOptions(ReftestOptions):
                 print "ERROR: you must specify a --remote-webserver=<ip address>\n"
                 return None
 
         options.webServer = options.remoteWebServer
 
         if options.geckoPath and not options.emulator:
             self.error("You must specify --emulator if you specify --gecko-path")
 
+        if options.logcat_dir and not options.emulator:
+            self.error("You must specify --emulator if you specify --logcat-dir")
+
         #if not options.emulator and not options.deviceIP:
         #    print "ERROR: you must provide a device IP"
         #    return None
 
         if options.remoteLogFile == None:
             options.remoteLogFile = "reftest.log"
 
         options.localLogName = options.remoteLogFile
@@ -465,26 +472,28 @@ def main(args=sys.argv[1:]):
 
     # create our Marionette instance
     kwargs = {}
     if options.emulator:
         kwargs['emulator'] = options.emulator
         auto.setEmulator(True)
         if options.noWindow:
             kwargs['noWindow'] = True
+        if options.geckoPath:
+            kwargs['gecko_path'] = options.geckoPath
+        if options.logcat_dir:
+            kwargs['logcat_dir'] = options.logcat_dir
     if options.emulator_res:
         kwargs['emulator_res'] = options.emulator_res
     if options.b2gPath:
         kwargs['homedir'] = options.b2gPath
     if options.marionette:
         host,port = options.marionette.split(':')
         kwargs['host'] = host
         kwargs['port'] = int(port)
-    if options.geckoPath:
-        kwargs['gecko_path'] = options.geckoPath
     marionette = Marionette(**kwargs)
     auto.marionette = marionette
 
     # create the DeviceManager
     kwargs = {'adbPath': options.adbPath}
     if options.deviceIP:
         kwargs.update({'host': options.deviceIP,
                        'port': options.devicePort})
--- a/testing/marionette/client/marionette/emulator.py
+++ b/testing/marionette/client/marionette/emulator.py
@@ -1,17 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 import datetime
 from errors import *
 from mozdevice import devicemanagerADB, DMError
 from mozprocess import ProcessHandlerMixin
-import multiprocessing
 import os
 import re
 import platform
 import shutil
 import socket
 import subprocess
 from telnetlib import Telnet
 import tempfile
@@ -245,17 +244,17 @@ class Emulator(object):
             self.proc = None
             if self._tmp_userdata:
                 os.remove(self._tmp_userdata)
                 self._tmp_userdata = None
             if self._tmp_sdcard:
                 os.remove(self._tmp_sdcard)
                 self._tmp_sdcard = None
             return retcode
-        if self.logcat_proc:
+        if self.logcat_proc and self.logcat_proc.proc.poll() is None:
             self.logcat_proc.kill()
         return 0
 
     def _get_adb_devices(self):
         offline = set()
         online = set()
         output = self._run_adb(['devices'])
         for line in output.split('\n'):
@@ -363,23 +362,16 @@ waitFor(
         self.screen.initialize()
 
         if self.logcat_dir:
             self.save_logcat()
 
         # setup DNS fix for networking
         self._run_adb(['shell', 'setprop', 'net.dns1', '10.0.2.3'])
 
-    def _save_logcat_proc(self, filename, cmd):
-        self.logcat_proc = LogcatProc(filename, cmd)
-        self.logcat_proc.run()
-        self.logcat_proc.processOutput()
-        self.logcat_proc.waitForFinish()
-        self.logcat_proc = None
-
     def install_gecko(self, gecko_path, marionette):
         """
         Install gecko into the emulator using adb push.  Restart b2g after the
         installation.
         """
         # See bug 800102.  We use this particular method of installing
         # gecko in order to avoid an adb bug in which adb will sometimes
         # hang indefinitely while copying large files to the system
@@ -430,22 +422,18 @@ waitFor(
     def save_logcat(self):
         """ Save the output of logcat to a file.
         """
         filename = os.path.join(self.logcat_dir, "emulator-%d.log" % self.port)
         if os.access(filename, os.F_OK):
             self.rotate_log(filename)
         cmd = [self.adb, '-s', 'emulator-%d' % self.port, 'logcat']
 
-        # We do this in a separate process because we call mozprocess's
-        # waitForFinish method to process logcat's output, and this method
-        # blocks.
-        proc = multiprocessing.Process(target=self._save_logcat_proc, args=(filename, cmd))
-        proc.daemon = True
-        proc.start()
+        self.logcat_proc = LogcatProc(filename, cmd)
+        self.logcat_proc.run()
 
     def setup_port_forwarding(self, remote_port):
         """ Set up TCP port forwarding to the specified port on the device,
             using any availble local port, and return the local port.
         """
 
         import socket
         s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
--- a/testing/marionette/client/setup.py
+++ b/testing/marionette/client/setup.py
@@ -7,17 +7,17 @@ version = '0.5.8'
 try:
     here = os.path.dirname(os.path.abspath(__file__))
     description = file(os.path.join(here, 'README.md')).read()
 except (OSError, IOError):
     description = ''
 
 # dependencies
 deps = ['manifestdestiny', 'mozhttpd >= 0.3',
-        'mozprocess >= 0.5', 'mozrunner >= 5.10',
+        'mozprocess >= 0.6', 'mozrunner >= 5.11',
         'mozdevice >= 0.12']
 
 setup(name='marionette_client',
       version=version,
       description="Marionette test automation client",
       long_description=description,
       classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
       keywords='mozilla',
--- a/testing/mochitest/runtestsb2g.py
+++ b/testing/mochitest/runtestsb2g.py
@@ -93,16 +93,20 @@ class B2GOptions(MochitestOptions):
                     help = "name of the pidfile to generate")
         defaults["pidFile"] = ""
 
         self.add_option("--gecko-path", action="store",
                         type="string", dest="geckoPath",
                         help="the path to a gecko distribution that should "
                         "be installed on the emulator prior to test")
         defaults["geckoPath"] = None
+        self.add_option("--logcat-dir", action="store",
+                        type="string", dest="logcat_dir",
+                        help="directory to store logcat dump files")
+        defaults["logcat_dir"] = None
 
         defaults["remoteTestRoot"] = None
         defaults["logFile"] = "mochitest.log"
         defaults["autorun"] = True
         defaults["closeWhenDone"] = True
         defaults["testPath"] = ""
         defaults["extensionsToExclude"] = ["specialpowers"]
 
@@ -115,21 +119,23 @@ class B2GOptions(MochitestOptions):
         if options.utilityPath == self._automation.DIST_BIN:
             options.utilityPath = productRoot + "/bin"
 
         if options.remoteWebServer == None:
             if os.name != "nt":
                 options.remoteWebServer = automation.getLanIp()
             else:
                 self.error("You must specify a --remote-webserver=<ip address>")
+        options.webServer = options.remoteWebServer
 
         if options.geckoPath and not options.emulator:
             self.error("You must specify --emulator if you specify --gecko-path")
 
-        options.webServer = options.remoteWebServer
+        if options.logcat_dir and not options.emulator:
+            self.error("You must specify --emulator if you specify --logcat-dir")
 
         #if not options.emulator and not options.deviceIP:
         #    print "ERROR: you must provide a device IP"
         #    return None
 
         if options.remoteLogFile == None:
             options.remoteLogFile = options.remoteTestRoot + '/logs/mochitest.log'
 
@@ -468,16 +474,18 @@ def main():
     kwargs = {}
     if options.emulator:
         kwargs['emulator'] = options.emulator
         auto.setEmulator(True)
         if options.noWindow:
             kwargs['noWindow'] = True
         if options.geckoPath:
             kwargs['gecko_path'] = options.geckoPath
+        if options.logcat_dir:
+            kwargs['logcat_dir'] = options.logcat_dir
     # needless to say sdcard is only valid if using an emulator
     if options.sdcard:
         kwargs['sdcard'] = options.sdcard
     if options.b2gPath:
         kwargs['homedir'] = options.b2gPath
     if options.marionette:
         host,port = options.marionette.split(':')
         kwargs['host'] = host