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
|
|
|
|
2015-06-22 03:39:09 +03:00
|
|
|
from __future__ import absolute_import, unicode_literals
|
2012-09-26 20:43:53 +04:00
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
from argparse import Namespace
|
2015-05-05 23:41:59 +03:00
|
|
|
from collections import defaultdict
|
2013-04-05 02:17:23 +04:00
|
|
|
import logging
|
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
|
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
|
|
|
|
2014-07-17 21:38:20 +04:00
|
|
|
ENG_BUILD_REQUIRED = '''
|
2015-05-05 23:41:59 +03:00
|
|
|
The mochitest command requires an engineering build. It may be the case that
|
2014-07-17 21:38:20 +04:00
|
|
|
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
|
2015-05-05 23:41:59 +03:00
|
|
|
{}.
|
|
|
|
'''.lstrip()
|
|
|
|
|
|
|
|
SUPPORTED_TESTS_NOT_FOUND = '''
|
|
|
|
The mochitest command could not find any supported tests to run! The
|
|
|
|
following flavors and subsuites were found, but are either not supported on
|
|
|
|
{} builds, or were excluded on the command line:
|
|
|
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
Double check the command line you used, and make sure you are running in
|
|
|
|
context of the proper build. To switch build contexts, either run |mach|
|
|
|
|
from the appropriate objdir, or export the correct mozconfig:
|
|
|
|
|
|
|
|
$ export MOZCONFIG=path/to/mozconfig
|
2014-07-17 21:38:20 +04:00
|
|
|
'''.lstrip()
|
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
TESTS_NOT_FOUND = '''
|
|
|
|
The mochitest command could not find any mochitests under the following
|
|
|
|
test path(s):
|
|
|
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
Please check spelling and make sure there are mochitests living there.
|
|
|
|
'''.lstrip()
|
|
|
|
|
2016-01-22 02:59:44 +03:00
|
|
|
ROBOCOP_TESTS_NOT_FOUND = '''
|
|
|
|
The robocop command could not find any tests under the following
|
|
|
|
test path(s):
|
|
|
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
Please check spelling and make sure the named tests exist.
|
|
|
|
'''.lstrip()
|
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
NOW_RUNNING = '''
|
|
|
|
######
|
|
|
|
### Now running mochitest-{}.
|
|
|
|
######
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
2016-10-06 17:05:27 +03:00
|
|
|
SUPPORTED_APPS = ['firefox', 'android']
|
2015-05-05 23:41:59 +03:00
|
|
|
|
2016-07-20 18:13:30 +03:00
|
|
|
parser = None
|
|
|
|
|
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
|
|
|
|
|
|
|
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-05-05 23:41:59 +03:00
|
|
|
def resolve_tests(self, test_paths, test_objects=None, cwd=None):
|
|
|
|
if test_objects:
|
|
|
|
return test_objects
|
2013-08-28 18:08:50 +04:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
from mozbuild.testing import TestResolver
|
|
|
|
resolver = self._spawn(TestResolver)
|
|
|
|
tests = list(resolver.resolve_tests(paths=test_paths, cwd=cwd))
|
|
|
|
return tests
|
|
|
|
|
|
|
|
def run_desktop_test(self, context, tests=None, suite=None, **kwargs):
|
2015-04-30 20:47:01 +03:00
|
|
|
"""Runs a mochitest.
|
2015-05-05 04:28:16 +03:00
|
|
|
|
|
|
|
suite is the type of mochitest to run. It can be one of ('plain',
|
2016-03-08 00:32:26 +03:00
|
|
|
'chrome', 'browser', 'a11y', 'jetpack-package', 'jetpack-addon').
|
2012-09-26 20:43:53 +04:00
|
|
|
"""
|
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
|
|
|
|
|
|
|
|
# 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
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
from manifestparser import TestManifest
|
2016-10-03 15:23:14 +03:00
|
|
|
if tests and not options.manifestFile:
|
2015-08-27 02:51:15 +03:00
|
|
|
manifest = TestManifest()
|
|
|
|
manifest.tests.extend(tests)
|
|
|
|
options.manifestFile = manifest
|
|
|
|
|
|
|
|
# When developing mochitest-plain tests, it's often useful to be able to
|
|
|
|
# refresh the page to pick up modifications. Therefore leave the browser
|
|
|
|
# open if only running a single mochitest-plain test. This behaviour can
|
|
|
|
# be overridden by passing in --keep-open=false.
|
|
|
|
if len(tests) == 1 and options.keep_open is None and suite == 'plain':
|
|
|
|
options.keep_open = True
|
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()
|
2016-07-20 18:13:30 +03:00
|
|
|
result = mochitest.run_test_harness(parser, 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-05-05 23:41:59 +03:00
|
|
|
def run_android_test(self, context, tests, suite=None, **kwargs):
|
|
|
|
host_ret = verify_host_bin()
|
|
|
|
if host_ret != 0:
|
|
|
|
return host_ret
|
|
|
|
|
2015-04-10 04:11:56 +03:00
|
|
|
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)
|
2015-02-25 17:23:54 +03:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
from manifestparser import TestManifest
|
2016-10-03 15:23:14 +03:00
|
|
|
if tests and not options.manifestFile:
|
2015-08-27 02:51:15 +03:00
|
|
|
manifest = TestManifest()
|
|
|
|
manifest.tests.extend(tests)
|
|
|
|
options.manifestFile = manifest
|
2015-02-13 22:42:02 +03:00
|
|
|
|
2016-07-20 18:13:30 +03:00
|
|
|
return runtestsremote.run_test_harness(parser, options)
|
2015-04-10 22:31:36 +03:00
|
|
|
|
2015-07-09 21:30:01 +03:00
|
|
|
def run_robocop_test(self, context, tests, suite=None, **kwargs):
|
|
|
|
host_ret = verify_host_bin()
|
|
|
|
if host_ret != 0:
|
|
|
|
return host_ret
|
|
|
|
|
|
|
|
import imp
|
|
|
|
path = os.path.join(self.mochitest_dir, 'runrobocop.py')
|
|
|
|
with open(path, 'r') as fh:
|
|
|
|
imp.load_module('runrobocop', fh, path,
|
|
|
|
('.py', 'r', imp.PY_SOURCE))
|
|
|
|
import runrobocop
|
|
|
|
|
|
|
|
options = Namespace(**kwargs)
|
|
|
|
|
|
|
|
from manifestparser import TestManifest
|
2016-10-03 15:23:14 +03:00
|
|
|
if tests and not options.manifestFile:
|
2015-08-27 02:51:15 +03:00
|
|
|
manifest = TestManifest()
|
|
|
|
manifest.tests.extend(tests)
|
|
|
|
options.manifestFile = manifest
|
2015-07-09 21:30:01 +03:00
|
|
|
|
2016-07-20 18:13:30 +03:00
|
|
|
return runrobocop.run_test_harness(parser, options)
|
2015-04-10 22:31:36 +03:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
# parser
|
2013-08-28 18:08:50 +04:00
|
|
|
|
2015-12-28 11:23:37 +03: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')
|
2016-12-27 12:33:15 +03:00
|
|
|
if not os.path.exists(path):
|
|
|
|
path = os.path.join(here, "runtests.py")
|
|
|
|
|
2015-04-30 20:47:01 +03:00
|
|
|
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-09-02 00:07:53 +03:00
|
|
|
if conditions.is_android(build_obj):
|
|
|
|
# On Android, check for a connected device (and offer to start an
|
|
|
|
# emulator if appropriate) before running tests. This check must
|
|
|
|
# be done in this admittedly awkward place because
|
|
|
|
# MochitestArgumentParser initialization fails if no device is found.
|
|
|
|
from mozrunner.devices.android_device import verify_android_device
|
2015-09-17 01:58:52 +03:00
|
|
|
verify_android_device(build_obj, install=True, xre=True)
|
2015-09-02 00:07:53 +03:00
|
|
|
|
2016-07-20 18:13:30 +03:00
|
|
|
global parser
|
|
|
|
parser = MochitestArgumentParser()
|
|
|
|
return parser
|
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
|
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
def is_buildapp_in(*apps):
|
|
|
|
def is_buildapp_supported(cls):
|
|
|
|
for a in apps:
|
|
|
|
c = getattr(conditions, 'is_{}'.format(a), None)
|
2015-04-08 18:12:52 +03:00
|
|
|
if c and c(cls):
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
is_buildapp_supported.__doc__ = 'Must have a {} build.'.format(
|
|
|
|
' or '.join(apps))
|
|
|
|
return is_buildapp_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:
|
2016-09-28 15:28:04 +03:00
|
|
|
print('environment variable MOZ_HOST_BIN must be set to a directory containing host '
|
|
|
|
'xpcshell')
|
2015-04-10 04:11:56 +03:00
|
|
|
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):
|
2014-06-18 02:42:08 +04:00
|
|
|
@Command('mochitest', category='testing',
|
2015-05-05 23:41:59 +03:00
|
|
|
conditions=[is_buildapp_in(*SUPPORTED_APPS)],
|
2015-02-13 22:42:02 +03:00
|
|
|
description='Run any flavor of mochitest (integration test).',
|
2015-04-13 22:36:56 +03:00
|
|
|
parser=setup_argument_parser)
|
2015-08-27 02:51:15 +03:00
|
|
|
def run_mochitest_general(self, flavor=None, test_objects=None, resolve_tests=True, **kwargs):
|
2017-01-04 17:39:42 +03:00
|
|
|
from mochitest_options import ALL_FLAVORS
|
2016-12-20 18:50:43 +03:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
buildapp = None
|
|
|
|
for app in SUPPORTED_APPS:
|
|
|
|
if is_buildapp_in(app)(self):
|
|
|
|
buildapp = app
|
|
|
|
break
|
|
|
|
|
|
|
|
flavors = None
|
|
|
|
if flavor:
|
|
|
|
for fname, fobj in ALL_FLAVORS.iteritems():
|
|
|
|
if flavor in fobj['aliases']:
|
|
|
|
if buildapp not in fobj['enabled_apps']:
|
|
|
|
continue
|
|
|
|
flavors = [fname]
|
|
|
|
break
|
2014-06-18 22:19:45 +04:00
|
|
|
else:
|
2015-05-05 23:41:59 +03:00
|
|
|
flavors = [f for f, v in ALL_FLAVORS.iteritems() if buildapp in v['enabled_apps']]
|
2014-06-18 02:42:08 +04:00
|
|
|
|
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('.')
|
|
|
|
|
2015-06-05 20:28:29 +03:00
|
|
|
test_paths = kwargs['test_paths']
|
|
|
|
kwargs['test_paths'] = []
|
|
|
|
|
2012-10-10 22:08:09 +04:00
|
|
|
mochitest = self._spawn(MochitestRunner)
|
2015-08-27 02:51:15 +03:00
|
|
|
tests = []
|
|
|
|
if resolve_tests:
|
|
|
|
tests = mochitest.resolve_tests(test_paths, test_objects, cwd=self._mach_context.cwd)
|
2013-09-19 22:43:44 +04:00
|
|
|
|
2016-04-05 00:56:52 +03:00
|
|
|
driver = self._spawn(BuildDriver)
|
|
|
|
driver.install_tests(tests)
|
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
subsuite = kwargs.get('subsuite')
|
|
|
|
if subsuite == 'default':
|
|
|
|
kwargs['subsuite'] = None
|
2014-07-17 21:38:20 +04:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
suites = defaultdict(list)
|
|
|
|
unsupported = set()
|
|
|
|
for test in tests:
|
|
|
|
# Filter out non-mochitests and unsupported flavors.
|
|
|
|
if test['flavor'] not in ALL_FLAVORS:
|
|
|
|
continue
|
2013-10-01 20:36:44 +04:00
|
|
|
|
2016-10-31 20:04:42 +03:00
|
|
|
key = (test['flavor'], test.get('subsuite', ''))
|
2015-05-05 23:41:59 +03:00
|
|
|
if test['flavor'] not in flavors:
|
|
|
|
unsupported.add(key)
|
|
|
|
continue
|
2013-08-28 18:08:50 +04:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
if subsuite == 'default':
|
|
|
|
# "--subsuite default" means only run tests that don't have a subsuite
|
2016-10-31 20:04:42 +03:00
|
|
|
if test.get('subsuite'):
|
2015-05-05 23:41:59 +03:00
|
|
|
unsupported.add(key)
|
|
|
|
continue
|
2016-10-31 20:04:42 +03:00
|
|
|
elif subsuite and test.get('subsuite', '') != subsuite:
|
2015-05-05 23:41:59 +03:00
|
|
|
unsupported.add(key)
|
|
|
|
continue
|
2013-10-01 20:36:44 +04:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
suites[key].append(test)
|
2014-07-17 21:38:20 +04:00
|
|
|
|
2016-08-23 18:13:19 +03:00
|
|
|
if ('mochitest', 'media') in suites:
|
|
|
|
req = os.path.join('testing', 'tools', 'websocketprocessbridge',
|
|
|
|
'websocketprocessbridge_requirements.txt')
|
|
|
|
self.virtualenv_manager.activate()
|
|
|
|
self.virtualenv_manager.install_pip_requirements(req, require_hashes=False)
|
|
|
|
|
|
|
|
# sys.executable is used to start the websocketprocessbridge, though for some
|
|
|
|
# reason it doesn't get set when calling `activate_this.py` in the virtualenv.
|
|
|
|
sys.executable = self.virtualenv_manager.python_path
|
|
|
|
|
2015-08-27 02:51:15 +03:00
|
|
|
# This is a hack to introduce an option in mach to not send
|
|
|
|
# filtered tests to the mochitest harness. Mochitest harness will read
|
|
|
|
# the master manifest in that case.
|
|
|
|
if not resolve_tests:
|
|
|
|
for flavor in flavors:
|
|
|
|
key = (flavor, kwargs.get('subsuite'))
|
|
|
|
suites[key] = []
|
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
if not suites:
|
|
|
|
# Make it very clear why no tests were found
|
|
|
|
if not unsupported:
|
|
|
|
print(TESTS_NOT_FOUND.format('\n'.join(
|
|
|
|
sorted(list(test_paths or test_objects)))))
|
|
|
|
return 1
|
2014-07-17 21:38:20 +04:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
msg = []
|
|
|
|
for f, s in unsupported:
|
|
|
|
fobj = ALL_FLAVORS[f]
|
|
|
|
apps = fobj['enabled_apps']
|
|
|
|
name = fobj['aliases'][0]
|
|
|
|
if s:
|
|
|
|
name = '{} --subsuite {}'.format(name, s)
|
|
|
|
|
|
|
|
if buildapp not in apps:
|
|
|
|
reason = 'requires {}'.format(' or '.join(apps))
|
|
|
|
else:
|
|
|
|
reason = 'excluded by the command line'
|
|
|
|
msg.append(' mochitest -f {} ({})'.format(name, reason))
|
|
|
|
print(SUPPORTED_TESTS_NOT_FOUND.format(
|
|
|
|
buildapp, '\n'.join(sorted(msg))))
|
|
|
|
return 1
|
2013-10-01 20:36:44 +04:00
|
|
|
|
2016-10-06 17:05:27 +03:00
|
|
|
if buildapp == 'android':
|
2016-02-02 01:52:34 +03:00
|
|
|
from mozrunner.devices.android_device import grant_runtime_permissions
|
2016-08-05 23:40:08 +03:00
|
|
|
grant_runtime_permissions(self)
|
2015-05-05 23:41:59 +03:00
|
|
|
run_mochitest = mochitest.run_android_test
|
|
|
|
else:
|
|
|
|
run_mochitest = mochitest.run_desktop_test
|
2013-09-19 22:43:44 +04:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
overall = None
|
|
|
|
for (flavor, subsuite), tests in sorted(suites.items()):
|
|
|
|
fobj = ALL_FLAVORS[flavor]
|
|
|
|
msg = fobj['aliases'][0]
|
|
|
|
if subsuite:
|
|
|
|
msg = '{} with subsuite {}'.format(msg, subsuite)
|
|
|
|
print(NOW_RUNNING.format(msg))
|
2013-10-01 20:36:44 +04:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
harness_args = kwargs.copy()
|
2015-06-02 18:03:55 +03:00
|
|
|
harness_args['subsuite'] = subsuite
|
2015-05-05 23:41:59 +03:00
|
|
|
harness_args.update(fobj.get('extra_args', {}))
|
2014-09-09 03:23:12 +04:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
result = run_mochitest(
|
|
|
|
self._mach_context,
|
|
|
|
tests=tests,
|
|
|
|
suite=fobj['suite'],
|
|
|
|
**harness_args)
|
2015-04-10 04:11:56 +03:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
if result:
|
|
|
|
overall = result
|
2015-04-10 04:11:56 +03:00
|
|
|
|
2015-05-05 23:41:59 +03:00
|
|
|
# TODO consolidate summaries from all suites
|
|
|
|
return overall
|
2015-04-30 20:47:01 +03:00
|
|
|
|
2014-09-09 03:23:12 +04:00
|
|
|
|
|
|
|
@CommandProvider
|
2015-05-05 23:41:59 +03:00
|
|
|
class RobocopCommands(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-05-30 03:18:07 +03:00
|
|
|
@CommandArgument('--serve', default=False, action='store_true',
|
2015-12-21 22:22:06 +03:00
|
|
|
help='Run no tests but start the mochi.test web server '
|
|
|
|
'and launch Fennec with a test profile.')
|
2015-06-05 20:28:29 +03:00
|
|
|
def run_robocop(self, serve=False, **kwargs):
|
2015-05-30 03:18:07 +03:00
|
|
|
if serve:
|
|
|
|
kwargs['autorun'] = False
|
|
|
|
|
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'):
|
2015-11-09 23:55:38 +03:00
|
|
|
kwargs['robocopApk'] = os.path.join(self.topobjdir, 'mobile', 'android',
|
|
|
|
'tests', 'browser', 'robocop',
|
|
|
|
'robocop-debug.apk')
|
2015-05-05 23:41:59 +03:00
|
|
|
|
2015-06-02 00:45:48 +03:00
|
|
|
from mozbuild.controller.building import BuildDriver
|
|
|
|
self._ensure_state_subdir_exists('.')
|
|
|
|
|
2015-06-05 20:28:29 +03:00
|
|
|
test_paths = kwargs['test_paths']
|
|
|
|
kwargs['test_paths'] = []
|
|
|
|
|
2015-06-02 00:45:48 +03:00
|
|
|
from mozbuild.testing import TestResolver
|
|
|
|
resolver = self._spawn(TestResolver)
|
|
|
|
tests = list(resolver.resolve_tests(paths=test_paths, cwd=self._mach_context.cwd,
|
2015-12-21 22:22:06 +03:00
|
|
|
flavor='instrumentation', subsuite='robocop'))
|
2016-04-05 00:56:52 +03:00
|
|
|
driver = self._spawn(BuildDriver)
|
|
|
|
driver.install_tests(tests)
|
2015-05-05 23:41:59 +03:00
|
|
|
|
2016-01-22 02:59:44 +03:00
|
|
|
if len(tests) < 1:
|
|
|
|
print(ROBOCOP_TESTS_NOT_FOUND.format('\n'.join(
|
|
|
|
sorted(list(test_paths)))))
|
|
|
|
return 1
|
|
|
|
|
2016-02-02 01:52:34 +03:00
|
|
|
from mozrunner.devices.android_device import grant_runtime_permissions
|
2016-08-05 23:40:08 +03:00
|
|
|
grant_runtime_permissions(self)
|
2016-02-02 01:52:34 +03:00
|
|
|
|
2015-04-10 04:11:56 +03:00
|
|
|
mochitest = self._spawn(MochitestRunner)
|
2015-07-09 21:30:01 +03:00
|
|
|
return mochitest.run_robocop_test(self._mach_context, tests, 'robocop', **kwargs)
|
2015-05-05 23:41:59 +03:00
|
|
|
|
|
|
|
|
2015-09-21 04:32:03 +03:00
|
|
|
# NOTE python/mach/mach/commands/commandinfo.py references this function
|
|
|
|
# by name. If this function is renamed or removed, that file should
|
|
|
|
# be updated accordingly as well.
|
2015-05-05 23:41:59 +03:00
|
|
|
def REMOVED(cls):
|
|
|
|
"""Command no longer exists! Use |mach mochitest| instead.
|
|
|
|
|
|
|
|
The |mach mochitest| command will automatically detect which flavors and
|
|
|
|
subsuites exist in a given directory. If desired, flavors and subsuites
|
|
|
|
can be restricted using `--flavor` and `--subsuite` respectively. E.g:
|
|
|
|
|
|
|
|
$ ./mach mochitest dom/indexedDB
|
|
|
|
|
|
|
|
will run all of the plain, chrome and browser-chrome mochitests in that
|
|
|
|
directory. To only run the plain mochitests:
|
|
|
|
|
|
|
|
$ ./mach mochitest -f plain dom/indexedDB
|
|
|
|
"""
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
@CommandProvider
|
|
|
|
class DeprecatedCommands(MachCommandBase):
|
|
|
|
@Command('mochitest-plain', category='testing', conditions=[REMOVED])
|
|
|
|
def mochitest_plain(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@Command('mochitest-chrome', category='testing', conditions=[REMOVED])
|
|
|
|
def mochitest_chrome(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@Command('mochitest-browser', category='testing', conditions=[REMOVED])
|
|
|
|
def mochitest_browser(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@Command('mochitest-devtools', category='testing', conditions=[REMOVED])
|
|
|
|
def mochitest_devtools(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@Command('mochitest-a11y', category='testing', conditions=[REMOVED])
|
|
|
|
def mochitest_a11y(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@Command('jetpack-addon', category='testing', conditions=[REMOVED])
|
|
|
|
def jetpack_addon(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
@Command('jetpack-package', category='testing', conditions=[REMOVED])
|
|
|
|
def jetpack_package(self):
|
|
|
|
pass
|