2013-09-09 23:37:38 +04:00
|
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
2015-06-22 03:39:09 +03:00
|
|
|
from __future__ import absolute_import, print_function, unicode_literals
|
2013-09-09 23:37:38 +04:00
|
|
|
|
2015-08-27 02:51:15 +03:00
|
|
|
import json
|
2013-09-09 23:37:38 +04:00
|
|
|
import os
|
2014-06-18 22:21:12 +04:00
|
|
|
import sys
|
2015-08-27 02:51:15 +03:00
|
|
|
import tempfile
|
2015-09-01 08:52:07 +03:00
|
|
|
import subprocess
|
|
|
|
import shutil
|
2013-09-09 23:37:38 +04:00
|
|
|
|
|
|
|
from mach.decorators import (
|
|
|
|
CommandArgument,
|
|
|
|
CommandProvider,
|
|
|
|
Command,
|
|
|
|
)
|
|
|
|
|
|
|
|
from mozbuild.base import MachCommandBase
|
2015-09-14 17:40:35 +03:00
|
|
|
from mozbuild.base import MachCommandConditions as conditions
|
2015-08-27 02:51:15 +03:00
|
|
|
from argparse import ArgumentParser
|
2013-09-09 23:37:38 +04:00
|
|
|
|
|
|
|
|
2014-06-18 22:21:12 +04:00
|
|
|
UNKNOWN_TEST = '''
|
|
|
|
I was unable to find tests in the argument(s) given.
|
2013-09-09 23:37:38 +04:00
|
|
|
|
2014-06-18 22:21:12 +04:00
|
|
|
You need to specify a test directory, filename, test suite name, or
|
|
|
|
abbreviation.
|
2013-09-09 23:37:38 +04:00
|
|
|
|
2014-06-18 22:21:12 +04:00
|
|
|
It's possible my little brain doesn't know about the type of test you are
|
|
|
|
trying to execute. If you suspect this, please request support by filing
|
|
|
|
a bug at
|
|
|
|
https://bugzilla.mozilla.org/enter_bug.cgi?product=Testing&component=General.
|
|
|
|
'''.strip()
|
2013-09-09 23:37:38 +04:00
|
|
|
|
2014-06-18 22:21:12 +04:00
|
|
|
UNKNOWN_FLAVOR = '''
|
|
|
|
I know you are trying to run a %s test. Unfortunately, I can't run those
|
|
|
|
tests yet. Sorry!
|
2013-09-09 23:37:38 +04:00
|
|
|
'''.strip()
|
|
|
|
|
|
|
|
MOCHITEST_CHUNK_BY_DIR = 4
|
|
|
|
MOCHITEST_TOTAL_CHUNKS = 5
|
|
|
|
|
|
|
|
TEST_SUITES = {
|
2014-01-02 19:19:35 +04:00
|
|
|
'cppunittest': {
|
|
|
|
'aliases': ('Cpp', 'cpp'),
|
|
|
|
'mach_command': 'cppunittest',
|
|
|
|
'kwargs': {'test_file': None},
|
|
|
|
},
|
2013-09-09 23:37:38 +04:00
|
|
|
'crashtest': {
|
|
|
|
'aliases': ('C', 'Rc', 'RC', 'rc'),
|
|
|
|
'mach_command': 'crashtest',
|
|
|
|
'kwargs': {'test_file': None},
|
|
|
|
},
|
|
|
|
'crashtest-ipc': {
|
|
|
|
'aliases': ('Cipc', 'cipc'),
|
|
|
|
'mach_command': 'crashtest-ipc',
|
|
|
|
'kwargs': {'test_file': None},
|
|
|
|
},
|
|
|
|
'jetpack': {
|
|
|
|
'aliases': ('J',),
|
|
|
|
'mach_command': 'jetpack-test',
|
|
|
|
'kwargs': {},
|
|
|
|
},
|
2014-04-29 18:22:50 +04:00
|
|
|
'check-spidermonkey': {
|
|
|
|
'aliases': ('Sm', 'sm'),
|
|
|
|
'mach_command': 'check-spidermonkey',
|
|
|
|
'kwargs': {'valgrind': False},
|
2014-03-27 18:16:14 +04:00
|
|
|
},
|
2013-09-09 23:37:38 +04:00
|
|
|
'mochitest-a11y': {
|
2014-06-18 03:03:49 +04:00
|
|
|
'mach_command': 'mochitest',
|
|
|
|
'kwargs': {'flavor': 'a11y', 'test_paths': None},
|
2013-09-09 23:37:38 +04:00
|
|
|
},
|
|
|
|
'mochitest-browser': {
|
|
|
|
'aliases': ('bc', 'BC', 'Bc'),
|
2015-05-30 00:05:34 +03:00
|
|
|
'mach_command': 'mochitest',
|
2014-06-18 03:03:49 +04:00
|
|
|
'kwargs': {'flavor': 'browser-chrome', 'test_paths': None},
|
2013-09-09 23:37:38 +04:00
|
|
|
},
|
|
|
|
'mochitest-chrome': {
|
2014-06-18 03:03:49 +04:00
|
|
|
'mach_command': 'mochitest',
|
|
|
|
'kwargs': {'flavor': 'chrome', 'test_paths': None},
|
2013-09-09 23:37:38 +04:00
|
|
|
},
|
2014-03-25 20:52:53 +04:00
|
|
|
'mochitest-devtools': {
|
|
|
|
'aliases': ('dt', 'DT', 'Dt'),
|
2015-05-30 00:05:34 +03:00
|
|
|
'mach_command': 'mochitest',
|
2014-06-18 03:03:49 +04:00
|
|
|
'kwargs': {'subsuite': 'devtools', 'test_paths': None},
|
2014-03-25 20:52:53 +04:00
|
|
|
},
|
2013-09-09 23:37:38 +04:00
|
|
|
'mochitest-plain': {
|
2014-06-18 03:03:49 +04:00
|
|
|
'mach_command': 'mochitest',
|
2015-05-30 00:05:34 +03:00
|
|
|
'kwargs': {'flavor': 'plain', 'test_paths': None},
|
2013-09-09 23:37:38 +04:00
|
|
|
},
|
2015-04-09 18:46:00 +03:00
|
|
|
'luciddream': {
|
|
|
|
'mach_command': 'luciddream',
|
|
|
|
'kwargs': {'test_paths': None},
|
|
|
|
},
|
2013-09-09 23:37:38 +04:00
|
|
|
'reftest': {
|
|
|
|
'aliases': ('RR', 'rr', 'Rr'),
|
|
|
|
'mach_command': 'reftest',
|
2015-09-14 12:46:34 +03:00
|
|
|
'kwargs': {'test_file': None},
|
2013-09-09 23:37:38 +04:00
|
|
|
},
|
|
|
|
'reftest-ipc': {
|
|
|
|
'aliases': ('Ripc',),
|
|
|
|
'mach_command': 'reftest-ipc',
|
|
|
|
'kwargs': {'test_file': None},
|
|
|
|
},
|
2015-05-28 22:27:23 +03:00
|
|
|
'web-platform-tests': {
|
|
|
|
'aliases': ('wpt',),
|
|
|
|
'mach_command': 'web-platform-tests',
|
|
|
|
'kwargs': {}
|
|
|
|
},
|
2013-12-19 05:36:08 +04:00
|
|
|
'valgrind': {
|
|
|
|
'aliases': ('V', 'v'),
|
|
|
|
'mach_command': 'valgrind-test',
|
|
|
|
'kwargs': {},
|
|
|
|
},
|
2013-09-09 23:37:38 +04:00
|
|
|
'xpcshell': {
|
|
|
|
'aliases': ('X', 'x'),
|
|
|
|
'mach_command': 'xpcshell-test',
|
|
|
|
'kwargs': {'test_file': 'all'},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2014-06-18 22:21:12 +04:00
|
|
|
# Maps test flavors to metadata on how to run that test.
|
|
|
|
TEST_FLAVORS = {
|
|
|
|
'a11y': {
|
|
|
|
'mach_command': 'mochitest',
|
|
|
|
'kwargs': {'flavor': 'a11y', 'test_paths': []},
|
|
|
|
},
|
|
|
|
'browser-chrome': {
|
|
|
|
'mach_command': 'mochitest',
|
|
|
|
'kwargs': {'flavor': 'browser-chrome', 'test_paths': []},
|
|
|
|
},
|
|
|
|
'chrashtest': { },
|
|
|
|
'chrome': {
|
|
|
|
'mach_command': 'mochitest',
|
|
|
|
'kwargs': {'flavor': 'chrome', 'test_paths': []},
|
|
|
|
},
|
|
|
|
'mochitest': {
|
|
|
|
'mach_command': 'mochitest',
|
|
|
|
'kwargs': {'flavor': 'mochitest', 'test_paths': []},
|
|
|
|
},
|
2015-09-14 12:46:34 +03:00
|
|
|
'reftest': { },
|
2014-06-18 22:21:12 +04:00
|
|
|
'steeplechase': { },
|
2015-05-28 22:27:23 +03:00
|
|
|
'web-platform-tests': {
|
|
|
|
'mach_command': 'web-platform-tests',
|
|
|
|
'kwargs': {'include': []}
|
|
|
|
},
|
2014-06-18 22:21:12 +04:00
|
|
|
'webapprt-chrome': {
|
|
|
|
'mach_command': 'mochitest',
|
|
|
|
'kwargs': {'flavor': 'webapprt-chrome', 'test_paths': []},
|
|
|
|
},
|
|
|
|
'xpcshell': {
|
|
|
|
'mach_command': 'xpcshell-test',
|
|
|
|
'kwargs': {'test_paths': []},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-09 23:37:38 +04:00
|
|
|
for i in range(1, MOCHITEST_TOTAL_CHUNKS + 1):
|
|
|
|
TEST_SUITES['mochitest-%d' %i] = {
|
|
|
|
'aliases': ('M%d' % i, 'm%d' % i),
|
2014-06-18 03:03:49 +04:00
|
|
|
'mach_command': 'mochitest',
|
2013-09-09 23:37:38 +04:00
|
|
|
'kwargs': {
|
2014-06-18 03:03:49 +04:00
|
|
|
'flavor': 'mochitest',
|
2015-05-30 00:05:34 +03:00
|
|
|
'subsuite': 'default',
|
2013-09-09 23:37:38 +04:00
|
|
|
'chunk_by_dir': MOCHITEST_CHUNK_BY_DIR,
|
|
|
|
'total_chunks': MOCHITEST_TOTAL_CHUNKS,
|
|
|
|
'this_chunk': i,
|
2014-06-18 03:03:49 +04:00
|
|
|
'test_paths': None,
|
2013-09-09 23:37:38 +04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_HELP = '''
|
2014-06-18 22:21:12 +04:00
|
|
|
Test or tests to run. Tests can be specified by filename, directory, suite
|
|
|
|
name or suite alias.
|
|
|
|
|
2013-09-09 23:37:38 +04:00
|
|
|
The following test suites and aliases are supported: %s
|
|
|
|
''' % ', '.join(sorted(TEST_SUITES))
|
|
|
|
TEST_HELP = TEST_HELP.strip()
|
|
|
|
|
|
|
|
|
|
|
|
@CommandProvider
|
|
|
|
class Test(MachCommandBase):
|
2014-08-09 17:37:29 +04:00
|
|
|
@Command('test', category='testing', description='Run tests (detects the kind of test and runs it).')
|
2013-09-09 23:37:38 +04:00
|
|
|
@CommandArgument('what', default=None, nargs='*', help=TEST_HELP)
|
|
|
|
def test(self, what):
|
2015-06-11 18:32:02 +03:00
|
|
|
"""Run tests from names or paths.
|
|
|
|
|
|
|
|
mach test accepts arguments specifying which tests to run. Each argument
|
|
|
|
can be:
|
|
|
|
|
|
|
|
* The path to a test file
|
|
|
|
* A directory containing tests
|
|
|
|
* A test suite name
|
|
|
|
* An alias to a test suite name (codes used on TreeHerder)
|
|
|
|
|
|
|
|
When paths or directories are given, they are first resolved to test
|
|
|
|
files known to the build system.
|
|
|
|
|
|
|
|
If resolved tests belong to more than one test type/flavor/harness,
|
|
|
|
the harness for each relevant type/flavor will be invoked. e.g. if
|
|
|
|
you specify a directory with xpcshell and browser chrome mochitests,
|
|
|
|
both harnesses will be invoked.
|
|
|
|
"""
|
2014-06-18 22:21:12 +04:00
|
|
|
from mozbuild.testing import TestResolver
|
|
|
|
|
|
|
|
# Parse arguments and assemble a test "plan."
|
|
|
|
run_suites = set()
|
|
|
|
run_tests = []
|
|
|
|
resolver = self._spawn(TestResolver)
|
|
|
|
|
2013-09-09 23:37:38 +04:00
|
|
|
for entry in what:
|
2014-06-18 22:21:12 +04:00
|
|
|
# If the path matches the name or alias of an entire suite, run
|
|
|
|
# the entire suite.
|
|
|
|
if entry in TEST_SUITES:
|
|
|
|
run_suites.add(entry)
|
|
|
|
continue
|
|
|
|
suitefound = False
|
|
|
|
for suite, v in TEST_SUITES.items():
|
|
|
|
if entry in v.get('aliases', []):
|
|
|
|
run_suites.add(suite)
|
|
|
|
suitefound = True
|
|
|
|
if suitefound:
|
|
|
|
continue
|
2013-09-09 23:37:38 +04:00
|
|
|
|
2014-06-18 22:21:12 +04:00
|
|
|
# Now look for file/directory matches in the TestResolver.
|
2014-07-02 01:21:00 +04:00
|
|
|
relpath = self._wrap_path_argument(entry).relpath()
|
|
|
|
tests = list(resolver.resolve_tests(paths=[relpath]))
|
2014-06-18 22:21:12 +04:00
|
|
|
run_tests.extend(tests)
|
2013-09-09 23:37:38 +04:00
|
|
|
|
2014-06-18 22:21:12 +04:00
|
|
|
if not tests:
|
|
|
|
print('UNKNOWN TEST: %s' % entry, file=sys.stderr)
|
2013-09-09 23:37:38 +04:00
|
|
|
|
2014-06-18 22:21:12 +04:00
|
|
|
if not run_suites and not run_tests:
|
|
|
|
print(UNKNOWN_TEST)
|
|
|
|
return 1
|
|
|
|
|
|
|
|
status = None
|
|
|
|
for suite_name in run_suites:
|
|
|
|
suite = TEST_SUITES[suite_name]
|
2013-09-09 23:37:38 +04:00
|
|
|
|
|
|
|
if 'mach_command' in suite:
|
2014-06-18 22:21:12 +04:00
|
|
|
res = self._mach_context.commands.dispatch(
|
|
|
|
suite['mach_command'], self._mach_context,
|
|
|
|
**suite['kwargs'])
|
|
|
|
if res:
|
|
|
|
status = res
|
2013-09-09 23:37:38 +04:00
|
|
|
|
2014-06-18 22:21:12 +04:00
|
|
|
elif 'make_target' in suite:
|
|
|
|
res = self._run_make(target=suite['make_target'],
|
2013-09-09 23:37:38 +04:00
|
|
|
pass_thru=True)
|
2014-06-18 22:21:12 +04:00
|
|
|
if res:
|
|
|
|
status = res
|
2013-09-09 23:37:38 +04:00
|
|
|
|
2015-02-06 23:36:59 +03:00
|
|
|
buckets = {}
|
2014-06-18 22:21:12 +04:00
|
|
|
for test in run_tests:
|
2015-02-06 23:36:59 +03:00
|
|
|
key = (test['flavor'], test['subsuite'])
|
|
|
|
buckets.setdefault(key, []).append(test)
|
2013-09-09 23:37:38 +04:00
|
|
|
|
2015-02-06 23:36:59 +03:00
|
|
|
for (flavor, subsuite), tests in sorted(buckets.items()):
|
2014-06-18 22:21:12 +04:00
|
|
|
if flavor not in TEST_FLAVORS:
|
|
|
|
print(UNKNOWN_FLAVOR % flavor)
|
|
|
|
status = 1
|
|
|
|
continue
|
2013-09-09 23:37:38 +04:00
|
|
|
|
2014-06-18 22:21:12 +04:00
|
|
|
m = TEST_FLAVORS[flavor]
|
|
|
|
if 'mach_command' not in m:
|
|
|
|
print(UNKNOWN_FLAVOR % flavor)
|
|
|
|
status = 1
|
|
|
|
continue
|
|
|
|
|
2015-02-06 23:36:59 +03:00
|
|
|
kwargs = dict(m['kwargs'])
|
|
|
|
kwargs['subsuite'] = subsuite
|
|
|
|
|
2014-06-18 22:21:12 +04:00
|
|
|
res = self._mach_context.commands.dispatch(
|
|
|
|
m['mach_command'], self._mach_context,
|
2015-02-06 23:36:59 +03:00
|
|
|
test_objects=tests, **kwargs)
|
2014-06-18 22:21:12 +04:00
|
|
|
if res:
|
|
|
|
status = res
|
|
|
|
|
|
|
|
return status
|
2013-09-09 23:37:38 +04:00
|
|
|
|
2014-01-02 19:19:35 +04:00
|
|
|
|
|
|
|
@CommandProvider
|
|
|
|
class MachCommands(MachCommandBase):
|
|
|
|
@Command('cppunittest', category='testing',
|
2014-08-09 17:37:29 +04:00
|
|
|
description='Run cpp unit tests (C++ tests).')
|
2014-01-02 19:19:35 +04:00
|
|
|
@CommandArgument('test_files', nargs='*', metavar='N',
|
|
|
|
help='Test to run. Can be specified as one or more files or ' \
|
|
|
|
'directories, or omitted. If omitted, the entire test suite is ' \
|
|
|
|
'executed.')
|
|
|
|
|
|
|
|
def run_cppunit_test(self, **params):
|
2014-10-28 16:38:21 +03:00
|
|
|
import mozinfo
|
2015-07-16 17:38:40 +03:00
|
|
|
from mozlog import commandline
|
2014-07-10 17:33:39 +04:00
|
|
|
log = commandline.setup_logging("cppunittest",
|
|
|
|
{},
|
|
|
|
{"tbpl": sys.stdout})
|
2014-01-02 19:19:35 +04:00
|
|
|
|
|
|
|
# See if we have crash symbols
|
|
|
|
symbols_path = os.path.join(self.distdir, 'crashreporter-symbols')
|
|
|
|
if not os.path.isdir(symbols_path):
|
|
|
|
symbols_path = None
|
|
|
|
|
2015-09-14 17:40:35 +03:00
|
|
|
# If no tests specified, run all tests in main manifest
|
|
|
|
tests = params['test_files']
|
|
|
|
if len(tests) == 0:
|
|
|
|
tests = [os.path.join(self.distdir, 'cppunittests')]
|
|
|
|
manifest_path = os.path.join(self.topsrcdir, 'testing', 'cppunittest.ini')
|
|
|
|
else:
|
|
|
|
manifest_path = None
|
|
|
|
|
|
|
|
if conditions.is_android(self):
|
|
|
|
from mozrunner.devices.android_device import verify_android_device
|
|
|
|
verify_android_device(self, install=False)
|
|
|
|
return self.run_android_test(tests, symbols_path, manifest_path, log)
|
|
|
|
|
|
|
|
return self.run_desktop_test(tests, symbols_path, manifest_path, log)
|
|
|
|
|
|
|
|
def run_desktop_test(self, tests, symbols_path, manifest_path, log):
|
|
|
|
import runcppunittests as cppunittests
|
|
|
|
from mozlog import commandline
|
|
|
|
|
|
|
|
parser = cppunittests.CPPUnittestOptions()
|
|
|
|
commandline.add_logging_group(parser)
|
|
|
|
options, args = parser.parse_args()
|
|
|
|
|
|
|
|
options.symbols_path = symbols_path
|
|
|
|
options.manifest_path = manifest_path
|
|
|
|
options.xre_path = self.bindir
|
|
|
|
|
|
|
|
try:
|
|
|
|
result = cppunittests.run_test_harness(options, tests)
|
|
|
|
except Exception as e:
|
|
|
|
log.error("Caught exception running cpp unit tests: %s" % str(e))
|
|
|
|
result = False
|
|
|
|
raise
|
|
|
|
|
|
|
|
return 0 if result else 1
|
|
|
|
|
|
|
|
def run_android_test(self, tests, symbols_path, manifest_path, log):
|
|
|
|
import remotecppunittests as remotecppunittests
|
|
|
|
from mozlog import commandline
|
|
|
|
|
|
|
|
parser = remotecppunittests.RemoteCPPUnittestOptions()
|
|
|
|
commandline.add_logging_group(parser)
|
|
|
|
options, args = parser.parse_args()
|
|
|
|
|
|
|
|
options.symbols_path = symbols_path
|
|
|
|
options.manifest_path = manifest_path
|
|
|
|
options.xre_path = self.bindir
|
|
|
|
options.dm_trans = "adb"
|
|
|
|
options.local_lib = self.bindir.replace('bin', 'fennec')
|
|
|
|
for file in os.listdir(os.path.join(self.topobjdir, "dist")):
|
|
|
|
if file.endswith(".apk") and file.startswith("fennec"):
|
|
|
|
options.local_apk = os.path.join(self.topobjdir, "dist", file)
|
|
|
|
log.info("using APK: " + options.local_apk)
|
|
|
|
break
|
|
|
|
|
2014-01-02 19:19:35 +04:00
|
|
|
try:
|
2015-09-14 17:40:35 +03:00
|
|
|
result = remotecppunittests.run_test_harness(options, tests)
|
2014-07-10 17:33:39 +04:00
|
|
|
except Exception as e:
|
|
|
|
log.error("Caught exception running cpp unit tests: %s" % str(e))
|
2014-01-02 19:19:35 +04:00
|
|
|
result = False
|
2015-09-14 17:40:35 +03:00
|
|
|
raise
|
2014-01-02 19:19:35 +04:00
|
|
|
|
|
|
|
return 0 if result else 1
|
2014-03-27 18:16:14 +04:00
|
|
|
|
2015-05-16 01:41:50 +03:00
|
|
|
def executable_name(name):
|
|
|
|
return name + '.exe' if sys.platform.startswith('win') else name
|
|
|
|
|
2014-03-27 18:16:14 +04:00
|
|
|
@CommandProvider
|
2014-04-29 18:22:50 +04:00
|
|
|
class CheckSpiderMonkeyCommand(MachCommandBase):
|
2014-08-09 17:37:29 +04:00
|
|
|
@Command('check-spidermonkey', category='testing', description='Run SpiderMonkey tests (JavaScript engine).')
|
2014-03-27 18:16:14 +04:00
|
|
|
@CommandArgument('--valgrind', action='store_true', help='Run jit-test suite with valgrind flag')
|
|
|
|
|
2014-04-29 18:22:50 +04:00
|
|
|
def run_checkspidermonkey(self, **params):
|
2014-03-27 18:16:14 +04:00
|
|
|
import subprocess
|
|
|
|
import sys
|
|
|
|
|
2015-05-16 01:41:50 +03:00
|
|
|
js = os.path.join(self.bindir, executable_name('js'))
|
2014-04-29 18:22:50 +04:00
|
|
|
|
|
|
|
print('Running jit-tests')
|
|
|
|
jittest_cmd = [os.path.join(self.topsrcdir, 'js', 'src', 'jit-test', 'jit_test.py'),
|
2015-05-07 18:28:55 +03:00
|
|
|
js, '--no-slow', '--jitflags=all']
|
2014-03-27 18:16:14 +04:00
|
|
|
if params['valgrind']:
|
2014-04-29 18:22:50 +04:00
|
|
|
jittest_cmd.append('--valgrind')
|
|
|
|
|
|
|
|
jittest_result = subprocess.call(jittest_cmd)
|
|
|
|
|
|
|
|
print('running jstests')
|
|
|
|
jstest_cmd = [os.path.join(self.topsrcdir, 'js', 'src', 'tests', 'jstests.py'),
|
2015-05-07 18:28:55 +03:00
|
|
|
js, '--jitflags=all']
|
2014-04-29 18:22:50 +04:00
|
|
|
jstest_result = subprocess.call(jstest_cmd)
|
|
|
|
|
|
|
|
print('running jsapi-tests')
|
2015-05-16 01:41:50 +03:00
|
|
|
jsapi_tests_cmd = [os.path.join(self.bindir, executable_name('jsapi-tests'))]
|
2014-04-29 18:22:50 +04:00
|
|
|
jsapi_tests_result = subprocess.call(jsapi_tests_cmd)
|
|
|
|
|
|
|
|
print('running check-style')
|
|
|
|
check_style_cmd = [sys.executable, os.path.join(self.topsrcdir, 'config', 'check_spidermonkey_style.py')]
|
|
|
|
check_style_result = subprocess.call(check_style_cmd, cwd=os.path.join(self.topsrcdir, 'js', 'src'))
|
|
|
|
|
2015-07-09 15:35:29 +03:00
|
|
|
print('running check-masm')
|
|
|
|
check_masm_cmd = [sys.executable, os.path.join(self.topsrcdir, 'config', 'check_macroassembler_style.py')]
|
|
|
|
check_masm_result = subprocess.call(check_masm_cmd, cwd=os.path.join(self.topsrcdir, 'js', 'src'))
|
|
|
|
|
|
|
|
all_passed = jittest_result and jstest_result and jsapi_tests_result and check_style_result and check_masm_result
|
2014-03-27 18:16:14 +04:00
|
|
|
|
2014-04-29 18:22:50 +04:00
|
|
|
return all_passed
|
2015-05-16 01:41:50 +03:00
|
|
|
|
|
|
|
@CommandProvider
|
|
|
|
class JsapiTestsCommand(MachCommandBase):
|
|
|
|
@Command('jsapi-tests', category='testing', description='Run jsapi tests (JavaScript engine).')
|
|
|
|
@CommandArgument('test_name', nargs='?', metavar='N',
|
|
|
|
help='Test to run. Can be a prefix or omitted. If omitted, the entire ' \
|
|
|
|
'test suite is executed.')
|
|
|
|
|
|
|
|
def run_jsapitests(self, **params):
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
bin_suffix = ''
|
|
|
|
if sys.platform.startswith('win'):
|
|
|
|
bin_suffix = '.exe'
|
|
|
|
|
|
|
|
print('running jsapi-tests')
|
|
|
|
jsapi_tests_cmd = [os.path.join(self.bindir, executable_name('jsapi-tests'))]
|
|
|
|
if params['test_name']:
|
|
|
|
jsapi_tests_cmd.append(params['test_name'])
|
|
|
|
|
|
|
|
jsapi_tests_result = subprocess.call(jsapi_tests_cmd)
|
|
|
|
|
|
|
|
return jsapi_tests_result
|
2015-05-29 01:57:21 +03:00
|
|
|
|
|
|
|
|
|
|
|
@CommandProvider
|
|
|
|
class PushToTry(MachCommandBase):
|
|
|
|
|
2015-08-06 20:19:31 +03:00
|
|
|
def validate_args(self, paths, tests, tags, builds, platforms):
|
|
|
|
if not any([len(paths), tests, tags]):
|
|
|
|
print("Paths, tests, or tags must be specified.")
|
2015-05-29 01:57:21 +03:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if platforms is None:
|
|
|
|
platforms = os.environ['AUTOTRY_PLATFORM_HINT']
|
|
|
|
|
|
|
|
for p in paths:
|
|
|
|
p = os.path.normpath(os.path.abspath(p))
|
|
|
|
if not p.startswith(self.topsrcdir):
|
|
|
|
print('Specified path "%s" is outside of the srcdir, unable to'
|
|
|
|
' specify tests outside of the srcdir' % p)
|
|
|
|
sys.exit(1)
|
|
|
|
if len(p) <= len(self.topsrcdir):
|
|
|
|
print('Specified path "%s" is at the top of the srcdir and would'
|
|
|
|
' select all tests.' % p)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
return builds, platforms
|
|
|
|
|
2015-06-14 08:22:44 +03:00
|
|
|
@Command('try', category='testing', description='Push selected tests to the try server')
|
2015-05-29 01:57:21 +03:00
|
|
|
@CommandArgument('paths', nargs='*', help='Paths to search for tests to run on try.')
|
2015-06-14 08:22:44 +03:00
|
|
|
@CommandArgument('-n', dest='verbose', action='store_true', default=False,
|
2015-05-29 01:57:21 +03:00
|
|
|
help='Print detailed information about the resulting test selection '
|
|
|
|
'and commands performed.')
|
|
|
|
@CommandArgument('-p', dest='platforms', required='AUTOTRY_PLATFORM_HINT' not in os.environ,
|
|
|
|
help='Platforms to run. (required if not found in the environment)')
|
|
|
|
@CommandArgument('-u', dest='tests',
|
2015-06-14 08:22:44 +03:00
|
|
|
help='Test jobs to run. These will be used in place of suites '
|
2015-05-29 01:57:21 +03:00
|
|
|
'determined by test paths, if any.')
|
|
|
|
@CommandArgument('--extra', dest='extra_tests',
|
2015-06-14 08:22:44 +03:00
|
|
|
help='Additional tests to run. These will be added to suites '
|
2015-05-29 01:57:21 +03:00
|
|
|
'determined by test paths, if any.')
|
|
|
|
@CommandArgument('-b', dest='builds', default='do',
|
|
|
|
help='Build types to run (d for debug, o for optimized)')
|
|
|
|
@CommandArgument('--tag', dest='tags', action='append',
|
|
|
|
help='Restrict tests to the given tag (may be specified multiple times)')
|
|
|
|
@CommandArgument('--no-push', dest='push', action='store_false',
|
|
|
|
help='Do not push to try as a result of running this command (if '
|
|
|
|
'specified this command will only print calculated try '
|
|
|
|
'syntax and selection info).')
|
2015-06-14 08:22:44 +03:00
|
|
|
def autotry(self, builds=None, platforms=None, paths=None, verbose=None,
|
|
|
|
extra_tests=None, push=None, tags=None, tests=None):
|
2015-08-06 20:19:31 +03:00
|
|
|
"""mach try is under development, please file bugs blocking 1149670.
|
2015-06-14 08:22:44 +03:00
|
|
|
|
|
|
|
Pushes the specified tests to try. The simplest way to specify tests is
|
|
|
|
by using the -u argument, which will behave as usual for try syntax.
|
|
|
|
This command also provides a mechanism to select test jobs and tests
|
|
|
|
within a job by path based on tests present in the tree under that
|
|
|
|
path. Mochitests, xpcshell tests, and reftests are eligible for
|
|
|
|
selection by this mechanism. Selected tests will be run in a single
|
|
|
|
chunk of the relevant suite, at this time in chunk 1.
|
|
|
|
|
|
|
|
Specifying platforms is still required with the -p argument (a default
|
|
|
|
is taken from the AUTOTRY_PLATFORM_HINT environment variable if set).
|
|
|
|
|
|
|
|
Tests may be further filtered by passing one or more --tag to the
|
2015-08-06 20:19:31 +03:00
|
|
|
command. If one or more --tag is specified with out paths or -u,
|
|
|
|
tests with the given tags will be run in a single chunk of
|
|
|
|
applicable suites.
|
2015-06-14 08:22:44 +03:00
|
|
|
|
|
|
|
To run suites in addition to those determined from the tree, they
|
|
|
|
can be passed to the --extra arguent.
|
|
|
|
|
|
|
|
The command requires either its own mercurial extension ("push-to-try",
|
|
|
|
installable from mach mercurial-setup) or a git repo using git-cinnabar
|
|
|
|
(available at https://github.com/glandium/git-cinnabar).
|
|
|
|
"""
|
2015-05-29 01:57:21 +03:00
|
|
|
|
|
|
|
from mozbuild.testing import TestResolver
|
|
|
|
from mozbuild.controller.building import BuildDriver
|
2015-06-25 22:11:34 +03:00
|
|
|
from autotry import AutoTry
|
|
|
|
import pprint
|
2015-05-29 01:57:21 +03:00
|
|
|
|
|
|
|
print("mach try is under development, please file bugs blocking 1149670.")
|
|
|
|
|
2015-08-06 20:19:31 +03:00
|
|
|
builds, platforms = self.validate_args(paths, tests, tags, builds, platforms)
|
2015-05-29 01:57:21 +03:00
|
|
|
resolver = self._spawn(TestResolver)
|
|
|
|
|
|
|
|
at = AutoTry(self.topsrcdir, resolver, self._mach_context)
|
|
|
|
if at.find_uncommited_changes():
|
|
|
|
print('ERROR please commit changes before continuing')
|
|
|
|
sys.exit(1)
|
|
|
|
|
2015-08-26 22:48:28 +03:00
|
|
|
if paths or tags:
|
|
|
|
driver = self._spawn(BuildDriver)
|
|
|
|
driver.install_tests(remove=False)
|
2015-05-29 01:57:21 +03:00
|
|
|
|
2015-08-06 20:19:31 +03:00
|
|
|
manifests_by_flavor = at.resolve_manifests(paths=paths, tags=tags)
|
2015-05-29 01:57:21 +03:00
|
|
|
|
|
|
|
if not manifests_by_flavor and not tests:
|
|
|
|
print("No tests were found when attempting to resolve paths:\n\n\t%s" %
|
|
|
|
paths)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
all_manifests = set()
|
|
|
|
for m in manifests_by_flavor.values():
|
|
|
|
all_manifests |= m
|
|
|
|
all_manifests = list(all_manifests)
|
|
|
|
|
|
|
|
msg = at.calc_try_syntax(platforms, manifests_by_flavor.keys(), tests,
|
|
|
|
extra_tests, builds, all_manifests, tags)
|
|
|
|
|
2015-06-14 08:22:44 +03:00
|
|
|
if verbose and manifests_by_flavor:
|
2015-05-29 01:57:21 +03:00
|
|
|
print('Tests from the following manifests will be selected: ')
|
|
|
|
pprint.pprint(manifests_by_flavor)
|
|
|
|
|
2015-09-10 20:20:59 +03:00
|
|
|
if verbose or not push:
|
2015-06-14 08:22:44 +03:00
|
|
|
print('The following try syntax was calculated:\n\n\t%s\n' % msg)
|
2015-05-29 01:57:21 +03:00
|
|
|
|
|
|
|
if push:
|
|
|
|
at.push_to_try(msg, verbose)
|
|
|
|
|
|
|
|
return
|
2015-08-27 02:51:15 +03:00
|
|
|
|
|
|
|
|
|
|
|
def get_parser(argv=None):
|
|
|
|
parser = ArgumentParser()
|
|
|
|
parser.add_argument(dest="suite_name",
|
|
|
|
nargs=1,
|
|
|
|
choices=['mochitest'],
|
|
|
|
type=str,
|
|
|
|
help="The test for which chunk should be found. It corresponds "
|
|
|
|
"to the mach test invoked (only 'mochitest' currently).")
|
|
|
|
|
|
|
|
parser.add_argument(dest="test_path",
|
|
|
|
nargs=1,
|
|
|
|
type=str,
|
|
|
|
help="The test (any mochitest) for which chunk should be found.")
|
|
|
|
|
|
|
|
parser.add_argument('--total-chunks',
|
|
|
|
type=int,
|
|
|
|
dest='total_chunks',
|
|
|
|
required=True,
|
|
|
|
help='Total number of chunks to split tests into.',
|
2015-09-02 07:19:21 +03:00
|
|
|
default=None)
|
2015-08-27 02:51:15 +03:00
|
|
|
|
|
|
|
parser.add_argument('--chunk-by-runtime',
|
|
|
|
action='store_true',
|
|
|
|
dest='chunk_by_runtime',
|
|
|
|
help='Group tests such that each chunk has roughly the same runtime.',
|
2015-09-02 07:19:21 +03:00
|
|
|
default=False)
|
2015-08-27 02:51:15 +03:00
|
|
|
|
|
|
|
parser.add_argument('--chunk-by-dir',
|
|
|
|
type=int,
|
|
|
|
dest='chunk_by_dir',
|
|
|
|
help='Group tests together in the same chunk that are in the same top '
|
|
|
|
'chunkByDir directories.',
|
2015-09-02 07:19:21 +03:00
|
|
|
default=None)
|
|
|
|
|
|
|
|
parser.add_argument('--e10s',
|
|
|
|
action='store_true',
|
|
|
|
dest='e10s',
|
|
|
|
help='Find test on chunk with electrolysis preferences enabled.',
|
|
|
|
default=False)
|
2015-08-27 02:51:15 +03:00
|
|
|
|
2015-09-04 07:32:53 +03:00
|
|
|
parser.add_argument('-p', '--platform',
|
|
|
|
choices=['linux', 'linux64', 'mac', 'macosx64', 'win32', 'win64'],
|
|
|
|
dest='platform',
|
|
|
|
help="Platform for the chunk to find the test.",
|
|
|
|
default=None)
|
|
|
|
|
2015-09-01 08:52:07 +03:00
|
|
|
parser.add_argument('--debug',
|
|
|
|
action='store_true',
|
|
|
|
dest='debug',
|
|
|
|
help="Find the test on chunk in a debug build.",
|
|
|
|
default=False)
|
|
|
|
|
2015-08-27 02:51:15 +03:00
|
|
|
return parser
|
|
|
|
|
|
|
|
|
2015-09-04 07:32:53 +03:00
|
|
|
def download_mozinfo(platform=None, debug_build=False):
|
2015-09-01 08:52:07 +03:00
|
|
|
temp_dir = tempfile.mkdtemp()
|
|
|
|
temp_path = os.path.join(temp_dir, "mozinfo.json")
|
|
|
|
args = [
|
|
|
|
'mozdownload',
|
|
|
|
'-t', 'tinderbox',
|
|
|
|
'--ext', 'mozinfo.json',
|
|
|
|
'-d', temp_path,
|
|
|
|
]
|
2015-09-04 07:32:53 +03:00
|
|
|
if platform:
|
|
|
|
if platform == 'macosx64':
|
|
|
|
platform = 'mac64'
|
|
|
|
args.extend(['-p', platform])
|
2015-09-01 08:52:07 +03:00
|
|
|
if debug_build:
|
|
|
|
args.extend(['--debug-build'])
|
|
|
|
|
|
|
|
subprocess.call(args)
|
|
|
|
return temp_dir, temp_path
|
|
|
|
|
2015-08-27 02:51:15 +03:00
|
|
|
@CommandProvider
|
|
|
|
class ChunkFinder(MachCommandBase):
|
|
|
|
@Command('find-test-chunk', category='testing',
|
|
|
|
description='Find which chunk a test belongs to (works for mochitest).',
|
|
|
|
parser=get_parser)
|
|
|
|
def chunk_finder(self, **kwargs):
|
|
|
|
total_chunks = kwargs['total_chunks']
|
|
|
|
test_path = kwargs['test_path'][0]
|
|
|
|
suite_name = kwargs['suite_name'][0]
|
|
|
|
_, dump_tests = tempfile.mkstemp()
|
2015-09-02 23:18:08 +03:00
|
|
|
|
|
|
|
from mozbuild.testing import TestResolver
|
|
|
|
resolver = self._spawn(TestResolver)
|
|
|
|
relpath = self._wrap_path_argument(test_path).relpath()
|
|
|
|
tests = list(resolver.resolve_tests(paths=[relpath]))
|
|
|
|
if len(tests) != 1:
|
|
|
|
print('No test found for test_path: %s' % test_path)
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
flavor = tests[0]['flavor']
|
|
|
|
subsuite = tests[0]['subsuite']
|
2015-08-27 02:51:15 +03:00
|
|
|
args = {
|
|
|
|
'totalChunks': total_chunks,
|
|
|
|
'dump_tests': dump_tests,
|
|
|
|
'chunkByDir': kwargs['chunk_by_dir'],
|
|
|
|
'chunkByRuntime': kwargs['chunk_by_runtime'],
|
2015-09-02 07:19:21 +03:00
|
|
|
'e10s': kwargs['e10s'],
|
2015-09-02 23:18:08 +03:00
|
|
|
'subsuite': subsuite,
|
2015-08-27 02:51:15 +03:00
|
|
|
}
|
|
|
|
|
2015-09-01 08:52:07 +03:00
|
|
|
temp_dir = None
|
2015-09-04 07:32:53 +03:00
|
|
|
if kwargs['platform'] or kwargs['debug']:
|
2015-09-01 08:52:07 +03:00
|
|
|
self._activate_virtualenv()
|
|
|
|
self.virtualenv_manager.install_pip_package('mozdownload==1.17')
|
2015-09-04 07:32:53 +03:00
|
|
|
temp_dir, temp_path = download_mozinfo(kwargs['platform'], kwargs['debug'])
|
2015-09-01 08:52:07 +03:00
|
|
|
args['extra_mozinfo_json'] = temp_path
|
|
|
|
|
2015-08-27 02:51:15 +03:00
|
|
|
found = False
|
|
|
|
for this_chunk in range(1, total_chunks+1):
|
|
|
|
args['thisChunk'] = this_chunk
|
|
|
|
try:
|
|
|
|
self._mach_context.commands.dispatch(suite_name, self._mach_context, flavor=flavor, resolve_tests=False, **args)
|
|
|
|
except SystemExit:
|
|
|
|
pass
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
break
|
|
|
|
|
|
|
|
fp = open(os.path.expanduser(args['dump_tests']), 'r')
|
|
|
|
tests = json.loads(fp.read())['active_tests']
|
2015-09-02 07:10:23 +03:00
|
|
|
for test in tests:
|
|
|
|
if test_path == test['path']:
|
|
|
|
if 'disabled' in test:
|
2015-09-02 23:18:08 +03:00
|
|
|
print('The test %s for flavor %s is disabled on the given platform' % (test_path, flavor))
|
2015-09-02 07:10:23 +03:00
|
|
|
else:
|
2015-09-02 23:18:08 +03:00
|
|
|
print('The test %s for flavor %s is present in chunk number: %d' % (test_path, flavor, this_chunk))
|
2015-09-02 07:10:23 +03:00
|
|
|
found = True
|
|
|
|
break
|
|
|
|
|
|
|
|
if found:
|
2015-08-27 02:51:15 +03:00
|
|
|
break
|
|
|
|
|
|
|
|
if not found:
|
|
|
|
raise Exception("Test %s not found." % test_path)
|
|
|
|
# Clean up the file
|
|
|
|
os.remove(dump_tests)
|
2015-09-01 08:52:07 +03:00
|
|
|
if temp_dir:
|
|
|
|
shutil.rmtree(temp_dir)
|