--- a/testing/tools/mach_test_package_bootstrap.py
+++ b/testing/tools/mach_test_package_bootstrap.py
@@ -124,16 +124,17 @@ def find_hostutils(context):
def normalize_test_path(test_root, path):
if os.path.isabs(path) or os.path.exists(path):
return os.path.normpath(os.path.abspath(path))
for parent in ancestors(test_root):
test_path = os.path.join(parent, path)
if os.path.exists(test_path):
return os.path.normpath(os.path.abspath(test_path))
+ return path
def bootstrap(test_package_root):
test_package_root = os.path.abspath(test_package_root)
# Ensure we are running Python 2.7+. We put this check here so we generate a
# user-friendly error message rather than a cryptic stack trace on module
# import.
--- a/testing/xpcshell/mach_commands.py
+++ b/testing/xpcshell/mach_commands.py
@@ -36,16 +36,17 @@ If you have a B2G build, this can be fou
'''.lstrip()
BUSYBOX_URLS = {
'arm': 'http://www.busybox.net/downloads/binaries/latest/busybox-armv7l',
'x86': 'http://www.busybox.net/downloads/binaries/latest/busybox-i686'
}
here = os.path.abspath(os.path.dirname(__file__))
+parser = None
if sys.version_info[0] < 3:
unicode_type = unicode
else:
unicode_type = str
# This should probably be consolidated with similar classes in other test
# runners.
@@ -72,19 +73,16 @@ class XPCShellRunner(MozbuildObject):
return self.run_suite(**kwargs)
def _run_xpcshell_harness(self, **kwargs):
# Obtain a reference to the xpcshell test runner.
import runxpcshelltests
- log = kwargs.pop("log")
-
- xpcshell = runxpcshelltests.XPCShellTests(log=log)
self.log_manager.enable_unstructured()
tests_dir = os.path.join(self.topobjdir, '_tests', 'xpcshell')
# We want output from the test to be written immediately if we are only
# running a single test.
single_test = (len(kwargs["testPaths"]) == 1 and
os.path.isfile(kwargs["testPaths"][0]) or
kwargs["manifest"] and
@@ -142,17 +140,18 @@ class XPCShellRunner(MozbuildObject):
if isinstance(v, unicode_type):
v = v.encode('utf-8')
if isinstance(k, unicode_type):
k = k.encode('utf-8')
filtered_args[k] = v
- result = xpcshell.runTests(**filtered_args)
+ options = Namespace(**kwargs)
+ result = runxpcshelltests.run_test_harness(parser, options)
self.log_manager.disable_unstructured()
if not result and not xpcshell.sequential:
print("Tests were run in parallel. Try running with --sequential "
"to make sure the failures were not caused by this.")
return int(not result)
@@ -180,17 +179,16 @@ class AndroidXPCShellRunner(MozbuildObje
if build_path not in sys.path:
sys.path.append(build_path)
import remotexpcshelltests
dm = self.get_devicemanager(kwargs["dm_trans"], kwargs["deviceIP"], kwargs["devicePort"],
kwargs["remoteTestRoot"])
- log = kwargs.pop("log")
self.log_manager.enable_unstructured()
if kwargs["xpcshell"] is None:
kwargs["xpcshell"] = "xpcshell"
if not kwargs["objdir"]:
kwargs["objdir"] = self.topobjdir
@@ -220,17 +218,17 @@ class AndroidXPCShellRunner(MozbuildObje
break
else:
raise Exception("APK not found in objdir. You must specify an APK.")
if not kwargs["sequential"]:
kwargs["sequential"] = True
options = argparse.Namespace(**kwargs)
- xpcshell = remotexpcshelltests.XPCShellRemote(dm, options, log)
+ remotexpcshelltests.run_test_harness(parser, options)
result = xpcshell.runTests(testClass=remotexpcshelltests.RemoteXPCShellTestThread,
mobileArgs=xpcshell.mobileArgs,
**vars(options))
self.log_manager.disable_unstructured()
return int(not result)
@@ -284,17 +282,16 @@ class B2GXPCShellRunner(MozbuildObject):
which.which('adb')
except which.WhichError:
# TODO Find adb automatically if it isn't on the path
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["device_name"].startswith('emulator') and 'x86' in kwargs["device_name"]:
kwargs["emulator"] = 'x86'
if kwargs["xpcshell"] is None:
kwargs["xpcshell"] = "xpcshell"
if kwargs["b2g_path"] is None:
@@ -320,29 +317,33 @@ class B2GXPCShellRunner(MozbuildObject):
kwargs["symbolsPath"] = os.path.join(self.distdir, 'crashreporter-symbols')
if kwargs["testingModulesDir"] is None:
kwargs["testingModulesDir"] = os.path.join(self.tests_dir, 'modules')
if kwargs["use_device_libs"] is None:
kwargs["use_device_libs"] = True
parser = parser_b2g()
options = argparse.Namespace(**kwargs)
- rv = runtestsb2g.run_remote_xpcshell(parser, options, log)
+ rv = runtestsb2g.run_test_harness(parser, options)
self.log_manager.disable_unstructured()
return rv
+
def get_parser():
+ global parser
build_obj = MozbuildObject.from_environment(cwd=here)
if conditions.is_android(build_obj):
- return parser_remote()
+ parser = parser_remote()
elif conditions.is_b2g(build_obj):
- return parser_b2g()
+ parser = parser_b2g()
else:
- return parser_desktop()
+ parser = parser_desktop()
+ return parser
+
@CommandProvider
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))
--- a/testing/xpcshell/mach_test_package_commands.py
+++ b/testing/xpcshell/mach_test_package_commands.py
@@ -4,61 +4,98 @@
from __future__ import unicode_literals
import os
import sys
from argparse import Namespace
from functools import partial
-
-import mozlog
-from xpcshellcommandline import parser_desktop
-
from mach.decorators import (
CommandProvider,
Command,
)
+here = os.path.abspath(os.path.dirname(__file__))
+parser = None
+
def run_xpcshell(context, **kwargs):
+ import mozinfo
+ import mozlog
+
args = Namespace(**kwargs)
+ args.testingModulesDir = context.modules_dir
+
+ args.log = mozlog.commandline.setup_logging(
+ "XPCShellTests",
+ args,
+ {"mach": sys.stdout},
+ {"verbose": True}
+ )
+
+ if args.testPaths:
+ test_root = os.path.join(context.package_root, 'xpcshell', 'tests')
+ normalize = partial(context.normalize_test_path, test_root)
+ args.testPaths = map(normalize, args.testPaths)
+
+ if mozinfo.info.get('buildapp') == 'mobile/android':
+ return run_android_xpcshell(context, args)
+ return run_desktop_xpcshell(context, args)
+
+
+def run_desktop_xpcshell(context, args):
+ import runxpcshelltests
+
args.appPath = args.appPath or os.path.dirname(context.firefox_bin)
- args.e10s = context.mozharness_config.get('e10s', args.e10s)
args.utility_path = context.bin_dir
- args.testingModulesDir = context.modules_dir
if not args.xpcshell:
args.xpcshell = os.path.join(args.appPath, 'xpcshell')
if not args.pluginsPath:
for path in context.ancestors(args.appPath, depth=2):
test = os.path.join(path, 'plugins')
if os.path.isdir(test):
args.pluginsPath = test
break
- log = mozlog.commandline.setup_logging("XPCShellTests",
- args,
- {"mach": sys.stdout},
- {"verbose": True})
+ return runxpcshelltests.run_test_harness(parser, args)
+
+
+def run_android_xpcshell(context, args):
+ import remotexpcshelltests
+ args.localAPK = os.path.join(context.mozharness_workdir, 'target.apk')
+ args.xrePath = context.hostutils
- if args.testPaths:
- test_root = os.path.join(context.package_root, 'xpcshell', 'tests')
- normalize = partial(context.normalize_test_path, test_root)
- args.testPaths = map(normalize, args.testPaths)
+ config = context.mozharness_config
+ if config:
+ args.remoteWebServer = config['remote_webserver']
+ args.httpPort = config['emulator']['http_port']
+ args.sslPort = config['emulator']['ssl_port']
+ args.adb_path = config['exes']['adb'] % {'abs_work_dir': context.mozharness_workdir}
+ return remotexpcshelltests.run_test_harness(parser, args)
+
- import runxpcshelltests
- xpcshell = runxpcshelltests.XPCShellTests(log=log)
- return xpcshell.runTests(**vars(args))
+def get_argument_parser():
+ import mozinfo
+ import xpcshellcommandline
+
+ global parser
+ mozinfo.find_and_update_from_json(os.path.dirname(here))
+ if mozinfo.info.get('buildapp') == 'mobile/android':
+ parser = xpcshellcommandline.parser_remote()
+ else:
+ parser = xpcshellcommandline.parser_desktop()
+ return parser
@CommandProvider
class MochitestCommands(object):
def __init__(self, context):
self.context = context
@Command('xpcshell-test', category='testing',
description='Run the xpcshell harness.',
- parser=parser_desktop)
+ parser=get_argument_parser)
def xpcshell(self, **kwargs):
return run_xpcshell(self.context, **kwargs)
--- a/testing/xpcshell/remotexpcshelltests.py
+++ b/testing/xpcshell/remotexpcshelltests.py
@@ -541,16 +541,27 @@ class XPCShellRemote(xpcshell.XPCShellTe
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(parser, options):
+ if not options.localAPK:
+ for file in os.listdir(os.path.join(options.objdir, "dist")):
+ if (file.endswith(".apk") and file.startswith("fennec")):
+ 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)
+
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:
parser.error("Couldn't find local library dir, specify --local-lib-dir")
@@ -578,62 +589,54 @@ def verifyRemoteOptions(parser, options)
return options
class PathMapping:
def __init__(self, localDir, remoteDir):
self.local = localDir
self.remote = remoteDir
-def main():
+def run_test_harness(parser, options):
if sys.version_info < (2,7):
print >>sys.stderr, "Error: You must use python version 2.7 or newer but less than 3.0"
sys.exit(1)
- parser = parser_remote()
- options = parser.parse_args()
- if not options.localAPK:
- for file in os.listdir(os.path.join(options.objdir, "dist")):
- if (file.endswith(".apk") and file.startswith("fennec")):
- 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 = verifyRemoteOptions(parser, options)
+
+ dm_args = {
+ 'deviceRoot': options.remoteTestRoot,
+ 'host': options.deviceIP,
+ 'port': options.devicePort,
+ }
- options = verifyRemoteOptions(parser, options)
- log = commandline.setup_logging("Remote XPCShell",
- options,
- {"tbpl": sys.stdout})
+ dm_cls = mozdevice.DroidSUT
+ if options.dm_trans == 'adb':
+ dm_args['adbPath'] = options.adb_path
+ dm_cls = mozdevice.DroidADB
+ elif not options.deviceIP:
+ print "Error: you must provide a device IP to connect to via the --device option"
+ sys.exit(1)
- if options.dm_trans == "adb":
- if options.deviceIP:
- dm = mozdevice.DroidADB(options.deviceIP, options.devicePort, packageName=None, deviceRoot=options.remoteTestRoot)
- else:
- dm = mozdevice.DroidADB(packageName=None, deviceRoot=options.remoteTestRoot)
- else:
- if not options.deviceIP:
- print "Error: you must provide a device IP to connect to via the --device option"
- sys.exit(1)
- dm = mozdevice.DroidSUT(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
+ dm = dm_cls(**dm_args)
if options.interactive and not options.testPath:
print >>sys.stderr, "Error: You must specify a test filename in interactive mode!"
sys.exit(1)
if options.xpcshell is None:
options.xpcshell = "xpcshell"
- xpcsh = XPCShellRemote(dm, options, log)
+ xpcsh = XPCShellRemote(dm, options, options.log)
# we don't run concurrent tests on mobile
options.sequential = True
- if not xpcsh.runTests(testClass=RemoteXPCShellTestThread,
+ return xpcsh.runTests(testClass=RemoteXPCShellTestThread,
mobileArgs=xpcsh.mobileArgs,
- **vars(options)):
- sys.exit(1)
-
+ **vars(options))
if __name__ == '__main__':
- main()
+ parser = parser_remote()
+ options = parser.parse_args()
+ options.log = commandline.setup_logging("Remote XPCShell",
+ options,
+ {"tbpl": sys.stdout})
+ sys.exit(run_test_harness(parser, options))
--- a/testing/xpcshell/runtestsb2g.py
+++ b/testing/xpcshell/runtestsb2g.py
@@ -82,17 +82,18 @@ def verifyRemoteOptions(parser, options)
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:
parser.error("You must specify --emulator if you specify --logdir")
return remotexpcshelltests.verifyRemoteOptions(parser, options)
-def run_remote_xpcshell(parser, options, log):
+
+def run_test_harness(parser, options):
options = verifyRemoteOptions(parser, options)
# Create the Marionette instance
kwargs = {}
if options.emulator:
kwargs['emulator'] = options.emulator
if options.no_window:
kwargs['noWindow'] = True
@@ -123,17 +124,17 @@ def run_remote_xpcshell(parser, options,
if options.deviceIP:
kwargs['host'] = options.deviceIP
kwargs['port'] = options.devicePort
kwargs['deviceRoot'] = options.remoteTestRoot
dm = devicemanagerADB.DeviceManagerADB(**kwargs)
if not options.remoteTestRoot:
options.remoteTestRoot = dm.deviceRoot
- xpcsh = B2GXPCShellRemote(dm, options, log)
+ xpcsh = B2GXPCShellRemote(dm, options, options.log)
# we don't run concurrent tests on mobile
options.sequential = True
if options.xpcshell is None:
options.xpcshell = "xpcshell"
try:
@@ -141,22 +142,20 @@ def run_remote_xpcshell(parser, options,
mobileArgs=xpcsh.mobileArgs,
**vars(options)):
sys.exit(1)
except:
print "Automation Error: Exception caught while running tests"
traceback.print_exc()
sys.exit(1)
-def main():
- parser = parser_b2g()
- options = parser.parse_args()
- log = commandline.setup_logging("Remote XPCShell",
- options,
- {"tbpl": sys.stdout})
- run_remote_xpcshell(parser, options, log)
# You usually run this like :
# python runtestsb2g.py --emulator arm --b2gpath $B2GPATH --manifest $MANIFEST [--xre-path $MOZ_HOST_BIN
# --adbpath $ADB_PATH
# ...]
if __name__ == '__main__':
- main()
+ parser = parser_b2g()
+ options = parser.parse_args()
+ options.log = commandline.setup_logging("Remote XPCShell",
+ options,
+ {"tbpl": sys.stdout})
+ sys.exit(run_test_harnesS(parser, options)
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -1474,28 +1474,26 @@ class XPCShellTests(object):
self.log.error("TEST-UNEXPECTED-FAIL | Received SIGINT (control-C), so stopped run. " \
"(Use --keep-going to keep running tests after killing one with SIGINT)")
return False
self.log.suite_end()
return self.failCount == 0
-def main():
- parser = parser_desktop()
- options = parser.parse_args()
-
- log = commandline.setup_logging("XPCShell", options, {"tbpl": sys.stdout})
-
+def run_test_harness(parser, options):
if options.xpcshell is None:
print >> sys.stderr, """Must provide path to xpcshell using --xpcshell"""
-
- xpcsh = XPCShellTests(log)
+ return 1
if options.interactive and not options.testPath:
print >>sys.stderr, "Error: You must specify a test filename in interactive mode!"
- sys.exit(1)
+ return 1
- if not xpcsh.runTests(**vars(options)):
- sys.exit(1)
+ xpcsh = XPCShellTests(options.log)
+ return xpcsh.runTests(**vars(options))
+
if __name__ == '__main__':
- main()
+ parser = parser_desktop()
+ options = parser.parse_args()
+ options.log = commandline.setup_logging("XPCShell", options, {"tbpl": sys.stdout})
+ sys.exit(run_test_harness(parser, options))
--- a/testing/xpcshell/xpcshellcommandline.py
+++ b/testing/xpcshell/xpcshellcommandline.py
@@ -127,29 +127,31 @@ def add_remote_arguments(parser):
parser.add_argument("--objdir", action="store", type=str, dest="objdir",
help="local objdir, containing xpcshell binaries")
parser.add_argument("--apk", action="store", type=str, dest="localAPK",
help="local path to Fennec APK")
-
parser.add_argument("--noSetup", action="store_false", dest="setup", default=True,
help="do not copy any files to device (to be used only if device is already setup)")
- parser.add_argument("--local-lib-dir", action="store", type=str, dest="localLib",
+ parser.add_argument("--local-lib-dir", action="store", type=str, dest="localLib", default=None,
help="local path to library directory")
parser.add_argument("--local-bin-dir", action="store", type=str, dest="localBin",
help="local path to bin directory")
parser.add_argument("--remoteTestRoot", action="store", type=str, dest="remoteTestRoot",
help="remote directory to use as test root (eg. /mnt/sdcard/tests or /data/local/tests)")
+ parser.add_argument('--adbpath', action='store', type=str, dest='adb_path',
+ default="adb", help="Path to adb")
+
def add_b2g_arguments(parser):
parser.add_argument('--b2gpath', action='store', type=str, dest='b2g_path',
help="Path to B2G repo or qemu dir")
parser.add_argument('--emupath', action='store', type=str, dest='emu_path',
help="Path to emulator folder (if different "
"from b2gpath")