Fix xpcshell mach command for B2G
authorJames Graham <james@hoppipolla.co.uk>
Tue, 28 Jul 2015 16:56:40 +0100
changeset 517125 a954d4f2e33560e4b32ce03338b6fce249e9d194
parent 517124 ce36fc16b3b98fba0422b0b0297eb20d1410c29b
child 517126 0b116658c110a56b216ec528ba2d4f4ddf1d305e
push id80661
push userjames@hoppipolla.co.uk
push dateWed, 29 Jul 2015 13:57:04 +0000
treeherdertry@e05c6b4d5466 [default view] [failures only]
milestone42.0a1
Fix xpcshell mach command for B2G
testing/xpcshell/mach_commands.py
testing/xpcshell/remotexpcshelltests.py
testing/xpcshell/runtestsb2g.py
testing/xpcshell/xpcshellcommandline.py
--- a/testing/xpcshell/mach_commands.py
+++ b/testing/xpcshell/mach_commands.py
@@ -161,16 +161,18 @@ class AndroidXPCShellRunner(MozbuildObje
         build_path = os.path.join(self.topobjdir, 'build')
         if build_path not in sys.path:
             sys.path.append(build_path)
 
         import remotexpcshelltests
 
         dm = self.get_devicemanager(devicemanager, ip, port, remote_test_root)
 
+        log = kwargs.pop("log")
+        self.log_manager.enable_unstructured()
 
         if not kwargs["objdir"]:
             kwargs["objdir"] = self.topobjdir
 
         if not kwargs["localLib"]:
             kwargs["localLib"] = os.path.join(self.topobjdir, 'dist/fennec')
 
         if not kwargs["localBin"]:
@@ -184,32 +186,33 @@ class AndroidXPCShellRunner(MozbuildObje
 
         if not kwargs["manifest"]:
             kwargs["manifest"] = os.path.join(self.topobjdir, '_tests/xpcshell/xpcshell.ini')
 
         if not kwargs["symbolsPath"]:
             kwars["symbolsPath"] = os.path.join(self.distdir, 'crashreporter-symbols')
 
         if not kwargs["localAPK"]:
-            for file_name in os.listdir(os.path.join(options.objdir, "dist")):
+            for file_name in os.listdir(os.path.join(kwargs["objdir"], "dist")):
                 if file_name.endswith(".apk") and file_name.startswith("fennec"):
-                    kwargs["localAPK"] = os.path.join(options.objdir, "dist", file_name)
-                    print ("using APK: " + options.localAPK)
+                    kwargs["localAPK"] = os.path.join(kwargs["objdir"], "dist", file_name)
+                    print ("using APK: %s" % kwargs["localAPK"])
                     break
             else:
                 raise Exception("You must specify an APK")
 
         options = argparse.Namespace(**kwargs)
         xpcshell = remotexpcshelltests.XPCShellRemote(dm, options, log)
 
         result = xpcshell.runTests(xpcshell='xpcshell',
                                    testClass=remotexpcshelltests.RemoteXPCShellTestThread,
                                    mobileArgs=xpcshell.mobileArgs,
-                                   **options.__dict__)
+                                   **vargs(options))
 
+        self.log_manager.disable_unstructured()
 
         return int(not result)
 
 class B2GXPCShellRunner(MozbuildObject):
     def __init__(self, *args, **kwargs):
         MozbuildObject.__init__(self, *args, **kwargs)
 
         # TODO Bug 794506 remove once mach integrates with virtualenv.
@@ -252,50 +255,61 @@ class B2GXPCShellRunner(MozbuildObject):
         return busybox_path
 
     def run_test(self, **kwargs):
         try:
             import which
             which.which('adb')
         except which.WhichError:
             # TODO Find adb automatically if it isn't on the path
-            print(ADB_NOT_FOUND % ('mochitest-remote', b2g_home))
+            print(ADB_NOT_FOUND % ('mochitest-remote', kwargs["b2g_home"]))
             sys.exit(1)
 
         import runtestsb2g
 
+        log = kwargs.pop("log")
+        self.log_manager.enable_unstructured()
+
+        if kwargs["xpcshell"] is None:
+            kwargs["xpcshell"] = "xpcshell"
+        if kwargs["b2g_path"] is None:
+            kwargs["b2g_path"] = kwargs["b2g_home"]
         if kwargs["busybox"] is None:
             kwargs["busybox"] = os.environ.get('BUSYBOX')
         if kwargs["busybox"] is None:
-            kwargs["busybox"] = self._download_busybox(b2g_home, options.emulator)
+            kwargs["busybox"] = self._download_busybox(kwargs["b2g_home"], kwargs["emulator"])
 
         if kwargs["localLib"] is None:
             kwargs["localLib"] = self.bin_dir
         if kwargs["localBin"] is None:
             kwargs["localBin"] = self.bin_dir
         if kwargs["logdir"] is None:
             kwargs["logdir"] = self.xpcshell_dir
         if kwargs["manifest"] is None:
             kwargs["manifest"] = os.path.join(self.xpcshell_dir, 'xpcshell.ini')
         if kwargs["mozInfo"] is None:
             kwargs["mozInfo"] = os.path.join(self.topobjdir, 'mozinfo.json')
         if kwargs["objdir"] is None:
             kwargs["objdir"] = self.topobjdir
         if kwargs["symbolsPath"] is None:
-            kwargs["symbolsPath"] = os.path.join(self.distdir, 'crashreporter-symbols'),
+            kwargs["symbolsPath"] = os.path.join(self.distdir, 'crashreporter-symbols')
         if kwargs["testingModulesDir"] is None:
-            options.testingModulesDir = os.path.join(self.tests_dir, 'modules')
+            kwargs["testingModulesDir"] = os.path.join(self.tests_dir, 'modules')
         if kwargs["use_device_libs"] is None:
             kwargs["use_device_libs"] = True
 
         if kwargs["device_name"].startswith('emulator') and 'x86' in kwargs["device_name"]:
             kwargs["emulator"] = 'x86'
 
-        return runtestsb2g.run_remote_xpcshell(parser, argparse.Namespace(kwargs), log)
+        parser = parser_b2g()
+        options = argparse.Namespace(**kwargs)
+        rv = runtestsb2g.run_remote_xpcshell(parser, options, log)
 
+        self.log_manager.disable_unstructured()
+        return rv
 
 def get_parser():
     build_obj = MozbuildObject.from_environment(cwd=here)
     if conditions.is_android(build_obj):
         return parser_remote()
     elif conditions.is_b2g(build_obj):
         return parser_b2g()
     else:
@@ -305,18 +319,18 @@ def get_parser():
 class MachCommands(MachCommandBase):
     def __init__(self, context):
         MachCommandBase.__init__(self, context)
 
         for attr in ('b2g_home', 'device_name'):
             setattr(self, attr, getattr(context, attr, None))
 
     @Command('xpcshell-test', category='testing',
-        description='Run XPCOM Shell tests (API direct unit testing)',
-        conditions=[lambda *args: True],
+             description='Run XPCOM Shell tests (API direct unit testing)',
+             conditions=[lambda *args: True],
              parser=get_parser)
     def run_xpcshell_test(self, **params):
         from mozbuild.controller.building import BuildDriver
 
         # We should probably have a utility function to ensure the tree is
         # ready to run tests. Until then, we just create the state dir (in
         # case the tree wasn't built with mach).
         self._ensure_state_subdir_exists('.')
--- a/testing/xpcshell/remotexpcshelltests.py
+++ b/testing/xpcshell/remotexpcshelltests.py
@@ -94,25 +94,25 @@ class RemoteXPCShellTestThread(xpcshell.
 
                 yield path
 
         self.remoteHere = self.remoteForLocal(test['here'])
 
         return (list(sanitize_list(test['head'], 'head')),
                 list(sanitize_list(test['tail'], 'tail')))
 
-    def buildXpcsCmd(self, testdir):
+    def buildXpcsCmd(self):
         # change base class' paths to remote paths and use base class to build command
         self.xpcshell = remoteJoin(self.remoteBinDir, "xpcw")
         self.headJSPath = remoteJoin(self.remoteScriptsDir, 'head.js')
         self.httpdJSPath = remoteJoin(self.remoteComponentsDir, 'httpd.js')
         self.httpdManifest = remoteJoin(self.remoteComponentsDir, 'httpd.manifest')
         self.testingModulesDir = self.remoteModulesDir
         self.testharnessdir = self.remoteScriptsDir
-        xpcshell.XPCShellTestThread.buildXpcsCmd(self, testdir)
+        xpcshell.XPCShellTestThread.buildXpcsCmd(self)
         # remove "-g <dir> -a <dir>" and add "--greomni <apk>"
         del(self.xpcsCmd[1:5])
         if self.options.localAPK:
             self.xpcsCmd.insert(3, '--greomni')
             self.xpcsCmd.insert(4, self.remoteAPK)
 
         if self.remoteDebugger:
             # for example, "/data/local/gdbserver" "localhost:12345"
@@ -483,57 +483,57 @@ class XPCShellRemote(xpcshell.XPCShellTe
             # Foopies have an older mozdevice ver without retryLimit
             self.device.pushDir(self.xpcDir, self.remoteScriptsDir)
 
     def setupMinidumpDir(self):
         if self.device.dirExists(self.remoteMinidumpDir):
             self.device.removeDir(self.remoteMinidumpDir)
         self.device.mkDir(self.remoteMinidumpDir)
 
-    def buildTestList(self, test_tags=None):
-        xpcshell.XPCShellTests.buildTestList(self, test_tags=test_tags)
+    def buildTestList(self, test_tags=None, test_paths=None):
+        xpcshell.XPCShellTests.buildTestList(self, test_tags=test_tags, test_paths=test_paths)
         uniqueTestPaths = set([])
         for test in self.alltests:
             uniqueTestPaths.add(test['here'])
         for testdir in uniqueTestPaths:
             abbrevTestDir = os.path.relpath(testdir, self.xpcDir)
             remoteScriptDir = remoteJoin(self.remoteScriptsDir, abbrevTestDir)
             self.pathMapping.append(PathMapping(testdir, remoteScriptDir))
 
-    def verifyRemoteOptions(self, options):
-        if options.localLib is None:
-            if options.localAPK and options.objdir:
-                for path in ['dist/fennec', 'fennec/lib']:
-                    options.localLib = os.path.join(options.objdir, path)
-                    if os.path.isdir(options.localLib):
-                        break
-                else:
-                    self.error("Couldn't find local library dir, specify --local-lib-dir")
-            elif options.objdir:
-                options.localLib = os.path.join(options.objdir, 'dist/bin')
-            elif os.path.isfile(os.path.join(here, '..', 'bin', 'xpcshell')):
-                # assume tests are being run from a tests.zip
-                options.localLib = os.path.abspath(os.path.join(here, '..', 'bin'))
+def verifyRemoteOptions(parser, options):
+    if options.localLib is None:
+        if options.localAPK and options.objdir:
+            for path in ['dist/fennec', 'fennec/lib']:
+                options.localLib = os.path.join(options.objdir, path)
+                if os.path.isdir(options.localLib):
+                    break
             else:
-                self.error("Couldn't find local library dir, specify --local-lib-dir")
+                parser.error("Couldn't find local library dir, specify --local-lib-dir")
+        elif options.objdir:
+            options.localLib = os.path.join(options.objdir, 'dist/bin')
+        elif os.path.isfile(os.path.join(here, '..', 'bin', 'xpcshell')):
+            # assume tests are being run from a tests.zip
+            options.localLib = os.path.abspath(os.path.join(here, '..', 'bin'))
+        else:
+            parser.error("Couldn't find local library dir, specify --local-lib-dir")
 
-        if options.localBin is None:
-            if options.objdir:
-                for path in ['dist/bin', 'bin']:
-                    options.localBin = os.path.join(options.objdir, path)
-                    if os.path.isdir(options.localBin):
-                        break
-                else:
-                    self.error("Couldn't find local binary dir, specify --local-bin-dir")
-            elif os.path.isfile(os.path.join(here, '..', 'bin', 'xpcshell')):
-                # assume tests are being run from a tests.zip
-                options.localBin = os.path.abspath(os.path.join(here, '..', 'bin'))
+    if options.localBin is None:
+        if options.objdir:
+            for path in ['dist/bin', 'bin']:
+                options.localBin = os.path.join(options.objdir, path)
+                if os.path.isdir(options.localBin):
+                    break
             else:
-                self.error("Couldn't find local binary dir, specify --local-bin-dir")
-        return options
+                parser.error("Couldn't find local binary dir, specify --local-bin-dir")
+        elif os.path.isfile(os.path.join(here, '..', 'bin', 'xpcshell')):
+            # assume tests are being run from a tests.zip
+            options.localBin = os.path.abspath(os.path.join(here, '..', 'bin'))
+        else:
+            parser.error("Couldn't find local binary dir, specify --local-bin-dir")
+    return options
 
 class PathMapping:
 
     def __init__(self, localDir, remoteDir):
         self.local = localDir
         self.remote = remoteDir
 
 def main():
@@ -550,17 +550,17 @@ def main():
                 options.localAPK = os.path.join(options.objdir, "dist")
                 options.localAPK = os.path.join(options.localAPK, file)
                 print >>sys.stderr, "using APK: " + options.localAPK
                 break
         else:
             print >>sys.stderr, "Error: please specify an APK"
             sys.exit(1)
 
-    options = parser.verifyRemoteOptions(options)
+    options = verifyRemoteOptions(parser, options)
     log = commandline.setup_logging("Remote XPCShell",
                                     options,
                                     {"tbpl": sys.stdout})
 
     if options.dm_trans == "adb":
         if options.deviceIP:
             dm = mozdevice.DroidADB(options.deviceIP, options.devicePort, packageName=None, deviceRoot=options.remoteTestRoot)
         else:
--- a/testing/xpcshell/runtestsb2g.py
+++ b/testing/xpcshell/runtestsb2g.py
@@ -4,17 +4,18 @@
 # 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 sys
 import os
 sys.path.insert(0, os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0]))))
 
 import traceback
-from remotexpcshelltests import RemoteXPCShellTestThread, XPCShellRemote, RemoteXPCShellOptions
+import remotexpcshelltests
+from remotexpcshelltests import RemoteXPCShellTestThread, XPCShellRemote
 from mozdevice import devicemanagerADB, DMError
 from mozlog import commandline
 
 DEVICE_TEST_ROOT = '/data/local/tests'
 
 from marionette import Marionette
 from xpcshellcommandline import parser_b2g
 
@@ -70,29 +71,29 @@ class B2GXPCShellRemote(XPCShellRemote):
     def pushLibs(self):
         if not self.options.use_device_libs:
             count = XPCShellRemote.pushLibs(self)
             if not count:
                 # couldn't find any libs, fallback to device libs
                 self.env['LD_LIBRARY_PATH'] = '/system/b2g'
                 self.options.use_device_libs = True
 
-    def verifyRemoteOptions(self, options):
-        if options.b2g_path is None:
-            self.error("Need to specify a --b2gpath")
+def verifyRemoteOptions(parser, options):
+    if options.b2g_path is None:
+        parser.error("Need to specify a --b2gpath")
 
-        if options.geckoPath and not options.emulator:
-            self.error("You must specify --emulator if you specify --gecko-path")
+    if options.geckoPath and not options.emulator:
+        parser.error("You must specify --emulator if you specify --gecko-path")
 
-        if options.logdir and not options.emulator:
-            self.error("You must specify --emulator if you specify --logdir")
-        return RemoteXPCShellOptions.verifyRemoteOptions(self, options)
+    if options.logdir and not options.emulator:
+        parser.error("You must specify --emulator if you specify --logdir")
+    return remotexpcshelltests.verifyRemoteOptions(parser, options)
 
 def run_remote_xpcshell(parser, options, log):
-    options = parser.verifyRemoteOptions(options)
+    options = verifyRemoteOptions(parser, options)
 
     # Create the Marionette instance
     kwargs = {}
     if options.emulator:
         kwargs['emulator'] = options.emulator
         if options.no_window:
             kwargs['noWindow'] = True
         if options.geckoPath:
@@ -128,18 +129,17 @@ def run_remote_xpcshell(parser, options,
     if not options.remoteTestRoot:
         options.remoteTestRoot = dm.deviceRoot
     xpcsh = B2GXPCShellRemote(dm, options, log)
 
     # we don't run concurrent tests on mobile
     options.sequential = True
 
     try:
-        if not xpcsh.runTests(xpcshell='xpcshell',
-                              testClass=B2GXPCShellTestThread,
+        if not xpcsh.runTests(testClass=B2GXPCShellTestThread,
                               mobileArgs=xpcsh.mobileArgs,
                               **vars(options)):
             sys.exit(1)
     except:
         print "Automation Error: Exception caught while running tests"
         traceback.print_exc()
         sys.exit(1)
 
--- a/testing/xpcshell/xpcshellcommandline.py
+++ b/testing/xpcshell/xpcshellcommandline.py
@@ -30,49 +30,49 @@ def parser_common():
                         dest="testingModulesDir", default=None,
                         help="Directory where testing modules are located.")
     parser.add_argument("--test-plugin-path",
                         type=unicode, dest="pluginsPath", default=None,
                         help="Path to the location of a plugins directory containing the test plugin or plugins required for tests. "
                         "By default xpcshell's dir svc provider returns gre/plugins. Use test-plugin-path to add a directory "
                         "to return for NS_APP_PLUGINS_DIR_LIST when queried.")
     parser.add_argument("--total-chunks",
-                        type=int, dest = "totalChunks", default=1,
-                        help = "how many chunks to split the tests up into")
+                        type=int, dest="totalChunks", default=1,
+                        help="how many chunks to split the tests up into")
     parser.add_argument("--this-chunk",
-                        type=int, dest = "thisChunk", default=1,
-                        help = "which chunk to run between 1 and --total-chunks")
+                        type=int, dest="thisChunk", default=1,
+                        help="which chunk to run between 1 and --total-chunks")
     parser.add_argument("--profile-name",
                         type=unicode, dest="profileName", default=None,
                         help="name of application profile being tested")
     parser.add_argument("--build-info-json",
                         type=unicode, dest="mozInfo", default=None,
                         help="path to a mozinfo.json including information about the build configuration. defaults to looking for mozinfo.json next to the script.")
     parser.add_argument("--shuffle",
                         action="store_true", dest="shuffle", default=False,
                         help="Execute tests in random order")
     parser.add_argument("--xre-path",
                         action="store", type=unicode, dest="xrePath",
                         # individual scripts will set a sane default
-                        default = None,
-                        help = "absolute path to directory containing XRE (probably xulrunner)")
+                        default=None,
+                        help="absolute path to directory containing XRE (probably xulrunner)")
     parser.add_argument("--symbols-path",
-                        action = "store", type=unicode, dest = "symbolsPath",
-                        default = None,
-                        help = "absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols")
+                        action="store", type=unicode, dest="symbolsPath",
+                        default=None,
+                        help="absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols")
     parser.add_argument("--debugger",
-                        action = "store", dest = "debugger",
-                        help = "use the given debugger to launch the application")
+                        action="store", dest="debugger",
+                        help="use the given debugger to launch the application")
     parser.add_argument("--debugger-args",
-                        action = "store", dest = "debuggerArgs",
-                        help = "pass the given args to the debugger _before_ "
+                        action="store", dest="debuggerArgs",
+                        help="pass the given args to the debugger _before_ "
                         "the application on the command line")
     parser.add_argument("--debugger-interactive",
-                        action = "store_true", dest = "debuggerInteractive",
-                        help = "prevents the test harness from redirecting "
+                        action="store_true", dest="debuggerInteractive",
+                        help="prevents the test harness from redirecting "
                         "stdout and stderr for interactive debuggers")
     parser.add_argument("--jsdebugger", dest="jsDebugger", action="store_true",
                         help="Waits for a devtools JS debugger to connect before "
                         "starting the test.")
     parser.add_argument("--jsdebugger-port", type=int, dest="jsDebuggerPort",
                         default=6000,
                         help="The port to listen on for a debugger connection if "
                         "--jsdebugger is specified.")
@@ -177,14 +177,12 @@ def parser_b2g():
                         "be installed on the emulator prior to test")
 
     parser.add_argument("--logdir", action="store", type=unicode, dest="logdir",
                         help="directory to store log files")
 
     parser.add_argument('--busybox', action='store', type=unicode, dest='busybox',
                         help="Path to busybox binary to install on device")
 
-    defaults = {"remoteTestRoot": "/data/local/tests",
-                "dm_trans": "adb"}
-
-    parser.set_defaults(defaults)
+    parser.set_defaults(remoteTestRoot="/data/local/tests",
+                        dm_trans="adb")
 
     return parser