mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out 3 changesets (bug 1193264, bug 1193215
, bug 1204120) for S4 Test failures
Backed out changeset 3000fca0fc88 (bug 1204120)
Backed out changeset 2e67853b0b70 (bug 1193264)
Backed out changeset ced598ee50fe (bug 1193215
)
This commit is contained in:
parent
e259122ad0
commit
5b7d2f7ab4
@ -10,7 +10,6 @@ import sys
|
||||
import tempfile
|
||||
import subprocess
|
||||
import shutil
|
||||
from collections import defaultdict
|
||||
|
||||
from mach.decorators import (
|
||||
CommandArgument,
|
||||
@ -437,58 +436,19 @@ class JsapiTestsCommand(MachCommandBase):
|
||||
|
||||
return jsapi_tests_result
|
||||
|
||||
def autotry_parser():
|
||||
from autotry import arg_parser
|
||||
return arg_parser()
|
||||
|
||||
@CommandProvider
|
||||
class PushToTry(MachCommandBase):
|
||||
def normalise_list(self, items, allow_subitems=False):
|
||||
from autotry import parse_arg
|
||||
|
||||
rv = defaultdict(list)
|
||||
for item in items:
|
||||
parsed = parse_arg(item)
|
||||
for key, values in parsed.iteritems():
|
||||
rv[key].extend(values)
|
||||
|
||||
if not allow_subitems:
|
||||
if not all(item == [] for item in rv.itervalues()):
|
||||
raise ValueError("Unexpected subitems in argument")
|
||||
return rv.keys()
|
||||
else:
|
||||
return rv
|
||||
|
||||
def validate_args(self, **kwargs):
|
||||
if not kwargs["paths"] and not kwargs["tests"] and not kwargs["tags"]:
|
||||
print("Paths, tags, or tests must be specified as an argument to autotry.")
|
||||
def validate_args(self, paths, tests, tags, builds, platforms):
|
||||
if not any([len(paths), tests, tags]):
|
||||
print("Paths, tests, or tags must be specified.")
|
||||
sys.exit(1)
|
||||
|
||||
if kwargs["platforms"] is None:
|
||||
print("Platforms must be specified as an argument to autotry")
|
||||
sys.exit(1)
|
||||
if platforms is None:
|
||||
platforms = os.environ['AUTOTRY_PLATFORM_HINT']
|
||||
|
||||
try:
|
||||
platforms = self.normalise_list(kwargs["platforms"])
|
||||
except ValueError as e:
|
||||
print("Error parsing -p argument:\n%s" % e.message)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
tests = (self.normalise_list(kwargs["tests"], allow_subitems=True)
|
||||
if kwargs["tests"] else {})
|
||||
except ValueError as e:
|
||||
print("Error parsing -u argument:\n%s" % e.message)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
talos = self.normalise_list(kwargs["talos"]) if kwargs["talos"] else []
|
||||
except ValueError as e:
|
||||
print("Error parsing -t argument:\n%s" % e.message)
|
||||
sys.exit(1)
|
||||
|
||||
paths = []
|
||||
for p in kwargs["paths"]:
|
||||
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'
|
||||
@ -498,86 +458,70 @@ class PushToTry(MachCommandBase):
|
||||
print('Specified path "%s" is at the top of the srcdir and would'
|
||||
' select all tests.' % p)
|
||||
sys.exit(1)
|
||||
paths.append(os.path.relpath(p, self.topsrcdir))
|
||||
|
||||
try:
|
||||
tags = self.normalise_list(kwargs["tags"]) if kwargs["tags"] else []
|
||||
except ValueError as e:
|
||||
print("Error parsing --tags argument:\n%s" % e.message)
|
||||
sys.exit(1)
|
||||
return builds, platforms
|
||||
|
||||
return kwargs["builds"], platforms, tests, talos, paths, tags, kwargs["extra_args"]
|
||||
@Command('try', category='testing', description='Push selected tests to the try server')
|
||||
@CommandArgument('paths', nargs='*', help='Paths to search for tests to run on try.')
|
||||
@CommandArgument('-n', dest='verbose', action='store_true', default=False,
|
||||
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',
|
||||
help='Test jobs to run. These will be used in place of suites '
|
||||
'determined by test paths, if any.')
|
||||
@CommandArgument('--extra', dest='extra_tests',
|
||||
help='Additional tests to run. These will be added to suites '
|
||||
'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).')
|
||||
def autotry(self, builds=None, platforms=None, paths=None, verbose=None,
|
||||
extra_tests=None, push=None, tags=None, tests=None):
|
||||
"""mach try is under development, please file bugs blocking 1149670.
|
||||
|
||||
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.
|
||||
|
||||
@Command('try',
|
||||
category='testing',
|
||||
description='Push selected tests to the try server',
|
||||
parser=autotry_parser)
|
||||
Specifying platforms is still required with the -p argument (a default
|
||||
is taken from the AUTOTRY_PLATFORM_HINT environment variable if set).
|
||||
|
||||
def autotry(self, **kwargs):
|
||||
"""Autotry is in beta, please file bugs blocking 1149670.
|
||||
Tests may be further filtered by passing one or more --tag to the
|
||||
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.
|
||||
|
||||
Push the current tree to try, with the specified syntax.
|
||||
|
||||
Build options, platforms and regression tests may be selected
|
||||
using the usual try options (-b, -p and -u respectively). In
|
||||
addition, tests in a given directory may be automatically
|
||||
selected by passing that directory as a positional argument to the
|
||||
command. For example:
|
||||
|
||||
mach try -b d -p linux64 dom testing/web-platform/tests/dom
|
||||
|
||||
would schedule a try run for linux64 debug consisting of all
|
||||
tests under dom/ and testing/web-platform/tests/dom.
|
||||
|
||||
Test selection using positional arguments is available for
|
||||
mochitests, reftests, xpcshell tests and web-platform-tests.
|
||||
|
||||
Tests may be also filtered by passing --tag to the command,
|
||||
which will run only tests marked as having the specified
|
||||
tags e.g.
|
||||
|
||||
mach try -b d -p win64 --tag media
|
||||
|
||||
would run all tests tagged 'media' on Windows 64.
|
||||
|
||||
If both positional arguments or tags and -u are supplied, the
|
||||
suites in -u will be run in full. Where tests are selected by
|
||||
positional argument they will be run in a single chunk.
|
||||
|
||||
If no build option is selected, both debug and opt will be
|
||||
scheduled. If no platform is selected a default is taken from
|
||||
the AUTOTRY_PLATFORM_HINT environment variable, if set.
|
||||
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).
|
||||
|
||||
"""
|
||||
|
||||
from mozbuild.testing import TestResolver
|
||||
from mozbuild.controller.building import BuildDriver
|
||||
from autotry import AutoTry
|
||||
import pprint
|
||||
|
||||
print("mach try is under development, please file bugs blocking 1149670.")
|
||||
|
||||
builds, platforms = self.validate_args(paths, tests, tags, builds, platforms)
|
||||
resolver = self._spawn(TestResolver)
|
||||
|
||||
at = AutoTry(self.topsrcdir, resolver, self._mach_context)
|
||||
|
||||
if kwargs["load"] is not None:
|
||||
defaults = at.load_config(kwargs["load"])
|
||||
|
||||
if defaults is None:
|
||||
print("No saved configuration called %s found in autotry.ini" % kwargs["load"],
|
||||
file=sys.stderr)
|
||||
|
||||
for key, value in kwargs.iteritems():
|
||||
if value in (None, []) and key in defaults:
|
||||
kwargs[key] = defaults[key]
|
||||
|
||||
builds, platforms, tests, talos, paths, tags, extra_args = self.validate_args(**kwargs)
|
||||
|
||||
if kwargs["push"] and at.find_uncommited_changes():
|
||||
if at.find_uncommited_changes():
|
||||
print('ERROR please commit changes before continuing')
|
||||
sys.exit(1)
|
||||
|
||||
@ -585,40 +529,32 @@ class PushToTry(MachCommandBase):
|
||||
driver = self._spawn(BuildDriver)
|
||||
driver.install_tests(remove=False)
|
||||
|
||||
paths = [os.path.relpath(os.path.normpath(os.path.abspath(item)), self.topsrcdir)
|
||||
for item in paths]
|
||||
paths_by_flavor = at.paths_by_flavor(paths=paths, tags=tags)
|
||||
manifests_by_flavor = at.resolve_manifests(paths=paths, tags=tags)
|
||||
|
||||
if not paths_by_flavor and not tests:
|
||||
print("No tests were found when attempting to resolve paths:\n\n\t%s" %
|
||||
paths)
|
||||
sys.exit(1)
|
||||
|
||||
if not kwargs["intersection"]:
|
||||
paths_by_flavor = at.remove_duplicates(paths_by_flavor, tests)
|
||||
else:
|
||||
paths_by_flavor = {}
|
||||
|
||||
try:
|
||||
msg = at.calc_try_syntax(platforms, tests, talos, builds, paths_by_flavor, tags,
|
||||
extra_args, kwargs["intersection"])
|
||||
except ValueError as e:
|
||||
print(e.message)
|
||||
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)
|
||||
|
||||
if kwargs["verbose"] and paths_by_flavor:
|
||||
print('The following tests will be selected: ')
|
||||
for flavor, paths in paths_by_flavor.iteritems():
|
||||
print("%s: %s" % (flavor, ",".join(paths)))
|
||||
all_manifests = set()
|
||||
for m in manifests_by_flavor.values():
|
||||
all_manifests |= m
|
||||
all_manifests = list(all_manifests)
|
||||
|
||||
if kwargs["verbose"] or not kwargs["push"]:
|
||||
print('The following try syntax was calculated:\n%s' % msg)
|
||||
msg = at.calc_try_syntax(platforms, manifests_by_flavor.keys(), tests,
|
||||
extra_tests, builds, all_manifests, tags)
|
||||
|
||||
if kwargs["push"]:
|
||||
at.push_to_try(msg, kwargs["verbose"])
|
||||
if verbose and manifests_by_flavor:
|
||||
print('Tests from the following manifests will be selected: ')
|
||||
pprint.pprint(manifests_by_flavor)
|
||||
|
||||
if kwargs["save"] is not None:
|
||||
at.save_config(kwargs["save"], msg)
|
||||
if verbose or not push:
|
||||
print('The following try syntax was calculated:\n\n\t%s\n' % msg)
|
||||
|
||||
if push:
|
||||
at.push_to_try(msg, verbose)
|
||||
|
||||
return
|
||||
|
||||
|
||||
def get_parser(argv=None):
|
||||
|
@ -119,8 +119,8 @@ config = {
|
||||
"--log-errorsummary=%(error_summary_file)s",
|
||||
"--certificate-path=%(certificate_path)s",
|
||||
"--screenshot-on-fail",
|
||||
"%(test_path)s"
|
||||
],
|
||||
"tests": ["%(test_path)s"],
|
||||
"run_filename": "runtestsb2g.py",
|
||||
"testsdir": "mochitest"
|
||||
},
|
||||
@ -143,8 +143,8 @@ config = {
|
||||
"--log-errorsummary=%(error_summary_file)s",
|
||||
"--certificate-path=%(certificate_path)s",
|
||||
"--screenshot-on-fail",
|
||||
"%(test_path)s"
|
||||
],
|
||||
"tests": ["%(test_path)s"],
|
||||
"run_filename": "runtestsb2g.py",
|
||||
"testsdir": "mochitest"
|
||||
},
|
||||
|
@ -20,8 +20,8 @@ config = {
|
||||
"--this-chunk=%(this_chunk)s",
|
||||
"--symbols-path=%(symbols_path)s",
|
||||
"--enable-oop",
|
||||
"%(test_manifest)s"
|
||||
],
|
||||
"tests": ["%(test_manifest)s"]
|
||||
}
|
||||
},
|
||||
"run_file_names": {
|
||||
|
@ -256,7 +256,7 @@ config = {
|
||||
},
|
||||
},
|
||||
"all_cppunittest_suites": {
|
||||
"cppunittest": {"tests": ["tests/cppunittest"]}
|
||||
"cppunittest": ["tests/cppunittest"]
|
||||
},
|
||||
"all_gtest_suites": {
|
||||
"gtest": []
|
||||
|
@ -26,7 +26,7 @@ from mozharness.mozilla.proxxy import Proxxy
|
||||
from mozharness.mozilla.structuredlog import StructuredOutputParser
|
||||
from mozharness.mozilla.taskcluster_helper import TaskClusterArtifactFinderMixin
|
||||
from mozharness.mozilla.testing.unittest import DesktopUnittestOutputParser
|
||||
from mozharness.mozilla.testing.try_tools import TryToolsMixin, try_config_options
|
||||
from mozharness.mozilla.testing.try_tools import TryToolsMixin
|
||||
from mozharness.mozilla.tooltool import TooltoolMixin
|
||||
|
||||
from mozharness.lib.python.authentication import get_credentials
|
||||
@ -83,7 +83,7 @@ testing_config_options = [
|
||||
"choices": ['ondemand', 'true'],
|
||||
"help": "Download and extract crash reporter symbols.",
|
||||
}],
|
||||
] + copy.deepcopy(virtualenv_config_options) + copy.deepcopy(try_config_options)
|
||||
] + copy.deepcopy(virtualenv_config_options)
|
||||
|
||||
|
||||
# TestingMixin {{{1
|
||||
@ -676,35 +676,6 @@ Did you run with --create-virtualenv? Is mozinstall in virtualenv_modules?""")
|
||||
|
||||
return self.minidump_stackwalk_path
|
||||
|
||||
def query_options(self, *args, **kwargs):
|
||||
if "str_format_values" in kwargs:
|
||||
str_format_values = kwargs.pop("str_format_values")
|
||||
else:
|
||||
str_format_values = {}
|
||||
|
||||
arguments = []
|
||||
|
||||
for arg in args:
|
||||
if arg is not None:
|
||||
arguments.extend(argument % str_format_values for argument in arg)
|
||||
|
||||
return arguments
|
||||
|
||||
def query_tests_args(self, *args, **kwargs):
|
||||
if "str_format_values" in kwargs:
|
||||
str_format_values = kwargs.pop("str_format_values")
|
||||
else:
|
||||
str_format_values = {}
|
||||
|
||||
arguments = []
|
||||
|
||||
for arg in reversed(args):
|
||||
if arg:
|
||||
arguments.append("--")
|
||||
arguments.extend(argument % str_format_values for argument in arg)
|
||||
break
|
||||
|
||||
return arguments
|
||||
|
||||
def _run_cmd_checks(self, suites):
|
||||
if not suites:
|
||||
|
@ -8,43 +8,17 @@
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
from collections import defaultdict
|
||||
|
||||
from mozharness.base.script import PostScriptAction
|
||||
from mozharness.base.transfer import TransferMixin
|
||||
|
||||
try_config_options = [
|
||||
[["--try-message"],
|
||||
{"action": "store",
|
||||
"dest": "try_message",
|
||||
"default": None,
|
||||
"help": "try syntax string to select tests to run",
|
||||
}],
|
||||
]
|
||||
|
||||
test_flavors = {
|
||||
'browser-chrome': {},
|
||||
'chrome': {},
|
||||
'devtools-chrome': {},
|
||||
'mochitest': {},
|
||||
'xpcshell' :{},
|
||||
'reftest': {
|
||||
"path": lambda x: os.path.join("tests", "reftest", "tests", x)
|
||||
},
|
||||
'crashtest': {
|
||||
"path": lambda x: os.path.join("tests", "reftest", "tests", x)
|
||||
},
|
||||
'web-platform-tests': {
|
||||
"path": lambda x: os.path.join("tests", x.split("testing" + os.path.sep)[1])
|
||||
}
|
||||
}
|
||||
|
||||
class TryToolsMixin(TransferMixin):
|
||||
"""Utility functions for an interface between try syntax and out test harnesses.
|
||||
Requires log and script mixins."""
|
||||
|
||||
harness_extra_args = None
|
||||
try_test_paths = {}
|
||||
try_test_paths = []
|
||||
known_try_arguments = {
|
||||
'--tag': {
|
||||
'action': 'append',
|
||||
@ -55,34 +29,31 @@ class TryToolsMixin(TransferMixin):
|
||||
|
||||
def _extract_try_message(self):
|
||||
msg = None
|
||||
if "try_message" in self.config and self.config["try_message"]:
|
||||
msg = self.config["try_message"]
|
||||
else:
|
||||
if self.buildbot_config['sourcestamp']['changes']:
|
||||
msg = self.buildbot_config['sourcestamp']['changes'][-1]['comments']
|
||||
if self.buildbot_config['sourcestamp']['changes']:
|
||||
msg = self.buildbot_config['sourcestamp']['changes'][-1]['comments']
|
||||
|
||||
if msg is None or len(msg) == 1024:
|
||||
# This commit message was potentially truncated, get the full message
|
||||
# from hg.
|
||||
props = self.buildbot_config['properties']
|
||||
rev = props['revision']
|
||||
repo = props['repo_path']
|
||||
url = 'https://hg.mozilla.org/%s/json-pushes?changeset=%s&full=1' % (repo, rev)
|
||||
if msg is None or len(msg) == 1024:
|
||||
# This commit message was potentially truncated, get the full message
|
||||
# from hg.
|
||||
props = self.buildbot_config['properties']
|
||||
rev = props['revision']
|
||||
repo = props['repo_path']
|
||||
url = 'https://hg.mozilla.org/%s/json-pushes?changeset=%s&full=1' % (repo, rev)
|
||||
|
||||
pushinfo = self.load_json_from_url(url)
|
||||
for k, v in pushinfo.items():
|
||||
if isinstance(v, dict) and 'changesets' in v:
|
||||
msg = v['changesets'][-1]['desc']
|
||||
pushinfo = self.load_json_from_url(url)
|
||||
for k, v in pushinfo.items():
|
||||
if isinstance(v, dict) and 'changesets' in v:
|
||||
msg = v['changesets'][-1]['desc']
|
||||
|
||||
if not msg and 'try_syntax' in self.buildbot_config['properties']:
|
||||
# If we don't find try syntax in the usual place, check for it in an
|
||||
# alternate property available to tools using self-serve.
|
||||
msg = self.buildbot_config['properties']['try_syntax']
|
||||
if not msg and 'try_syntax' in self.buildbot_config['properties']:
|
||||
# If we don't find try syntax in the usual place, check for it in an
|
||||
# alternate property available to tools using self-serve.
|
||||
msg = self.buildbot_config['properties']['try_syntax']
|
||||
|
||||
return msg
|
||||
|
||||
@PostScriptAction('download-and-extract')
|
||||
def set_extra_try_arguments(self, action, success=None):
|
||||
def _set_extra_try_arguments(self, action, success=None):
|
||||
"""Finds a commit message and parses it for extra arguments to pass to the test
|
||||
harness command line and test paths used to filter manifests.
|
||||
|
||||
@ -136,7 +107,7 @@ class TryToolsMixin(TransferMixin):
|
||||
|
||||
parser.add_argument('--try-test-paths', nargs='*')
|
||||
(args, _) = parser.parse_known_args(all_try_args)
|
||||
self.try_test_paths = self._group_test_paths(args.try_test_paths)
|
||||
self.try_test_paths = args.try_test_paths
|
||||
del args.try_test_paths
|
||||
|
||||
out_args = []
|
||||
@ -156,35 +127,91 @@ class TryToolsMixin(TransferMixin):
|
||||
|
||||
self.harness_extra_args = out_args
|
||||
|
||||
def _group_test_paths(self, args):
|
||||
rv = defaultdict(list)
|
||||
def _resolve_specified_manifests(self):
|
||||
if not self.try_test_paths:
|
||||
return None
|
||||
|
||||
if args is None:
|
||||
return rv
|
||||
target_manifests = set(self.try_test_paths)
|
||||
|
||||
for item in args:
|
||||
suite, path = item.split(":", 1)
|
||||
rv[suite].append(path)
|
||||
return rv
|
||||
def filter_ini_manifest(line):
|
||||
# Lines are formatted as [include:<path>], we care about <path>.
|
||||
parts = line.split(':')
|
||||
term = line
|
||||
if len(parts) == 2:
|
||||
term = parts[1]
|
||||
if term.endswith(']'):
|
||||
term = term[:-1]
|
||||
if (term in target_manifests or
|
||||
any(term.startswith(l) for l in target_manifests)):
|
||||
return True
|
||||
return False
|
||||
|
||||
def try_args(self, flavor):
|
||||
"""Get arguments, test_list derived from try syntax to apply to a command"""
|
||||
def filter_list_manifest(line):
|
||||
# Lines are usually formatted as "include <path>", we care about <path>.
|
||||
parts = line.split()
|
||||
term = line
|
||||
if len(parts) == 2:
|
||||
term = parts[1]
|
||||
# Reftest master manifests also include skip-if lines and relative
|
||||
# paths we aren't doing to resolve here, so unlike above this is just
|
||||
# a substring check.
|
||||
if (term in target_manifests or
|
||||
any(l in term for l in target_manifests)):
|
||||
return True
|
||||
return False
|
||||
|
||||
# The master manifests we need to filter for target manifests.
|
||||
# TODO: All this needs to go in a config file somewhere and get sewn
|
||||
# into the job definition so its less likely to break as things are
|
||||
# modified. One straightforward way to achieve this would be with a key
|
||||
# in the tree manifest for the master manifest path, however the current
|
||||
# tree manifests don't distinguish between flavors of mochitests to this
|
||||
# isn't straightforward.
|
||||
master_manifests = [
|
||||
('mochitest/chrome/chrome.ini', filter_ini_manifest),
|
||||
('mochitest/browser/browser-chrome.ini', filter_ini_manifest),
|
||||
('mochitest/tests/mochitest.ini', filter_ini_manifest),
|
||||
('xpcshell/tests/all-test-dirs.list', filter_ini_manifest),
|
||||
('xpcshell/tests/xpcshell.ini', filter_ini_manifest),
|
||||
('reftest/tests/layout/reftests/reftest.list', filter_list_manifest),
|
||||
('reftest/tests/testing/crashtest/crashtests.list', filter_list_manifest),
|
||||
]
|
||||
|
||||
dirs = self.query_abs_dirs()
|
||||
tests_dir = dirs.get('abs_test_install_dir',
|
||||
os.path.join(dirs['abs_work_dir'], 'tests'))
|
||||
master_manifests = [(os.path.join(tests_dir, name), filter_fn) for (name, filter_fn) in
|
||||
master_manifests]
|
||||
for m, filter_fn in master_manifests:
|
||||
if not os.path.isfile(m):
|
||||
continue
|
||||
|
||||
self.info("Filtering master manifest at: %s" % m)
|
||||
lines = self.read_from_file(m).splitlines()
|
||||
|
||||
out_lines = [line for line in lines if filter_fn(line)]
|
||||
|
||||
self.rmtree(m)
|
||||
self.write_to_file(m, '\n'.join(out_lines))
|
||||
|
||||
|
||||
def append_harness_extra_args(self, cmd):
|
||||
"""Append arguments derived from try syntax to a command."""
|
||||
# TODO: Detect and reject incompatible arguments
|
||||
args = self.harness_extra_args[:] if self.harness_extra_args else []
|
||||
|
||||
if self.try_test_paths.get(flavor):
|
||||
extra_args = self.harness_extra_args[:] if self.harness_extra_args else []
|
||||
if self.try_test_paths:
|
||||
self._resolve_specified_manifests()
|
||||
self.info('TinderboxPrint: Tests will be run from the following '
|
||||
'files: %s.' % ','.join(self.try_test_paths[flavor]))
|
||||
args.extend(['--this-chunk=1', '--total-chunks=1'])
|
||||
'manifests: %s.' % ','.join(self.try_test_paths))
|
||||
extra_args.extend(['--this-chunk=1', '--total-chunks=1'])
|
||||
|
||||
path_func = test_flavors[flavor].get("path", lambda x:x)
|
||||
tests = [path_func(item) for item in self.try_test_paths[flavor]]
|
||||
else:
|
||||
tests = []
|
||||
if not extra_args:
|
||||
return cmd
|
||||
|
||||
if args or tests:
|
||||
self.info('TinderboxPrint: The following arguments were forwarded from mozharness '
|
||||
'to the test command:\nTinderboxPrint: \t%s -- %s' %
|
||||
(" ".join(args), " ".join(tests)))
|
||||
out_cmd = cmd[:]
|
||||
out_cmd.extend(extra_args)
|
||||
self.info('TinderboxPrint: The following arguments were forwarded from mozharness '
|
||||
'to the test command:\nTinderboxPrint: \t%s' %
|
||||
extra_args)
|
||||
|
||||
return args, tests
|
||||
return out_cmd
|
||||
|
@ -483,12 +483,14 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
|
||||
continue
|
||||
cmd.append(arg)
|
||||
|
||||
try_options, try_tests = self.try_args(suite_category)
|
||||
cmd.extend(try_options)
|
||||
cmd.extend(self.query_tests_args(
|
||||
self.config["suite_definitions"][suite_category].get("tests"),
|
||||
self.test_suite_definitions[self.test_suite].get("tests"),
|
||||
try_tests))
|
||||
tests = None
|
||||
if "tests" in self.test_suite_definitions[self.test_suite]:
|
||||
tests = self.test_suite_definitions[self.test_suite]["tests"]
|
||||
elif "tests" in self.config["suite_definitions"][suite_category]:
|
||||
tests = self.config["suite_definitions"][suite_category]["tests"]
|
||||
|
||||
if tests:
|
||||
cmd.extend(tests)
|
||||
|
||||
return cmd
|
||||
|
||||
@ -662,7 +664,7 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
|
||||
Run the tests
|
||||
"""
|
||||
cmd = self._build_command()
|
||||
|
||||
cmd = self.append_harness_extra_args(cmd)
|
||||
try:
|
||||
cwd = self._query_tests_dir()
|
||||
except:
|
||||
|
@ -217,20 +217,6 @@ class PandaTest(TestingMixin, MercurialScript, BlobUploadMixin, MozpoolMixin, Bu
|
||||
if self._query_specified_suites(cat) is not None]
|
||||
super(PandaTest, self).download_and_extract(suite_categories=target_categories)
|
||||
|
||||
def _query_try_flavor(self, category, suite):
|
||||
flavors = {
|
||||
"mochitest": [("plain.*", "mochitest"),
|
||||
("browser-chrome.*", "browser-chrome"),
|
||||
("mochitest-devtools-chrome.*", "devtools-chrome"),
|
||||
("chrome", "chrome")],
|
||||
"xpcshell": [("xpcshell", "xpcshell")],
|
||||
"reftest": [("reftest", "reftest"),
|
||||
("crashtest", "crashtest")]
|
||||
}
|
||||
for suite_pattern, flavor in flavors.get(category, []):
|
||||
if re.compile(suite_pattern).match(suite):
|
||||
return flavor
|
||||
|
||||
def _run_category_suites(self, suite_category, preflight_run_method=None):
|
||||
"""run suite(s) to a specific category"""
|
||||
|
||||
@ -260,13 +246,11 @@ class PandaTest(TestingMixin, MercurialScript, BlobUploadMixin, MozpoolMixin, Bu
|
||||
if should_install_app:
|
||||
self._install_app()
|
||||
cmd = abs_base_cmd[:]
|
||||
replace_dict = {}
|
||||
for arg in suites[suite]:
|
||||
cmd.append(arg % replace_dict)
|
||||
|
||||
flavor = self._query_try_flavor(suite_category, suite)
|
||||
try_options, try_tests = self.try_args(flavor)
|
||||
|
||||
cmd.extend(self.query_options(suites[suite],
|
||||
try_options))
|
||||
cmd.extend(self.query_tests_args(try_tests))
|
||||
cmd = self.append_harness_extra_args(cmd)
|
||||
|
||||
tests = self.config["suite_definitions"][suite_category].get("tests", [])
|
||||
cmd += tests
|
||||
|
@ -452,12 +452,10 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
|
||||
continue
|
||||
cmd.append(arg)
|
||||
|
||||
try_options, try_tests = self.try_args(suite_category)
|
||||
cmd.extend(try_options)
|
||||
cmd.extend(self.query_tests_args(
|
||||
self.config["suite_definitions"][suite_category].get("tests"),
|
||||
self.test_suite_definitions[self.test_suite].get("tests"),
|
||||
try_tests))
|
||||
if "tests" in self.test_suite_definitions[suite_name]:
|
||||
cmd.extend(self.suite_definitions[suite_name]["tests"])
|
||||
elif "tests" in c["suite_definitions"][suite_category]:
|
||||
cmd.extend(self.config["suite_definitions"][suite_category]["tests"])
|
||||
|
||||
return cmd
|
||||
|
||||
@ -479,6 +477,7 @@ class AndroidEmulatorTest(BlobUploadMixin, TestingMixin, EmulatorMixin, VCSMixin
|
||||
"""
|
||||
dirs = self.query_abs_dirs()
|
||||
cmd = self._build_command(self.emulators[emulator_index], suite_name)
|
||||
cmd = self.append_harness_extra_args(cmd)
|
||||
|
||||
try:
|
||||
cwd = self._query_tests_dir(suite_name)
|
||||
|
@ -139,7 +139,6 @@ class B2GDesktopTest(BlobUploadMixin, TestingMixin, MercurialScript):
|
||||
'%s_raw.log' % suite)
|
||||
error_summary_file = os.path.join(dirs['abs_blob_upload_dir'],
|
||||
'%s_errorsummary.log' % suite)
|
||||
|
||||
str_format_values = {
|
||||
'application': self.binary_path,
|
||||
'test_manifest': self.test_manifest,
|
||||
@ -157,15 +156,16 @@ class B2GDesktopTest(BlobUploadMixin, TestingMixin, MercurialScript):
|
||||
if suite not in self.config["suite_definitions"]:
|
||||
self.fatal("'%s' not defined in the config!" % suite)
|
||||
|
||||
try_options, try_tests = self.try_args(suite)
|
||||
options = self.config["suite_definitions"][suite]["options"]
|
||||
if options:
|
||||
for option in options:
|
||||
option = option % str_format_values
|
||||
if not option.endswith('None'):
|
||||
cmd.append(option)
|
||||
|
||||
cmd.extend(self.query_options(self.config["suite_definitions"][suite]["options"],
|
||||
try_options,
|
||||
str_format_values=str_format_values))
|
||||
|
||||
cmd.extend(self.query_tests_args(self.config["suite_definitions"][suite].get("tests"),
|
||||
try_tests,
|
||||
str_format_values=str_format_values))
|
||||
tests = self.config["suite_definitions"][suite].get("tests")
|
||||
if tests:
|
||||
cmd.extend(tests)
|
||||
|
||||
return cmd
|
||||
|
||||
@ -200,6 +200,7 @@ class B2GDesktopTest(BlobUploadMixin, TestingMixin, MercurialScript):
|
||||
self.fatal("Don't know how to run --test-suite '%s'!" % suite)
|
||||
|
||||
cmd = self._query_abs_base_cmd(suite)
|
||||
cmd = self.append_harness_extra_args(cmd)
|
||||
|
||||
cwd = dirs['abs_%s_dir' % suite]
|
||||
|
||||
|
@ -273,19 +273,18 @@ class B2GEmulatorTest(TestingMixin, VCSMixin, BaseScript, BlobUploadMixin):
|
||||
}
|
||||
|
||||
if suite not in self.config["suite_definitions"]:
|
||||
self.fatal("'%s' not defined in the config!" % suite)
|
||||
self.fatal("Key '%s' not defined in the config!" % suite)
|
||||
|
||||
try_options, try_tests = self.try_args(suite)
|
||||
options = self.config["suite_definitions"][suite]["options"]
|
||||
if options:
|
||||
for option in options:
|
||||
option = option % str_format_values
|
||||
if not option.endswith('None'):
|
||||
cmd.append(option)
|
||||
|
||||
options = self.query_options(self.config["suite_definitions"][suite]["options"],
|
||||
try_options,
|
||||
str_format_values=str_format_values)
|
||||
cmd.extend(opt for opt in options if not opt.endswith('None'))
|
||||
|
||||
tests = self.query_tests_args(self.config["suite_definitions"][suite].get("tests"),
|
||||
try_tests,
|
||||
str_format_values=str_format_values)
|
||||
cmd.extend(opt for opt in tests if not opt.endswith('None'))
|
||||
tests = self.config["suite_definitions"][suite].get("tests", [])
|
||||
if tests:
|
||||
cmd.extend(tests)
|
||||
|
||||
return cmd
|
||||
|
||||
@ -342,6 +341,8 @@ class B2GEmulatorTest(TestingMixin, VCSMixin, BaseScript, BlobUploadMixin):
|
||||
self.fatal("Don't know how to run --test-suite '%s'!" % suite)
|
||||
|
||||
cmd = self._query_abs_base_cmd(suite)
|
||||
cmd = self.append_harness_extra_args(cmd)
|
||||
|
||||
cwd = dirs['abs_%s_dir' % suite]
|
||||
|
||||
# TODO we probably have to move some of the code in
|
||||
|
@ -34,6 +34,7 @@ from mozharness.mozilla.testing.testbase import TestingMixin, testing_config_opt
|
||||
|
||||
SUITE_CATEGORIES = ['gtest', 'cppunittest', 'jittest', 'mochitest', 'reftest', 'xpcshell', 'mozbase', 'mozmill', 'webapprt']
|
||||
|
||||
|
||||
# DesktopUnittest {{{1
|
||||
class DesktopUnittest(TestingMixin, MercurialScript, BlobUploadMixin, MozbaseMixin, CodeCoverageMixin):
|
||||
config_options = [
|
||||
@ -298,6 +299,32 @@ class DesktopUnittest(TestingMixin, MercurialScript, BlobUploadMixin, MozbaseMix
|
||||
self.symbols_url = symbols_url
|
||||
return self.symbols_url
|
||||
|
||||
def get_webapprt_path(self, res_dir, mochitest_dir):
|
||||
"""Get the path to the webapp runtime binary.
|
||||
On Mac, we copy the stub from the resources dir to the test app bundle,
|
||||
since we have to run it from the executable directory of a bundle
|
||||
in order for its windows to appear. Ideally, the build system would do
|
||||
this for us at build time, and we should find a way for it to do that.
|
||||
"""
|
||||
exe_suffix = self.config.get('exe_suffix', '')
|
||||
app_name = 'webapprt-stub' + exe_suffix
|
||||
app_path = os.path.join(res_dir, app_name)
|
||||
if self._is_darwin():
|
||||
mac_dir_name = os.path.join(
|
||||
mochitest_dir,
|
||||
'webapprtChrome',
|
||||
'webapprt',
|
||||
'test',
|
||||
'chrome',
|
||||
'TestApp.app',
|
||||
'Contents',
|
||||
'MacOS')
|
||||
mac_app_name = 'webapprt' + exe_suffix
|
||||
mac_app_path = os.path.join(mac_dir_name, mac_app_name)
|
||||
self.copyfile(app_path, mac_app_path, copystat=True)
|
||||
return mac_app_path
|
||||
return app_path
|
||||
|
||||
def _query_abs_base_cmd(self, suite_category, suite):
|
||||
if self.binary_path:
|
||||
c = self.config
|
||||
@ -308,11 +335,6 @@ class DesktopUnittest(TestingMixin, MercurialScript, BlobUploadMixin, MozbaseMix
|
||||
abs_app_dir = self.query_abs_app_dir()
|
||||
abs_res_dir = self.query_abs_res_dir()
|
||||
|
||||
webapprt_path = os.path.join(os.path.dirname(self.binary_path),
|
||||
'webapprt-stub')
|
||||
if c.get('exe_suffix'):
|
||||
webapprt_path += c['exe_suffix']
|
||||
|
||||
raw_log_file = os.path.join(dirs['abs_blob_upload_dir'],
|
||||
'%s_raw.log' % suite)
|
||||
|
||||
@ -322,7 +344,7 @@ class DesktopUnittest(TestingMixin, MercurialScript, BlobUploadMixin, MozbaseMix
|
||||
'binary_path': self.binary_path,
|
||||
'symbols_path': self._query_symbols_url(),
|
||||
'abs_app_dir': abs_app_dir,
|
||||
'app_path': webapprt_path,
|
||||
'abs_res_dir': abs_res_dir,
|
||||
'raw_log_file': raw_log_file,
|
||||
'error_summary_file': error_summary_file,
|
||||
'gtest_dir': os.path.join(dirs['abs_test_install_dir'],
|
||||
@ -334,6 +356,9 @@ class DesktopUnittest(TestingMixin, MercurialScript, BlobUploadMixin, MozbaseMix
|
||||
if self.symbols_path:
|
||||
str_format_values['symbols_path'] = self.symbols_path
|
||||
|
||||
if suite_category == 'webapprt':
|
||||
str_format_values['app_path'] = self.get_webapprt_path(abs_res_dir, dirs['abs_mochitest_dir'])
|
||||
|
||||
if c['e10s']:
|
||||
base_cmd.append('--e10s')
|
||||
|
||||
@ -373,14 +398,7 @@ class DesktopUnittest(TestingMixin, MercurialScript, BlobUploadMixin, MozbaseMix
|
||||
"please make sure they are specified in your "
|
||||
"config under %s_options" %
|
||||
(suite_category, suite_category))
|
||||
|
||||
|
||||
for option in options:
|
||||
option = option % str_format_values
|
||||
if not option.endswith('None'):
|
||||
base_cmd.append(option)
|
||||
|
||||
return base_cmd
|
||||
return base_cmd
|
||||
else:
|
||||
self.fatal("'binary_path' could not be determined.\n This should "
|
||||
"be like '/path/build/application/firefox/firefox'"
|
||||
@ -416,20 +434,6 @@ class DesktopUnittest(TestingMixin, MercurialScript, BlobUploadMixin, MozbaseMix
|
||||
|
||||
return suites
|
||||
|
||||
def _query_try_flavor(self, category, suite):
|
||||
flavors = {
|
||||
"mochitest": [("plain.*", "mochitest"),
|
||||
("browser-chrome.*", "browser-chrome"),
|
||||
("mochitest-devtools-chrome.*", "devtools-chrome"),
|
||||
("chrome", "chrome")],
|
||||
"xpcshell": [("xpcshell", "xpcshell")],
|
||||
"reftest": [("reftest", "reftest"),
|
||||
("crashtest", "crashtest")]
|
||||
}
|
||||
for suite_pattern, flavor in flavors.get(category, []):
|
||||
if re.compile(suite_pattern).match(suite):
|
||||
return flavor
|
||||
|
||||
# Actions {{{2
|
||||
|
||||
# clobber defined in BaseScript, deletes mozharness/build if exists
|
||||
@ -584,22 +588,15 @@ class DesktopUnittest(TestingMixin, MercurialScript, BlobUploadMixin, MozbaseMix
|
||||
options_list = []
|
||||
env = {}
|
||||
if isinstance(suites[suite], dict):
|
||||
options_list = suites[suite].get('options', [])
|
||||
tests_list = suites[suite].get('tests', [])
|
||||
options_list = suites[suite]['options'] + suites[suite].get("tests", [])
|
||||
env = copy.deepcopy(suites[suite].get('env', {}))
|
||||
else:
|
||||
options_list = suites[suite]
|
||||
tests_list = []
|
||||
|
||||
flavor = self._query_try_flavor(suite_category, suite)
|
||||
try_options, try_tests = self.try_args(flavor)
|
||||
for arg in options_list:
|
||||
cmd.append(arg % replace_dict)
|
||||
|
||||
cmd.extend(self.query_options(options_list,
|
||||
try_options,
|
||||
str_format_values=replace_dict))
|
||||
cmd.extend(self.query_tests_args(tests_list,
|
||||
try_tests,
|
||||
str_format_values=replace_dict))
|
||||
cmd = self.append_harness_extra_args(cmd)
|
||||
|
||||
suite_name = suite_category + '-' + suite
|
||||
tbpl_status, log_level = None, None
|
||||
|
@ -439,10 +439,7 @@ class MarionetteTest(TestingMixin, MercurialScript, BlobUploadMixin, TransferMix
|
||||
self.fatal("Could not create blobber upload directory")
|
||||
|
||||
cmd.append(manifest)
|
||||
|
||||
try_options, try_tests = self.try_args("marionette")
|
||||
cmd.extend(self.query_tests_args(try_tests,
|
||||
str_format_values=config_fmt_args))
|
||||
cmd = self.append_harness_extra_args(cmd)
|
||||
|
||||
env = {}
|
||||
if self.query_minidump_stackwalk():
|
||||
|
@ -115,31 +115,31 @@ class WebPlatformTest(TestingMixin, MercurialScript, BlobUploadMixin):
|
||||
abs_app_dir = self.query_abs_app_dir()
|
||||
run_file_name = "runtests.py"
|
||||
|
||||
cmd = [self.query_python_path('python'), '-u']
|
||||
cmd.append(os.path.join(dirs["abs_wpttest_dir"], run_file_name))
|
||||
base_cmd = [self.query_python_path('python'), '-u']
|
||||
base_cmd.append(os.path.join(dirs["abs_wpttest_dir"], run_file_name))
|
||||
|
||||
# Make sure that the logging directory exists
|
||||
if self.mkdir_p(dirs["abs_blob_upload_dir"]) == -1:
|
||||
self.fatal("Could not create blobber upload directory")
|
||||
# Exit
|
||||
|
||||
cmd += ["--log-raw=-",
|
||||
"--log-raw=%s" % os.path.join(dirs["abs_blob_upload_dir"],
|
||||
"wpt_raw.log"),
|
||||
"--binary=%s" % self.binary_path,
|
||||
"--symbols-path=%s" % self.query_symbols_url(),
|
||||
"--stackwalk-binary=%s" % self.query_minidump_stackwalk()]
|
||||
base_cmd += ["--log-raw=-",
|
||||
"--log-raw=%s" % os.path.join(dirs["abs_blob_upload_dir"],
|
||||
"wpt_raw.log"),
|
||||
"--binary=%s" % self.binary_path,
|
||||
"--symbols-path=%s" % self.query_symbols_url(),
|
||||
"--stackwalk-binary=%s" % self.query_minidump_stackwalk()]
|
||||
|
||||
for test_type in c.get("test_type", []):
|
||||
cmd.append("--test-type=%s" % test_type)
|
||||
base_cmd.append("--test-type=%s" % test_type)
|
||||
|
||||
if c.get("e10s"):
|
||||
cmd.append("--e10s")
|
||||
base_cmd.append("--e10s")
|
||||
|
||||
for opt in ["total_chunks", "this_chunk"]:
|
||||
val = c.get(opt)
|
||||
if val:
|
||||
cmd.append("--%s=%s" % (opt.replace("_", "-"), val))
|
||||
base_cmd.append("--%s=%s" % (opt.replace("_", "-"), val))
|
||||
|
||||
options = list(c.get("options", []))
|
||||
|
||||
@ -151,15 +151,9 @@ class WebPlatformTest(TestingMixin, MercurialScript, BlobUploadMixin):
|
||||
'abs_work_dir': dirs["abs_work_dir"]
|
||||
}
|
||||
|
||||
try_options, try_tests = self.try_args("web-platform-tests")
|
||||
opt_cmd = [item % str_format_values for item in options]
|
||||
|
||||
cmd.extend(self.query_options(options,
|
||||
try_options,
|
||||
str_format_values=str_format_values))
|
||||
cmd.extend(self.query_tests_args(try_tests,
|
||||
str_format_values=str_format_values))
|
||||
|
||||
return cmd
|
||||
return base_cmd + opt_cmd
|
||||
|
||||
def download_and_extract(self):
|
||||
super(WebPlatformTest, self).download_and_extract(
|
||||
@ -173,6 +167,7 @@ class WebPlatformTest(TestingMixin, MercurialScript, BlobUploadMixin):
|
||||
def run_tests(self):
|
||||
dirs = self.query_abs_dirs()
|
||||
cmd = self._query_cmd()
|
||||
cmd = self.append_harness_extra_args(cmd)
|
||||
|
||||
parser = StructuredOutputParser(config=self.config,
|
||||
log_obj=self.log_obj)
|
||||
|
@ -2,172 +2,30 @@
|
||||
# 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/.
|
||||
|
||||
import argparse
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
import itertools
|
||||
import subprocess
|
||||
import which
|
||||
|
||||
from collections import defaultdict
|
||||
|
||||
import ConfigParser
|
||||
|
||||
|
||||
def arg_parser():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('paths', nargs='*', help='Paths to search for tests to run on try.')
|
||||
parser.add_argument('-b', dest='builds', default='do',
|
||||
help='Build types to run (d for debug, o for optimized).')
|
||||
parser.add_argument('-p', dest='platforms', action="append",
|
||||
help='Platforms to run (required if not found in the environment).')
|
||||
parser.add_argument('-u', dest='tests', action="append",
|
||||
help='Test suites to run in their entirety.')
|
||||
parser.add_argument('-t', dest="talos", action="append",
|
||||
help='Talos suites to run.')
|
||||
parser.add_argument('--tag', dest='tags', action='append',
|
||||
help='Restrict tests to the given tag (may be specified multiple times).')
|
||||
parser.add_argument('--and', action='store_true', dest="intersection",
|
||||
help='When -u and paths are supplied run only the intersection of the tests specified by the two arguments.')
|
||||
parser.add_argument('--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).')
|
||||
parser.add_argument('--save', dest="save", action='store',
|
||||
help="Save the command line arguments for future use with --preset.")
|
||||
parser.add_argument('--preset', dest="load", action='store',
|
||||
help="Load a saved set of arguments. Additional arguments will override saved ones.")
|
||||
parser.add_argument('extra_args', nargs=argparse.REMAINDER,
|
||||
help='Extra arguments to put in the try push.')
|
||||
parser.add_argument('-v', "--verbose", dest='verbose', action='store_true', default=False,
|
||||
help='Print detailed information about the resulting test selection '
|
||||
'and commands performed.')
|
||||
return parser
|
||||
|
||||
class TryArgumentTokenizer(object):
|
||||
symbols = [("seperator", ","),
|
||||
("list_start", "\["),
|
||||
("list_end", "\]"),
|
||||
("item", "([^,\[\]\s][^,\[\]]+)"),
|
||||
("space", "\s+")]
|
||||
token_re = re.compile("|".join("(?P<%s>%s)" % item for item in symbols))
|
||||
|
||||
def tokenize(self, data):
|
||||
for match in self.token_re.finditer(data):
|
||||
symbol = match.lastgroup
|
||||
data = match.group(symbol)
|
||||
if symbol == "space":
|
||||
pass
|
||||
else:
|
||||
yield symbol, data
|
||||
|
||||
class TryArgumentParser(object):
|
||||
"""Simple three-state parser for handling expressions
|
||||
of the from "foo[sub item, another], bar,baz". This takes
|
||||
input from the TryArgumentTokenizer and runs through a small
|
||||
state machine, returning a dictionary of {top-level-item:[sub_items]}
|
||||
i.e. the above would result in
|
||||
{"foo":["sub item", "another"], "bar": [], "baz": []}
|
||||
In the case of invalid input a ValueError is raised."""
|
||||
|
||||
EOF = object()
|
||||
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self.tokens = None
|
||||
self.current_item = None
|
||||
self.data = {}
|
||||
self.token = None
|
||||
self.state = None
|
||||
|
||||
def parse(self, tokens):
|
||||
self.reset()
|
||||
self.tokens = tokens
|
||||
self.consume()
|
||||
self.state = self.item_state
|
||||
while self.token[0] != self.EOF:
|
||||
self.state()
|
||||
return self.data
|
||||
|
||||
def consume(self):
|
||||
try:
|
||||
self.token = self.tokens.next()
|
||||
except StopIteration:
|
||||
self.token = (self.EOF, None)
|
||||
|
||||
def expect(self, *types):
|
||||
if self.token[0] not in types:
|
||||
raise ValueError("Error parsing try string, unexpected %s" % (self.token[0]))
|
||||
|
||||
def item_state(self):
|
||||
self.expect("item")
|
||||
value = self.token[1].strip()
|
||||
if value not in self.data:
|
||||
self.data[value] = []
|
||||
self.current_item = value
|
||||
self.consume()
|
||||
if self.token[0] == "seperator":
|
||||
self.consume()
|
||||
elif self.token[0] == "list_start":
|
||||
self.consume()
|
||||
self.state = self.subitem_state
|
||||
elif self.token[0] == self.EOF:
|
||||
pass
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
def subitem_state(self):
|
||||
self.expect("item")
|
||||
value = self.token[1].strip()
|
||||
self.data[self.current_item].append(value)
|
||||
self.consume()
|
||||
if self.token[0] == "seperator":
|
||||
self.consume()
|
||||
elif self.token[0] == "list_end":
|
||||
self.consume()
|
||||
self.state = self.after_list_end_state
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
def after_list_end_state(self):
|
||||
self.expect("seperator")
|
||||
self.consume()
|
||||
self.state = self.item_state
|
||||
|
||||
def parse_arg(arg):
|
||||
tokenizer = TryArgumentTokenizer()
|
||||
parser = TryArgumentParser()
|
||||
return parser.parse(tokenizer.tokenize(arg))
|
||||
TRY_SYNTAX_TMPL = """
|
||||
try: -b %s -p %s -u %s -t none %s %s
|
||||
"""
|
||||
|
||||
class AutoTry(object):
|
||||
|
||||
# Maps from flavors to the job names needed to run that flavour
|
||||
flavor_jobs = {
|
||||
'mochitest': ['mochitest-1', 'mochitest-e10s-1'],
|
||||
'xpcshell': ['xpcshell'],
|
||||
'chrome': ['mochitest-o'],
|
||||
'browser-chrome': ['mochitest-browser-chrome-1',
|
||||
'mochitest-e10s-browser-chrome-1'],
|
||||
'devtools-chrome': ['mochitest-dt',
|
||||
'mochitest-e10s-devtools-chrome'],
|
||||
'crashtest': ['crashtest', 'crashtest-e10s'],
|
||||
'reftest': ['reftest', 'reftest-e10s'],
|
||||
'web-platform-tests': ['web-platform-tests-1'],
|
||||
}
|
||||
|
||||
flavor_suites = {
|
||||
"mochitest": "mochitests",
|
||||
"xpcshell": "xpcshell",
|
||||
"chrome": "mochitest-o",
|
||||
"browser-chrome": "mochitest-bc",
|
||||
"devtools-chrome": "mochitest-dt",
|
||||
"crashtest": "crashtest",
|
||||
"reftest": "reftest",
|
||||
"web-platform-tests": "web-platform-tests",
|
||||
}
|
||||
test_flavors = [
|
||||
'browser-chrome',
|
||||
'chrome',
|
||||
'devtools-chrome',
|
||||
'mochitest',
|
||||
'xpcshell',
|
||||
'reftest',
|
||||
'crashtest',
|
||||
]
|
||||
|
||||
def __init__(self, topsrcdir, resolver, mach_context):
|
||||
self.topsrcdir = topsrcdir
|
||||
@ -179,107 +37,57 @@ class AutoTry(object):
|
||||
else:
|
||||
self._use_git = True
|
||||
|
||||
@property
|
||||
def config_path(self):
|
||||
return os.path.join(self.mach_context.state_dir, "autotry.ini")
|
||||
|
||||
def load_config(self, name):
|
||||
config = ConfigParser.RawConfigParser()
|
||||
success = config.read([self.config_path])
|
||||
if not success:
|
||||
return None
|
||||
|
||||
try:
|
||||
data = config.get("try", name)
|
||||
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError):
|
||||
return None
|
||||
|
||||
kwargs = vars(arg_parser().parse_args(data.split()))
|
||||
|
||||
return kwargs
|
||||
|
||||
def save_config(self, name, data):
|
||||
assert data.startswith("try: ")
|
||||
data = data[len("try: "):]
|
||||
|
||||
parser = ConfigParser.RawConfigParser()
|
||||
parser.read([self.config_path])
|
||||
|
||||
if not parser.has_section("try"):
|
||||
parser.add_section("try")
|
||||
|
||||
parser.set("try", name, data)
|
||||
|
||||
with open(self.config_path, "w") as f:
|
||||
parser.write(f)
|
||||
|
||||
def paths_by_flavor(self, paths=None, tags=None):
|
||||
paths_by_flavor = defaultdict(set)
|
||||
|
||||
def resolve_manifests(self, paths=None, tags=None):
|
||||
if not (paths or tags):
|
||||
return dict(paths_by_flavor)
|
||||
return {}
|
||||
|
||||
tests = list(self.resolver.resolve_tests(paths=paths,
|
||||
tags=tags))
|
||||
tests = list(self.resolver.resolve_tests(tags=tags,
|
||||
paths=paths,
|
||||
cwd=self.mach_context.cwd))
|
||||
manifests_by_flavor = defaultdict(set)
|
||||
|
||||
for t in tests:
|
||||
if t['flavor'] in self.flavor_suites:
|
||||
if t['flavor'] in AutoTry.test_flavors:
|
||||
flavor = t['flavor']
|
||||
if 'subsuite' in t and t['subsuite'] == 'devtools':
|
||||
flavor = 'devtools-chrome'
|
||||
manifest = os.path.relpath(t['manifest'], self.topsrcdir)
|
||||
manifests_by_flavor[flavor].add(manifest)
|
||||
|
||||
for path in paths:
|
||||
if flavor in ["crashtest", "reftest"]:
|
||||
manifest_relpath = os.path.relpath(t['manifest'], self.topsrcdir)
|
||||
if manifest_relpath.startswith(path):
|
||||
paths_by_flavor[flavor].add(manifest_relpath)
|
||||
else:
|
||||
if t['file_relpath'].startswith(path):
|
||||
paths_by_flavor[flavor].add(path)
|
||||
return dict(manifests_by_flavor)
|
||||
|
||||
return dict(paths_by_flavor)
|
||||
def calc_try_syntax(self, platforms, flavors, tests, extra_tests, builds,
|
||||
manifests, tags):
|
||||
|
||||
def remove_duplicates(self, paths_by_flavor, tests):
|
||||
rv = {}
|
||||
for item in paths_by_flavor:
|
||||
if self.flavor_suites[item] not in tests:
|
||||
rv[item] = paths_by_flavor[item].copy()
|
||||
return rv
|
||||
|
||||
def calc_try_syntax(self, platforms, tests, talos, builds, paths_by_flavor, tags,
|
||||
extra_args, intersection):
|
||||
parts = ["try:", "-b", builds, "-p", ",".join(platforms)]
|
||||
|
||||
suites = tests if not intersection else {}
|
||||
paths = set()
|
||||
for flavor, flavor_tests in paths_by_flavor.iteritems():
|
||||
suite = self.flavor_suites[flavor]
|
||||
if suite not in suites and (not intersection or suite in tests):
|
||||
for job_name in self.flavor_jobs[flavor]:
|
||||
for test in flavor_tests:
|
||||
paths.add("%s:%s" % (flavor, test))
|
||||
suites[job_name] = tests.get(suite, [])
|
||||
|
||||
if not suites:
|
||||
raise ValueError("No tests found matching filters")
|
||||
|
||||
parts.append("-u")
|
||||
parts.append(",".join("%s%s" % (k, "[%s]" % ",".join(v) if v else "")
|
||||
for k,v in sorted(suites.items())) if suites else "none")
|
||||
|
||||
parts.append("-t")
|
||||
parts.append(",".join(talos) if talos else "none")
|
||||
# Maps from flavors to the try syntax snippets implied by that flavor.
|
||||
# TODO: put selected tests under their own builder/label to avoid
|
||||
# confusion reading results on treeherder.
|
||||
flavor_suites = {
|
||||
'mochitest': ['mochitest-1', 'mochitest-e10s-1'],
|
||||
'xpcshell': ['xpcshell'],
|
||||
'chrome': ['mochitest-o'],
|
||||
'browser-chrome': ['mochitest-browser-chrome-1',
|
||||
'mochitest-e10s-browser-chrome-1'],
|
||||
'devtools-chrome': ['mochitest-dt',
|
||||
'mochitest-e10s-devtools-chrome'],
|
||||
'crashtest': ['crashtest', 'crashtest-e10s'],
|
||||
'reftest': ['reftest', 'reftest-e10s'],
|
||||
}
|
||||
|
||||
if tags:
|
||||
parts.append(' '.join('--tag %s' % t for t in tags))
|
||||
tags = ' '.join('--tag %s' % t for t in tags)
|
||||
else:
|
||||
tags = ''
|
||||
|
||||
if extra_args is not None:
|
||||
parts.extend(extra_args)
|
||||
if not tests:
|
||||
tests = ','.join(itertools.chain(*(flavor_suites[f] for f in flavors)))
|
||||
if extra_tests:
|
||||
tests += ',%s' % (extra_tests)
|
||||
|
||||
if paths:
|
||||
parts.append("--try-test-paths %s" % " ".join(sorted(paths)))
|
||||
|
||||
return " ".join(parts)
|
||||
manifests = ' '.join(manifests)
|
||||
if manifests:
|
||||
manifests = '--try-test-paths %s' % manifests
|
||||
return TRY_SYNTAX_TMPL % (builds, platforms, tests, manifests, tags)
|
||||
|
||||
def _run_git(self, *args):
|
||||
args = ['git'] + list(args)
|
||||
|
Loading…
Reference in New Issue
Block a user