2012-09-26 20:43:53 +04:00
|
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
2012-10-10 22:08:09 +04:00
|
|
|
# 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/.
|
2012-09-26 20:43:53 +04:00
|
|
|
|
|
|
|
from __future__ import unicode_literals
|
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
from argparse import Namespace
|
2013-04-05 02:17:23 +04:00
|
|
|
import logging
|
2015-03-25 09:05:28 +03:00
|
|
|
import mozpack.path as mozpath
|
2012-10-03 01:03:31 +04:00
|
|
|
import os
|
2013-03-27 02:00:43 +04:00
|
|
|
import sys
|
2013-09-19 22:43:44 +04:00
|
|
|
import warnings
|
2013-08-29 22:23:07 +04:00
|
|
|
import which
|
2012-10-03 01:03:31 +04:00
|
|
|
|
2012-11-07 04:57:41 +04:00
|
|
|
from mozbuild.base import (
|
|
|
|
MachCommandBase,
|
2013-08-28 18:08:50 +04:00
|
|
|
MachCommandConditions as conditions,
|
2012-11-07 04:57:41 +04:00
|
|
|
MozbuildObject,
|
|
|
|
)
|
2012-10-10 22:08:09 +04:00
|
|
|
|
2012-11-07 04:57:41 +04:00
|
|
|
from mach.decorators import (
|
2012-10-10 22:08:09 +04:00
|
|
|
CommandArgument,
|
|
|
|
CommandProvider,
|
|
|
|
Command,
|
|
|
|
)
|
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
here = os.path.abspath(os.path.dirname(__file__))
|
2013-04-05 02:17:23 +04:00
|
|
|
|
2014-08-13 20:03:00 +04:00
|
|
|
|
2013-09-19 22:43:44 +04:00
|
|
|
ADB_NOT_FOUND = '''
|
|
|
|
The %s command requires the adb binary to be on your path.
|
|
|
|
|
|
|
|
If you have a B2G build, this can be found in
|
|
|
|
'%s/out/host/<platform>/bin'.
|
|
|
|
'''.lstrip()
|
|
|
|
|
|
|
|
GAIA_PROFILE_NOT_FOUND = '''
|
|
|
|
The %s command requires a non-debug gaia profile. Either pass in --profile,
|
|
|
|
or set the GAIA_PROFILE environment variable.
|
|
|
|
|
|
|
|
If you do not have a non-debug gaia profile, you can build one:
|
|
|
|
$ git clone https://github.com/mozilla-b2g/gaia
|
|
|
|
$ cd gaia
|
|
|
|
$ make
|
|
|
|
|
|
|
|
The profile should be generated in a directory called 'profile'.
|
|
|
|
'''.lstrip()
|
|
|
|
|
|
|
|
GAIA_PROFILE_IS_DEBUG = '''
|
|
|
|
The %s command requires a non-debug gaia profile. The specified profile,
|
|
|
|
%s, is a debug profile.
|
|
|
|
|
|
|
|
If you do not have a non-debug gaia profile, you can build one:
|
|
|
|
$ git clone https://github.com/mozilla-b2g/gaia
|
|
|
|
$ cd gaia
|
|
|
|
$ make
|
|
|
|
|
|
|
|
The profile should be generated in a directory called 'profile'.
|
|
|
|
'''.lstrip()
|
|
|
|
|
2014-07-17 21:38:20 +04:00
|
|
|
ENG_BUILD_REQUIRED = '''
|
|
|
|
The %s command requires an engineering build. It may be the case that
|
|
|
|
VARIANT=user or PRODUCTION=1 were set. Try re-building with VARIANT=eng:
|
|
|
|
|
|
|
|
$ VARIANT=eng ./build.sh
|
|
|
|
|
|
|
|
There should be an app called 'test-container.gaiamobile.org' located in
|
|
|
|
%s.
|
|
|
|
'''.lstrip()
|
|
|
|
|
2014-06-18 02:42:08 +04:00
|
|
|
# Maps test flavors to mochitest suite type.
|
|
|
|
FLAVORS = {
|
|
|
|
'mochitest': 'plain',
|
|
|
|
'chrome': 'chrome',
|
|
|
|
'browser-chrome': 'browser',
|
2014-09-22 22:08:06 +04:00
|
|
|
'jetpack-package': 'jetpack-package',
|
|
|
|
'jetpack-addon': 'jetpack-addon',
|
2014-06-18 02:42:08 +04:00
|
|
|
'a11y': 'a11y',
|
|
|
|
'webapprt-chrome': 'webapprt-chrome',
|
|
|
|
}
|
2013-04-05 02:17:23 +04:00
|
|
|
|
2012-10-10 22:08:09 +04:00
|
|
|
|
2012-10-10 22:08:09 +04:00
|
|
|
class MochitestRunner(MozbuildObject):
|
2015-02-13 22:42:02 +03:00
|
|
|
|
2012-09-26 20:43:53 +04:00
|
|
|
"""Easily run mochitests.
|
|
|
|
|
|
|
|
This currently contains just the basics for running mochitests. We may want
|
|
|
|
to hook up result parsing, etc.
|
|
|
|
"""
|
2013-08-28 18:08:50 +04:00
|
|
|
|
2013-09-23 18:47:48 +04:00
|
|
|
def get_webapp_runtime_path(self):
|
2013-09-25 00:44:23 +04:00
|
|
|
import mozinfo
|
2013-09-23 18:47:48 +04:00
|
|
|
appname = 'webapprt-stub' + mozinfo.info.get('bin_suffix', '')
|
|
|
|
if sys.platform.startswith('darwin'):
|
2015-02-13 22:42:02 +03:00
|
|
|
appname = os.path.join(
|
|
|
|
self.distdir,
|
|
|
|
self.substs['MOZ_MACBUNDLE_NAME'],
|
|
|
|
'Contents',
|
|
|
|
'Resources',
|
|
|
|
appname)
|
2013-09-23 18:47:48 +04:00
|
|
|
else:
|
|
|
|
appname = os.path.join(self.distdir, 'bin', appname)
|
|
|
|
return appname
|
|
|
|
|
2013-08-28 18:08:50 +04:00
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
MozbuildObject.__init__(self, *args, **kwargs)
|
|
|
|
|
|
|
|
# TODO Bug 794506 remove once mach integrates with virtualenv.
|
|
|
|
build_path = os.path.join(self.topobjdir, 'build')
|
|
|
|
if build_path not in sys.path:
|
|
|
|
sys.path.append(build_path)
|
|
|
|
|
|
|
|
self.tests_dir = os.path.join(self.topobjdir, '_tests')
|
2015-02-13 22:42:02 +03:00
|
|
|
self.mochitest_dir = os.path.join(
|
|
|
|
self.tests_dir,
|
|
|
|
'testing',
|
|
|
|
'mochitest')
|
2014-01-16 21:23:32 +04:00
|
|
|
self.bin_dir = os.path.join(self.topobjdir, 'dist', 'bin')
|
2013-08-28 18:08:50 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
def run_b2g_test(self, test_paths=None, **kwargs):
|
2013-08-28 18:08:50 +04:00
|
|
|
"""Runs a b2g mochitest.
|
|
|
|
|
2014-03-25 03:19:57 +04:00
|
|
|
test_paths is an enumerable of paths to tests. It can be a relative path
|
|
|
|
from the top source directory, an absolute filename, or a directory
|
|
|
|
containing test files.
|
2013-08-28 18:08:50 +04:00
|
|
|
"""
|
2013-09-11 22:53:47 +04:00
|
|
|
# Need to call relpath before os.chdir() below.
|
|
|
|
test_path = ''
|
2014-03-25 03:19:57 +04:00
|
|
|
if test_paths:
|
|
|
|
if len(test_paths) > 1:
|
|
|
|
print('Warning: Only the first test path will be used.')
|
|
|
|
test_path = self._wrap_path_argument(test_paths[0]).relpath()
|
2013-09-11 22:53:47 +04:00
|
|
|
|
2013-08-28 18:08:50 +04:00
|
|
|
# TODO without os.chdir, chained imports fail below
|
|
|
|
os.chdir(self.mochitest_dir)
|
|
|
|
|
2013-09-19 22:43:44 +04:00
|
|
|
# The imp module can spew warnings if the modules below have
|
|
|
|
# already been imported, ignore them.
|
|
|
|
with warnings.catch_warnings():
|
|
|
|
warnings.simplefilter('ignore')
|
2013-08-28 18:08:50 +04:00
|
|
|
|
2013-09-19 22:43:44 +04:00
|
|
|
import imp
|
|
|
|
path = os.path.join(self.mochitest_dir, 'runtestsb2g.py')
|
|
|
|
with open(path, 'r') as fh:
|
|
|
|
imp.load_module('mochitest', fh, path,
|
2015-02-13 22:42:02 +03:00
|
|
|
('.py', 'r', imp.PY_SOURCE))
|
2013-09-19 22:43:44 +04:00
|
|
|
|
|
|
|
import mochitest
|
2013-08-28 18:08:50 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
options = Namespace(**kwargs)
|
2013-08-28 18:08:50 +04:00
|
|
|
|
2013-09-11 22:53:47 +04:00
|
|
|
if test_path:
|
2015-04-30 20:47:01 +03:00
|
|
|
if options.chrome:
|
2015-03-25 09:05:28 +03:00
|
|
|
test_root_file = mozpath.join(
|
2015-02-13 22:42:02 +03:00
|
|
|
self.mochitest_dir,
|
|
|
|
'chrome',
|
|
|
|
test_path)
|
2014-12-24 00:17:39 +03:00
|
|
|
else:
|
2015-03-25 09:05:28 +03:00
|
|
|
test_root_file = mozpath.join(
|
2015-02-13 22:42:02 +03:00
|
|
|
self.mochitest_dir,
|
|
|
|
'tests',
|
|
|
|
test_path)
|
2013-09-11 22:53:47 +04:00
|
|
|
if not os.path.exists(test_root_file):
|
2015-02-13 22:42:02 +03:00
|
|
|
print(
|
|
|
|
'Specified test path does not exist: %s' %
|
|
|
|
test_root_file)
|
2013-09-11 22:53:47 +04:00
|
|
|
return 1
|
|
|
|
options.testPath = test_path
|
2014-02-11 00:58:46 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
if options.desktop:
|
|
|
|
return mochitest.run_desktop_mochitests(options)
|
2013-09-19 22:43:44 +04:00
|
|
|
|
|
|
|
try:
|
|
|
|
which.which('adb')
|
|
|
|
except which.WhichError:
|
|
|
|
# TODO Find adb automatically if it isn't on the path
|
2015-04-30 20:47:01 +03:00
|
|
|
print(ADB_NOT_FOUND % ('mochitest-remote', options.b2gPath))
|
2013-09-19 22:43:44 +04:00
|
|
|
return 1
|
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
return mochitest.run_remote_mochitests(options)
|
2012-09-26 20:43:53 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
def run_desktop_test(self, context, suite=None, test_paths=None, **kwargs):
|
|
|
|
"""Runs a mochitest.
|
2012-09-26 20:43:53 +04:00
|
|
|
|
|
|
|
suite is the type of mochitest to run. It can be one of ('plain',
|
2014-09-22 22:08:06 +04:00
|
|
|
'chrome', 'browser', 'metro', 'a11y', 'jetpack-package', 'jetpack-addon').
|
2012-12-06 02:27:54 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
test_paths are path to tests. They can be a relative path from the
|
|
|
|
top source directory, an absolute filename, or a directory containing
|
|
|
|
test files.
|
2012-09-26 20:43:53 +04:00
|
|
|
"""
|
2014-09-03 15:06:00 +04:00
|
|
|
# Make absolute paths relative before calling os.chdir() below.
|
2014-03-25 03:19:57 +04:00
|
|
|
if test_paths:
|
2015-02-13 22:42:02 +03:00
|
|
|
test_paths = [self._wrap_path_argument(
|
|
|
|
p).relpath() if os.path.isabs(p) else p for p in test_paths]
|
2013-03-27 02:00:43 +04:00
|
|
|
|
|
|
|
# runtests.py is ambiguous, so we load the file/module manually.
|
|
|
|
if 'mochitest' not in sys.modules:
|
|
|
|
import imp
|
2013-08-28 18:08:50 +04:00
|
|
|
path = os.path.join(self.mochitest_dir, 'runtests.py')
|
2013-03-27 02:00:43 +04:00
|
|
|
with open(path, 'r') as fh:
|
|
|
|
imp.load_module('mochitest', fh, path,
|
2015-02-13 22:42:02 +03:00
|
|
|
('.py', 'r', imp.PY_SOURCE))
|
2013-03-27 02:00:43 +04:00
|
|
|
|
|
|
|
import mochitest
|
2014-03-25 01:35:06 +04:00
|
|
|
from manifestparser import TestManifest
|
|
|
|
from mozbuild.testing import TestResolver
|
2013-03-27 02:00:43 +04:00
|
|
|
|
|
|
|
# This is required to make other components happy. Sad, isn't it?
|
|
|
|
os.chdir(self.topobjdir)
|
|
|
|
|
2013-04-05 02:17:23 +04:00
|
|
|
# Automation installs its own stream handler to stdout. Since we want
|
|
|
|
# all logging to go through us, we just remove their handler.
|
|
|
|
remove_handlers = [l for l in logging.getLogger().handlers
|
2015-02-13 22:42:02 +03:00
|
|
|
if isinstance(l, logging.StreamHandler)]
|
2013-04-05 02:17:23 +04:00
|
|
|
for handler in remove_handlers:
|
|
|
|
logging.getLogger().removeHandler(handler)
|
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
options = Namespace(**kwargs)
|
2013-03-27 02:00:43 +04:00
|
|
|
|
2014-03-25 01:35:06 +04:00
|
|
|
flavor = suite
|
2013-08-23 18:06:16 +04:00
|
|
|
|
2013-03-28 20:23:03 +04:00
|
|
|
if suite == 'plain':
|
|
|
|
# Don't need additional options for plain.
|
2014-03-25 01:35:06 +04:00
|
|
|
flavor = 'mochitest'
|
2013-03-28 20:23:03 +04:00
|
|
|
elif suite == 'chrome':
|
|
|
|
options.chrome = True
|
|
|
|
elif suite == 'browser':
|
|
|
|
options.browserChrome = True
|
2014-03-25 01:35:06 +04:00
|
|
|
flavor = 'browser-chrome'
|
2014-03-25 20:52:53 +04:00
|
|
|
elif suite == 'devtools':
|
|
|
|
options.browserChrome = True
|
2015-04-30 20:47:01 +03:00
|
|
|
options.subsuite = 'devtools'
|
2014-09-22 22:08:06 +04:00
|
|
|
elif suite == 'jetpack-package':
|
|
|
|
options.jetpackPackage = True
|
|
|
|
elif suite == 'jetpack-addon':
|
|
|
|
options.jetpackAddon = True
|
2013-03-28 20:23:03 +04:00
|
|
|
elif suite == 'metro':
|
|
|
|
options.immersiveMode = True
|
|
|
|
options.browserChrome = True
|
|
|
|
elif suite == 'a11y':
|
|
|
|
options.a11y = True
|
2013-08-23 18:06:16 +04:00
|
|
|
elif suite == 'webapprt-content':
|
|
|
|
options.webapprtContent = True
|
2015-04-30 20:47:01 +03:00
|
|
|
if not options.app or options.app == self.get_binary_path():
|
|
|
|
options.app = self.get_webapp_runtime_path()
|
2013-08-23 18:06:16 +04:00
|
|
|
elif suite == 'webapprt-chrome':
|
|
|
|
options.webapprtChrome = True
|
|
|
|
options.browserArgs.append("-test-mode")
|
2015-04-30 20:47:01 +03:00
|
|
|
if not options.app or options.app == self.get_binary_path():
|
|
|
|
options.app = self.get_webapp_runtime_path()
|
2013-03-28 20:23:03 +04:00
|
|
|
else:
|
|
|
|
raise Exception('None or unrecognized mochitest suite type.')
|
|
|
|
|
2014-03-25 03:19:57 +04:00
|
|
|
if test_paths:
|
2014-03-25 01:35:06 +04:00
|
|
|
resolver = self._spawn(TestResolver)
|
|
|
|
|
2015-02-13 22:42:02 +03:00
|
|
|
tests = list(
|
|
|
|
resolver.resolve_tests(
|
|
|
|
paths=test_paths,
|
|
|
|
flavor=flavor))
|
2014-03-25 01:35:06 +04:00
|
|
|
|
|
|
|
if not tests:
|
|
|
|
print('No tests could be found in the path specified. Please '
|
2015-02-13 22:42:02 +03:00
|
|
|
'specify a path that is a test file or is a directory '
|
|
|
|
'containing tests.')
|
2013-03-28 20:23:03 +04:00
|
|
|
return 1
|
|
|
|
|
2014-03-25 01:35:06 +04:00
|
|
|
manifest = TestManifest()
|
|
|
|
manifest.tests.extend(tests)
|
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
# XXX why is this such a special case?
|
|
|
|
if len(tests) == 1 and options.closeWhenDone and suite == 'plain':
|
2014-05-22 23:09:21 +04:00
|
|
|
options.closeWhenDone = False
|
|
|
|
|
2014-03-25 01:35:06 +04:00
|
|
|
options.manifestFile = manifest
|
2012-09-26 20:43:53 +04:00
|
|
|
|
2013-04-05 02:17:23 +04:00
|
|
|
# We need this to enable colorization of output.
|
|
|
|
self.log_manager.enable_unstructured()
|
2015-04-30 20:47:01 +03:00
|
|
|
result = mochitest.run_test_harness(options)
|
2013-04-05 02:17:23 +04:00
|
|
|
self.log_manager.disable_unstructured()
|
|
|
|
return result
|
2013-03-27 02:00:43 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
def run_android_test(self, test_path, **kwargs):
|
2015-04-10 04:11:56 +03:00
|
|
|
self.tests_dir = os.path.join(self.topobjdir, '_tests')
|
|
|
|
self.mochitest_dir = os.path.join(self.tests_dir, 'testing', 'mochitest')
|
|
|
|
import imp
|
|
|
|
path = os.path.join(self.mochitest_dir, 'runtestsremote.py')
|
|
|
|
with open(path, 'r') as fh:
|
|
|
|
imp.load_module('runtestsremote', fh, path,
|
2015-04-30 20:47:01 +03:00
|
|
|
('.py', 'r', imp.PY_SOURCE))
|
2015-04-10 04:11:56 +03:00
|
|
|
import runtestsremote
|
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
options = Namespace(**kwargs)
|
|
|
|
if test_path:
|
|
|
|
options.testPath = test_path
|
2014-11-17 19:52:24 +03:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
sys.exit(runtestsremote.run_test_harness(options))
|
2015-02-25 17:23:54 +03:00
|
|
|
|
2015-02-13 22:42:02 +03:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
# parser
|
2015-04-10 22:31:36 +03:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
def TestPathArg(func):
|
|
|
|
test_paths = CommandArgument('test_paths', nargs='*', metavar='TEST', default=None,
|
|
|
|
help='Test to run. Can be a single test file or a directory of tests to '
|
|
|
|
'(run recursively). If omitted, the entire suite is run.')
|
|
|
|
return test_paths(func)
|
2015-04-10 22:31:36 +03:00
|
|
|
|
2013-08-28 18:08:50 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
def setup_argument_parser():
|
|
|
|
build_obj = MozbuildObject.from_environment(cwd=here)
|
2013-08-28 18:08:50 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
build_path = os.path.join(build_obj.topobjdir, 'build')
|
|
|
|
if build_path not in sys.path:
|
|
|
|
sys.path.append(build_path)
|
2013-09-19 22:43:44 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
mochitest_dir = os.path.join(build_obj.topobjdir, '_tests', 'testing', 'mochitest')
|
2013-09-19 22:43:44 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
with warnings.catch_warnings():
|
|
|
|
warnings.simplefilter('ignore')
|
2013-08-28 18:08:50 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
import imp
|
|
|
|
path = os.path.join(build_obj.topobjdir, mochitest_dir, 'runtests.py')
|
|
|
|
with open(path, 'r') as fh:
|
|
|
|
imp.load_module('mochitest', fh, path,
|
|
|
|
('.py', 'r', imp.PY_SOURCE))
|
2014-08-05 07:29:00 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
from mochitest_options import MochitestArgumentParser
|
2014-08-05 07:29:00 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
return MochitestArgumentParser()
|
2015-03-19 23:15:33 +03:00
|
|
|
|
2012-10-10 22:08:09 +04:00
|
|
|
|
2015-04-08 18:12:52 +03:00
|
|
|
# condition filters
|
|
|
|
|
|
|
|
def is_platform_in(*platforms):
|
|
|
|
def is_platform_supported(cls):
|
|
|
|
for p in platforms:
|
|
|
|
c = getattr(conditions, 'is_{}'.format(p), None)
|
|
|
|
if c and c(cls):
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
is_platform_supported.__doc__ = 'Must have a {} build.'.format(
|
|
|
|
' or '.join(platforms))
|
|
|
|
return is_platform_supported
|
2013-09-19 22:43:44 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
|
2015-04-10 04:11:56 +03:00
|
|
|
def verify_host_bin():
|
|
|
|
# validate MOZ_HOST_BIN environment variables for Android tests
|
|
|
|
MOZ_HOST_BIN = os.environ.get('MOZ_HOST_BIN')
|
|
|
|
if not MOZ_HOST_BIN:
|
|
|
|
print('environment variable MOZ_HOST_BIN must be set to a directory containing host xpcshell')
|
|
|
|
return 1
|
|
|
|
elif not os.path.isdir(MOZ_HOST_BIN):
|
|
|
|
print('$MOZ_HOST_BIN does not specify a directory')
|
|
|
|
return 1
|
|
|
|
elif not os.path.isfile(os.path.join(MOZ_HOST_BIN, 'xpcshell')):
|
|
|
|
print('$MOZ_HOST_BIN/xpcshell does not exist')
|
|
|
|
return 1
|
|
|
|
return 0
|
2015-02-13 22:42:02 +03:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
|
2012-10-10 22:08:09 +04:00
|
|
|
@CommandProvider
|
2012-11-07 04:57:41 +04:00
|
|
|
class MachCommands(MachCommandBase):
|
2015-02-13 22:42:02 +03:00
|
|
|
|
2015-04-08 18:12:52 +03:00
|
|
|
def __init__(self, context):
|
|
|
|
MachCommandBase.__init__(self, context)
|
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
for attr in ('device_name', 'target_out'):
|
2015-04-08 18:12:52 +03:00
|
|
|
setattr(self, attr, getattr(context, attr, None))
|
|
|
|
|
2015-02-13 22:42:02 +03:00
|
|
|
@Command(
|
|
|
|
'mochitest-plain',
|
|
|
|
category='testing',
|
2015-04-10 04:11:56 +03:00
|
|
|
conditions=[is_platform_in('firefox', 'mulet', 'b2g', 'b2g_desktop', 'android')],
|
2014-08-13 20:03:00 +04:00
|
|
|
description='Run a plain mochitest (integration test, plain web page).',
|
2015-04-13 22:36:56 +03:00
|
|
|
parser=setup_argument_parser)
|
2015-04-30 20:47:01 +03:00
|
|
|
@TestPathArg
|
2014-03-25 03:19:57 +04:00
|
|
|
def run_mochitest_plain(self, test_paths, **kwargs):
|
2015-04-08 18:12:52 +03:00
|
|
|
if is_platform_in('firefox', 'mulet')(self):
|
|
|
|
return self.run_mochitest(test_paths, 'plain', **kwargs)
|
|
|
|
elif conditions.is_emulator(self):
|
|
|
|
return self.run_mochitest_remote(test_paths, **kwargs)
|
|
|
|
elif conditions.is_b2g_desktop(self):
|
2015-04-18 02:19:28 +03:00
|
|
|
return self.run_mochitest_b2g_desktop(test_paths, **kwargs)
|
2015-04-10 04:11:56 +03:00
|
|
|
elif conditions.is_android(self):
|
|
|
|
return self.run_mochitest_android(test_paths, **kwargs)
|
2012-10-10 22:08:09 +04:00
|
|
|
|
2015-02-13 22:42:02 +03:00
|
|
|
@Command(
|
|
|
|
'mochitest-chrome',
|
|
|
|
category='testing',
|
2015-04-10 04:11:56 +03:00
|
|
|
conditions=[is_platform_in('firefox', 'emulator', 'android')],
|
2014-08-25 20:32:00 +04:00
|
|
|
description='Run a chrome mochitest (integration test with some XUL).',
|
2015-04-13 22:36:56 +03:00
|
|
|
parser=setup_argument_parser)
|
2015-04-30 20:47:01 +03:00
|
|
|
@TestPathArg
|
2014-03-25 03:19:57 +04:00
|
|
|
def run_mochitest_chrome(self, test_paths, **kwargs):
|
2015-04-30 20:47:01 +03:00
|
|
|
kwargs['chrome'] = True
|
2015-04-08 18:12:52 +03:00
|
|
|
if conditions.is_firefox(self):
|
|
|
|
return self.run_mochitest(test_paths, 'chrome', **kwargs)
|
|
|
|
elif conditions.is_b2g(self) and conditions.is_emulator(self):
|
2015-04-30 20:47:01 +03:00
|
|
|
return self.run_mochitest_remote(test_paths, **kwargs)
|
2015-04-10 04:11:56 +03:00
|
|
|
elif conditions.is_android(self):
|
2015-04-30 20:47:01 +03:00
|
|
|
return self.run_mochitest_android(test_paths, **kwargs)
|
2012-10-10 22:08:09 +04:00
|
|
|
|
2015-02-13 22:42:02 +03:00
|
|
|
@Command(
|
|
|
|
'mochitest-browser',
|
|
|
|
category='testing',
|
2015-04-08 18:12:52 +03:00
|
|
|
conditions=[conditions.is_firefox],
|
2014-08-25 20:32:00 +04:00
|
|
|
description='Run a mochitest with browser chrome (integration test with a standard browser).',
|
2015-04-13 22:36:56 +03:00
|
|
|
parser=setup_argument_parser)
|
2015-04-30 20:47:01 +03:00
|
|
|
@TestPathArg
|
2014-03-25 03:19:57 +04:00
|
|
|
def run_mochitest_browser(self, test_paths, **kwargs):
|
|
|
|
return self.run_mochitest(test_paths, 'browser', **kwargs)
|
2012-10-10 22:08:09 +04:00
|
|
|
|
2015-02-13 22:42:02 +03:00
|
|
|
@Command(
|
|
|
|
'mochitest-devtools',
|
|
|
|
category='testing',
|
2015-04-08 18:12:52 +03:00
|
|
|
conditions=[conditions.is_firefox],
|
2014-08-25 20:32:00 +04:00
|
|
|
description='Run a devtools mochitest with browser chrome (integration test with a standard browser with the devtools frame).',
|
2015-04-13 22:36:56 +03:00
|
|
|
parser=setup_argument_parser)
|
2015-04-30 20:47:01 +03:00
|
|
|
@TestPathArg
|
2014-03-25 20:52:53 +04:00
|
|
|
def run_mochitest_devtools(self, test_paths, **kwargs):
|
|
|
|
return self.run_mochitest(test_paths, 'devtools', **kwargs)
|
|
|
|
|
2014-09-22 22:08:06 +04:00
|
|
|
@Command('jetpack-package', category='testing',
|
2015-02-13 22:42:02 +03:00
|
|
|
conditions=[conditions.is_firefox],
|
2015-04-24 05:33:23 +03:00
|
|
|
description='Run a jetpack package test.',
|
|
|
|
parser=setup_argument_parser)
|
2015-04-30 20:47:01 +03:00
|
|
|
@TestPathArg
|
2014-09-22 22:08:06 +04:00
|
|
|
def run_mochitest_jetpack_package(self, test_paths, **kwargs):
|
|
|
|
return self.run_mochitest(test_paths, 'jetpack-package', **kwargs)
|
|
|
|
|
|
|
|
@Command('jetpack-addon', category='testing',
|
2015-02-13 22:42:02 +03:00
|
|
|
conditions=[conditions.is_firefox],
|
2015-04-24 05:33:23 +03:00
|
|
|
description='Run a jetpack addon test.',
|
|
|
|
parser=setup_argument_parser)
|
2015-04-30 20:47:01 +03:00
|
|
|
@TestPathArg
|
2014-09-22 22:08:06 +04:00
|
|
|
def run_mochitest_jetpack_addon(self, test_paths, **kwargs):
|
|
|
|
return self.run_mochitest(test_paths, 'jetpack-addon', **kwargs)
|
|
|
|
|
2015-02-13 22:42:02 +03:00
|
|
|
@Command(
|
|
|
|
'mochitest-metro',
|
|
|
|
category='testing',
|
2015-04-08 18:12:52 +03:00
|
|
|
conditions=[conditions.is_firefox],
|
2014-08-25 20:32:00 +04:00
|
|
|
description='Run a mochitest with metro browser chrome (tests for Windows touch interface).',
|
2015-04-13 22:36:56 +03:00
|
|
|
parser=setup_argument_parser)
|
2015-04-30 20:47:01 +03:00
|
|
|
@TestPathArg
|
2014-03-25 03:19:57 +04:00
|
|
|
def run_mochitest_metro(self, test_paths, **kwargs):
|
|
|
|
return self.run_mochitest(test_paths, 'metro', **kwargs)
|
2013-02-13 00:51:24 +04:00
|
|
|
|
2013-05-09 04:56:30 +04:00
|
|
|
@Command('mochitest-a11y', category='testing',
|
2015-02-13 22:42:02 +03:00
|
|
|
conditions=[conditions.is_firefox],
|
|
|
|
description='Run an a11y mochitest (accessibility tests).',
|
2015-04-13 22:36:56 +03:00
|
|
|
parser=setup_argument_parser)
|
2015-04-30 20:47:01 +03:00
|
|
|
@TestPathArg
|
2014-03-25 03:19:57 +04:00
|
|
|
def run_mochitest_a11y(self, test_paths, **kwargs):
|
|
|
|
return self.run_mochitest(test_paths, 'a11y', **kwargs)
|
2013-03-27 02:00:43 +04:00
|
|
|
|
2015-02-13 22:42:02 +03:00
|
|
|
@Command(
|
|
|
|
'webapprt-test-chrome',
|
|
|
|
category='testing',
|
2015-04-08 18:12:52 +03:00
|
|
|
conditions=[conditions.is_firefox],
|
2014-08-25 20:32:00 +04:00
|
|
|
description='Run a webapprt chrome mochitest (Web App Runtime with the browser chrome).',
|
2015-04-13 22:36:56 +03:00
|
|
|
parser=setup_argument_parser)
|
2015-04-30 20:47:01 +03:00
|
|
|
@TestPathArg
|
2014-03-25 03:19:57 +04:00
|
|
|
def run_mochitest_webapprt_chrome(self, test_paths, **kwargs):
|
|
|
|
return self.run_mochitest(test_paths, 'webapprt-chrome', **kwargs)
|
2013-08-23 18:06:16 +04:00
|
|
|
|
2015-02-13 22:42:02 +03:00
|
|
|
@Command(
|
|
|
|
'webapprt-test-content',
|
|
|
|
category='testing',
|
2015-04-08 18:12:52 +03:00
|
|
|
conditions=[conditions.is_firefox],
|
2014-08-25 20:32:00 +04:00
|
|
|
description='Run a webapprt content mochitest (Content rendering of the Web App Runtime).',
|
2015-04-13 22:36:56 +03:00
|
|
|
parser=setup_argument_parser)
|
2015-04-30 20:47:01 +03:00
|
|
|
@TestPathArg
|
2014-03-25 03:19:57 +04:00
|
|
|
def run_mochitest_webapprt_content(self, test_paths, **kwargs):
|
|
|
|
return self.run_mochitest(test_paths, 'webapprt-content', **kwargs)
|
2013-08-23 18:06:16 +04:00
|
|
|
|
2014-06-18 02:42:08 +04:00
|
|
|
@Command('mochitest', category='testing',
|
2015-02-13 22:42:02 +03:00
|
|
|
conditions=[conditions.is_firefox],
|
|
|
|
description='Run any flavor of mochitest (integration test).',
|
2015-04-13 22:36:56 +03:00
|
|
|
parser=setup_argument_parser)
|
2014-06-18 02:49:41 +04:00
|
|
|
@CommandArgument('-f', '--flavor', choices=FLAVORS.keys(),
|
2015-02-13 22:42:02 +03:00
|
|
|
help='Only run tests of this flavor.')
|
2015-04-30 20:47:01 +03:00
|
|
|
@TestPathArg
|
2014-06-18 22:19:45 +04:00
|
|
|
def run_mochitest_general(self, test_paths, flavor=None, test_objects=None,
|
2015-02-13 22:42:02 +03:00
|
|
|
**kwargs):
|
2014-06-18 02:42:08 +04:00
|
|
|
self._preruntest()
|
|
|
|
|
|
|
|
from mozbuild.testing import TestResolver
|
|
|
|
|
2014-06-18 22:19:45 +04:00
|
|
|
if test_objects:
|
|
|
|
tests = test_objects
|
|
|
|
else:
|
|
|
|
resolver = self._spawn(TestResolver)
|
|
|
|
tests = list(resolver.resolve_tests(paths=test_paths,
|
2015-02-13 22:42:02 +03:00
|
|
|
cwd=self._mach_context.cwd))
|
2014-06-18 02:42:08 +04:00
|
|
|
|
|
|
|
# Our current approach is to group the tests by suite and then perform
|
|
|
|
# an invocation for each suite. Ideally, this would be done
|
|
|
|
# automatically inside of core mochitest code. But it wasn't designed
|
|
|
|
# to do that.
|
|
|
|
#
|
|
|
|
# This does mean our output is less than ideal. When running tests from
|
|
|
|
# multiple suites, we see redundant summary lines. Hopefully once we
|
|
|
|
# have better machine readable output coming from mochitest land we can
|
|
|
|
# aggregate that here and improve the output formatting.
|
|
|
|
|
|
|
|
suites = {}
|
|
|
|
for test in tests:
|
2014-06-18 02:49:41 +04:00
|
|
|
# Filter out non-mochitests.
|
2014-06-18 02:42:08 +04:00
|
|
|
if test['flavor'] not in FLAVORS:
|
|
|
|
continue
|
|
|
|
|
2014-06-18 02:49:41 +04:00
|
|
|
if flavor and test['flavor'] != flavor:
|
|
|
|
continue
|
|
|
|
|
2014-06-18 02:42:08 +04:00
|
|
|
suite = FLAVORS[test['flavor']]
|
|
|
|
suites.setdefault(suite, []).append(test)
|
|
|
|
|
|
|
|
mochitest = self._spawn(MochitestRunner)
|
|
|
|
overall = None
|
|
|
|
for suite, tests in sorted(suites.items()):
|
2015-02-13 22:42:02 +03:00
|
|
|
result = mochitest.run_desktop_test(
|
|
|
|
self._mach_context,
|
|
|
|
test_paths=[
|
|
|
|
test['file_relpath'] for test in tests],
|
|
|
|
suite=suite,
|
2014-06-18 02:42:08 +04:00
|
|
|
**kwargs)
|
|
|
|
if result:
|
|
|
|
overall = result
|
|
|
|
|
|
|
|
return overall
|
|
|
|
|
|
|
|
def _preruntest(self):
|
2013-10-01 20:36:44 +04:00
|
|
|
from mozbuild.controller.building import BuildDriver
|
|
|
|
|
2012-11-02 21:32:40 +04:00
|
|
|
self._ensure_state_subdir_exists('.')
|
|
|
|
|
2013-10-01 20:36:44 +04:00
|
|
|
driver = self._spawn(BuildDriver)
|
|
|
|
driver.install_tests(remove=False)
|
|
|
|
|
2014-06-18 02:42:08 +04:00
|
|
|
def run_mochitest(self, test_paths, flavor, **kwargs):
|
|
|
|
self._preruntest()
|
|
|
|
|
2012-10-10 22:08:09 +04:00
|
|
|
mochitest = self._spawn(MochitestRunner)
|
2013-09-19 22:43:44 +04:00
|
|
|
|
2015-02-13 22:42:02 +03:00
|
|
|
return mochitest.run_desktop_test(
|
|
|
|
self._mach_context,
|
|
|
|
test_paths=test_paths,
|
|
|
|
suite=flavor,
|
|
|
|
**kwargs)
|
2013-08-28 18:08:50 +04:00
|
|
|
|
2014-03-25 03:19:57 +04:00
|
|
|
def run_mochitest_remote(self, test_paths, **kwargs):
|
2015-04-07 04:43:26 +03:00
|
|
|
if self.target_out:
|
2015-02-13 22:42:02 +03:00
|
|
|
host_webapps_dir = os.path.join(
|
2015-04-07 04:43:26 +03:00
|
|
|
self.target_out,
|
|
|
|
'data',
|
2015-02-13 22:42:02 +03:00
|
|
|
'local',
|
|
|
|
'webapps')
|
|
|
|
if not os.path.isdir(
|
|
|
|
os.path.join(
|
|
|
|
host_webapps_dir,
|
|
|
|
'test-container.gaiamobile.org')):
|
|
|
|
print(
|
|
|
|
ENG_BUILD_REQUIRED %
|
|
|
|
('mochitest-remote', host_webapps_dir))
|
2014-07-17 21:38:20 +04:00
|
|
|
return 1
|
|
|
|
|
2013-10-01 20:36:44 +04:00
|
|
|
from mozbuild.controller.building import BuildDriver
|
|
|
|
|
2013-08-28 18:08:50 +04:00
|
|
|
self._ensure_state_subdir_exists('.')
|
|
|
|
|
2013-10-01 20:36:44 +04:00
|
|
|
driver = self._spawn(BuildDriver)
|
|
|
|
driver.install_tests(remove=False)
|
|
|
|
|
2013-08-28 18:08:50 +04:00
|
|
|
mochitest = self._spawn(MochitestRunner)
|
2015-02-13 22:42:02 +03:00
|
|
|
return mochitest.run_b2g_test(
|
|
|
|
test_paths=test_paths,
|
|
|
|
**kwargs)
|
2013-09-19 22:43:44 +04:00
|
|
|
|
2014-03-25 03:19:57 +04:00
|
|
|
def run_mochitest_b2g_desktop(self, test_paths, **kwargs):
|
2015-02-13 22:42:02 +03:00
|
|
|
kwargs['profile'] = kwargs.get(
|
|
|
|
'profile') or os.environ.get('GAIA_PROFILE')
|
2014-07-17 21:38:20 +04:00
|
|
|
if not kwargs['profile'] or not os.path.isdir(kwargs['profile']):
|
|
|
|
print(GAIA_PROFILE_NOT_FOUND % 'mochitest-b2g-desktop')
|
|
|
|
return 1
|
|
|
|
|
|
|
|
if os.path.isfile(os.path.join(kwargs['profile'], 'extensions',
|
|
|
|
'httpd@gaiamobile.org')):
|
|
|
|
print(GAIA_PROFILE_IS_DEBUG % ('mochitest-b2g-desktop',
|
|
|
|
kwargs['profile']))
|
|
|
|
return 1
|
|
|
|
|
2013-10-01 20:36:44 +04:00
|
|
|
from mozbuild.controller.building import BuildDriver
|
|
|
|
|
2013-09-19 22:43:44 +04:00
|
|
|
self._ensure_state_subdir_exists('.')
|
|
|
|
|
2013-10-01 20:36:44 +04:00
|
|
|
driver = self._spawn(BuildDriver)
|
|
|
|
driver.install_tests(remove=False)
|
|
|
|
|
2013-09-19 22:43:44 +04:00
|
|
|
mochitest = self._spawn(MochitestRunner)
|
2014-03-25 03:19:57 +04:00
|
|
|
return mochitest.run_b2g_test(test_paths=test_paths, **kwargs)
|
2014-09-09 03:23:12 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
def run_mochitest_android(self, test_paths, **kwargs):
|
2015-04-10 04:11:56 +03:00
|
|
|
host_ret = verify_host_bin()
|
|
|
|
if host_ret != 0:
|
|
|
|
return host_ret
|
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
test_path = None
|
2015-04-10 04:11:56 +03:00
|
|
|
if test_paths:
|
|
|
|
if len(test_paths) > 1:
|
|
|
|
print('Warning: Only the first test path will be used.')
|
|
|
|
test_path = self._wrap_path_argument(test_paths[0]).relpath()
|
|
|
|
|
|
|
|
mochitest = self._spawn(MochitestRunner)
|
2015-04-30 20:47:01 +03:00
|
|
|
return mochitest.run_android_test(test_path, **kwargs)
|
|
|
|
|
2014-09-09 03:23:12 +04:00
|
|
|
|
|
|
|
@CommandProvider
|
|
|
|
class AndroidCommands(MachCommandBase):
|
2015-02-13 22:42:02 +03:00
|
|
|
|
2014-09-09 03:23:12 +04:00
|
|
|
@Command('robocop', category='testing',
|
2015-02-13 22:42:02 +03:00
|
|
|
conditions=[conditions.is_android],
|
2015-04-30 20:47:01 +03:00
|
|
|
description='Run a Robocop test.',
|
|
|
|
parser=setup_argument_parser)
|
2015-02-13 22:42:02 +03:00
|
|
|
@CommandArgument(
|
|
|
|
'test_path',
|
|
|
|
default=None,
|
|
|
|
nargs='?',
|
2014-09-09 03:23:12 +04:00
|
|
|
metavar='TEST',
|
2015-02-13 22:42:02 +03:00
|
|
|
help='Test to run. Can be specified as a Robocop test name (like "testLoad"), '
|
|
|
|
'or omitted. If omitted, the entire test suite is executed.')
|
2015-04-30 20:47:01 +03:00
|
|
|
def run_robocop(self, test_path, **kwargs):
|
2015-04-10 04:11:56 +03:00
|
|
|
host_ret = verify_host_bin()
|
|
|
|
if host_ret != 0:
|
|
|
|
return host_ret
|
2015-02-26 21:28:00 +03:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
if not kwargs.get('robocopIni'):
|
|
|
|
kwargs['robocopIni'] = os.path.join(self.topobjdir, '_tests', 'testing',
|
|
|
|
'mochitest', 'robocop.ini')
|
2014-09-09 03:23:12 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
if not kwargs.get('robocopApk'):
|
|
|
|
kwargs['robocopApk'] = os.path.join(self.topobjdir, 'build', 'mobile',
|
|
|
|
'robocop', 'robocop-debug.apk')
|
2015-04-10 04:11:56 +03:00
|
|
|
mochitest = self._spawn(MochitestRunner)
|
2015-04-30 20:47:01 +03:00
|
|
|
return mochitest.run_android_test(test_path, **kwargs)
|