--- a/testing/mach_commands.py
+++ b/testing/mach_commands.py
@@ -34,17 +34,17 @@ files relevant to those files.
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()
UNKNOWN_FLAVOR = '''
-I know you are trying to run a %s test. Unfortunately, I can't run those
+I know you are trying to run a %s%s test. Unfortunately, I can't run those
tests yet. Sorry!
'''.strip()
TEST_HELP = '''
Test or tests to run. Tests can be specified by filename, directory, suite
name or suite alias.
The following test suites and aliases are supported: %s
@@ -106,17 +106,17 @@ class Test(MachCommandBase):
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.
"""
from mozlog.commandline import setup_logging
- from moztest.resolve import TestResolver, TEST_FLAVORS, TEST_SUITES
+ from moztest.resolve import get_suite_definition, TestResolver, TEST_SUITES
resolver = self._spawn(TestResolver)
run_suites, run_tests = resolver.resolve_metadata(what)
if not run_suites and not run_tests:
print(UNKNOWN_TEST)
return 1
@@ -141,30 +141,25 @@ class Test(MachCommandBase):
status = res
buckets = {}
for test in run_tests:
key = (test['flavor'], test.get('subsuite', ''))
buckets.setdefault(key, []).append(test)
for (flavor, subsuite), tests in sorted(buckets.items()):
- if flavor not in TEST_FLAVORS:
- print(UNKNOWN_FLAVOR % flavor)
- status = 1
- continue
-
- m = TEST_FLAVORS[flavor]
+ m = get_suite_definition(flavor, subsuite)
if 'mach_command' not in m:
- print(UNKNOWN_FLAVOR % flavor)
+ substr = '-{}'.format(subsuite) if subsuite else ''
+ print(UNKNOWN_FLAVOR % (flavor, substr))
status = 1
continue
kwargs = dict(m['kwargs'])
kwargs['log'] = log
- kwargs['subsuite'] = subsuite
res = self._mach_context.commands.dispatch(
m['mach_command'], self._mach_context,
argv=extra_args, test_objects=tests, **kwargs)
if res:
status = res
log.shutdown()
--- a/testing/mozbase/moztest/moztest/resolve.py
+++ b/testing/mozbase/moztest/moztest/resolve.py
@@ -45,124 +45,80 @@ TEST_SUITES = {
},
'check-spidermonkey': {
'aliases': ('sm',),
'mach_command': 'check-spidermonkey',
'kwargs': {'valgrind': False},
},
# TODO(ato): integrate geckodriver tests with moz.build
'geckodriver': {
+ 'aliases': ('testing/geckodriver',),
'mach_command': 'geckodriver-test',
- 'aliases': ('testing/geckodriver',),
'kwargs': {},
},
+ 'marionette': {
+ 'aliases': ('mn',),
+ 'mach_command': 'marionette',
+ 'kwargs': {'tests': None},
+ },
'mochitest-a11y': {
'aliases': ('a11y', 'ally'),
'mach_command': 'mochitest',
'kwargs': {'flavor': 'a11y', 'test_paths': None},
+ 'task_regex': 'mochitest-a11y(?:-1)?$',
},
'mochitest-browser': {
'aliases': ('bc', 'browser-chrome'),
'mach_command': 'mochitest',
'kwargs': {'flavor': 'browser-chrome', 'test_paths': None},
+ 'task_regex': 'mochitest-browser-chrome(?:-e10s)?(?:-1)?$',
},
'mochitest-chrome': {
'aliases': ('mc',),
'mach_command': 'mochitest',
'kwargs': {'flavor': 'chrome', 'test_paths': None},
+ 'task_regex': 'mochitest-chrome(?:-e10s)?(?:-1)?$',
},
'mochitest-devtools': {
'aliases': ('dt', 'devtools-chrome'),
'mach_command': 'mochitest',
'kwargs': {'subsuite': 'devtools', 'test_paths': None},
+ 'task_regex': 'mochitest-devtools-chrome(?:-e10s)?(?:-1)?$',
},
'mochitest-plain': {
'aliases': ('mp', 'plain',),
'mach_command': 'mochitest',
'kwargs': {'flavor': 'plain', 'test_paths': None},
+ 'task_regex': 'mochitest(?:-e10s)?(?:-1)?$',
},
'python': {
'mach_command': 'python-test',
'kwargs': {'tests': None},
},
'reftest': {
'aliases': ('rr',),
'mach_command': 'reftest',
'kwargs': {'tests': None},
+ 'task_regex': '(opt|debug)-reftest(?:-no-accel|-gpu|-stylo)?(?:-e10s)?(?:-1)?$',
},
'web-platform-tests': {
'aliases': ('wpt',),
'mach_command': 'web-platform-tests',
- 'kwargs': {}
+ 'kwargs': {'include': []},
+ 'task_regex': 'web-platform-tests(?:-reftests|-wdspec)?(?:-e10s)?(?:-1)?$',
},
'valgrind': {
'aliases': ('v',),
'mach_command': 'valgrind-test',
'kwargs': {},
},
'xpcshell': {
'aliases': ('x',),
'mach_command': 'xpcshell-test',
'kwargs': {'test_file': 'all'},
- },
-}
-
-# Maps test flavors to metadata on how to run that test.
-TEST_FLAVORS = {
- 'a11y': {
- 'mach_command': 'mochitest',
- 'kwargs': {'flavor': 'a11y', 'test_paths': []},
- 'task_regex': 'mochitest-a11y(?:-1)?$',
- },
- 'browser-chrome': {
- 'mach_command': 'mochitest',
- 'kwargs': {'flavor': 'browser-chrome', 'test_paths': []},
- 'task_regex': 'mochitest-browser-chrome(?:-e10s)?(?:-1)?$',
- },
- 'crashtest': {},
- 'chrome': {
- 'mach_command': 'mochitest',
- 'kwargs': {'flavor': 'chrome', 'test_paths': []},
- 'task_regex': 'mochitest-chrome(?:-e10s)?(?:-1)?$',
- },
- 'firefox-ui-functional': {
- 'mach_command': 'firefox-ui-functional',
- 'kwargs': {'tests': []},
- },
- 'firefox-ui-update': {
- 'mach_command': 'firefox-ui-update',
- 'kwargs': {'tests': []},
- },
- 'marionette': {
- 'mach_command': 'marionette-test',
- 'kwargs': {'tests': []},
- },
- 'mochitest': {
- 'mach_command': 'mochitest',
- 'kwargs': {'flavor': 'mochitest', 'test_paths': []},
- 'task_regex': 'mochitest(?:-e10s)?(?:-1)?$',
- },
- 'python': {
- 'mach_command': 'python-test',
- 'kwargs': {},
- },
- 'reftest': {
- 'mach_command': 'reftest',
- 'kwargs': {'tests': []},
- 'task_regex': '(opt|debug)-reftest(?:-no-accel|-gpu|-stylo)?(?:-e10s)?(?:-1)?$',
- },
- 'steeplechase': {},
- 'web-platform-tests': {
- 'mach_command': 'web-platform-tests',
- 'kwargs': {'include': []},
- 'task_regex': 'web-platform-tests(?:-reftests|-wdspec)?(?:-e10s)?(?:-1)?$',
- },
- 'xpcshell': {
- 'mach_command': 'xpcshell-test',
- 'kwargs': {'test_paths': []},
'task_regex': 'xpcshell(?:-1)?$',
},
}
for i in range(1, MOCHITEST_TOTAL_CHUNKS + 1):
TEST_SUITES['mochitest-%d' % i] = {
'aliases': ('m%d' % i,),
'mach_command': 'mochitest',
@@ -171,16 +127,64 @@ for i in range(1, MOCHITEST_TOTAL_CHUNKS
'subsuite': 'default',
'chunk_by_dir': MOCHITEST_CHUNK_BY_DIR,
'total_chunks': MOCHITEST_TOTAL_CHUNKS,
'this_chunk': i,
'test_paths': None,
},
}
+_test_flavors = {
+ 'a11y': 'mochitest-a11y',
+ 'browser-chrome': 'mochitest-browser',
+ 'chrome': 'mochitest-chrome',
+ 'crashtest': '',
+ 'firefox-ui-functional': 'firefox-ui-functional',
+ 'firefox-ui-update': 'firefox-ui-update',
+ 'marionette': 'marionette',
+ 'mochitest': 'mochitest-plain',
+ 'python': 'python',
+ 'reftest': 'reftest',
+ 'steeplechase': '',
+ 'web-platform-tests': 'web-platform-tests',
+ 'xpcshell': 'xpcshell',
+}
+
+_test_subsuites = {
+ ('browser-chrome', 'devtools'): 'mochitest-devtools',
+}
+
+
+def get_suite_definition(flavor, subsuite=None, strict=False):
+ """Return a suite definition given a flavor and optional subsuite.
+
+ If strict is True, a subsuite must have its own entry in TEST_SUITES.
+ Otherwise, the entry for 'flavor' will be returned with the 'subsuite'
+ keyword arg set.
+
+ With or without strict mode, an empty dict will be returned if no
+ matching suite definition was found.
+ """
+ if not subsuite:
+ suite_name = _test_flavors.get(flavor)
+ return TEST_SUITES.get(suite_name, {}).copy()
+
+ suite_name = _test_subsuites.get((flavor, subsuite))
+ if suite_name or strict:
+ return TEST_SUITES.get(suite_name, {}).copy()
+
+ suite_name = _test_flavors.get(flavor)
+ if suite_name not in TEST_SUITES:
+ return {}
+
+ suite = TEST_SUITES[suite_name].copy()
+ suite.setdefault('kwargs', {})
+ suite['kwargs']['subsuite'] = subsuite
+ return suite
+
def rewrite_test_base(test, new_base, honor_install_to_subdir=False):
"""Rewrite paths in a test to be under a new base path.
This is useful for running tests from a separate location from where they
were defined.
honor_install_to_subdir and the underlying install-to-subdir field are a
--- a/tools/tryselect/selectors/fuzzy.py
+++ b/tools/tryselect/selectors/fuzzy.py
@@ -8,17 +8,17 @@ import os
import platform
import re
import subprocess
import sys
from distutils.spawn import find_executable
from mozboot.util import get_state_dir
from mozterm import Terminal
-from moztest.resolve import TestResolver, TEST_FLAVORS
+from moztest.resolve import TestResolver, get_suite_definition
from .. import preset as pset
from ..cli import BaseTryParser
from ..tasks import generate_tasks
from ..vcs import VCSHelper
terminal = Terminal()
@@ -171,19 +171,27 @@ def format_header():
shortcuts.append('{t.white}{action}{t.normal}: {t.yellow}<{key}>{t.normal}'.format(
t=terminal, action=action, key=key))
return FZF_HEADER.format(shortcuts=', '.join(shortcuts), t=terminal)
def filter_by_paths(tasks, paths):
resolver = TestResolver.from_environment(cwd=here)
run_suites, run_tests = resolver.resolve_metadata(paths)
- flavors = set([t['flavor'] for t in run_tests])
- task_regexes = [TEST_FLAVORS[f]['task_regex']
- for f in flavors if 'task_regex' in TEST_FLAVORS[f]]
+ flavors = set([(t['flavor'], t.get('subsuite')) for t in run_tests])
+
+ task_regexes = set()
+ for flavor, subsuite in flavors:
+ suite = get_suite_definition(flavor, subsuite, strict=True)
+ if 'task_regex' not in suite:
+ print("warning: no tasks could be resolved from flavor '{}'{}".format(
+ flavor, " and subsuite '{}'".format(subsuite) if subsuite else ""))
+ continue
+
+ task_regexes.add(suite['task_regex'])
def match_task(task):
return any(re.search(pattern, task) for pattern in task_regexes)
return filter(match_task, tasks)
def run_fuzzy_try(update=False, query=None, templates=None, full=False, parameters=None,
@@ -191,25 +199,27 @@ def run_fuzzy_try(update=False, query=No
paths=None, **kwargs):
if mod_presets:
return getattr(pset, mod_presets)(section='fuzzy')
fzf = fzf_bootstrap(update)
if not fzf:
print(FZF_NOT_FOUND)
- return
+ return 1
vcs = VCSHelper.create()
vcs.check_working_directory(push)
all_tasks = generate_tasks(parameters, full, root=vcs.root)
if paths:
all_tasks = filter_by_paths(all_tasks, paths)
+ if not all_tasks:
+ return 1
key_shortcuts = [k + ':' + v for k, v in fzf_shortcuts.iteritems()]
cmd = [
fzf, '-m',
'--bind', ','.join(key_shortcuts),
'--header', format_header(),
# Using python to split the preview string is a bit convoluted,
# but is guaranteed to be available on all platforms.