Backed out 5 changesets (bug 1634554) for lint failure CLOSED TREE

Backed out changeset e8db70067dbf (bug 1634554)
Backed out changeset ae24c9902708 (bug 1634554)
Backed out changeset 177cc940d57f (bug 1634554)
Backed out changeset 3240acbd85b6 (bug 1634554)
Backed out changeset 71aa576ada8b (bug 1634554)
This commit is contained in:
Bogdan Tara 2020-06-15 22:25:12 +03:00
Родитель ec7c82ed3a
Коммит 30c59d36db
8 изменённых файлов: 95 добавлений и 222 удалений

Просмотреть файл

@ -175,11 +175,6 @@ def mozharness_test_on_docker(config, job, taskdesc):
'task-reference': six.ensure_text(json.dumps(extra_config, sort_keys=True))
}
# Bug 1634554 - pass in decision task URL for manifest/test mapping for WPT.
if 'web-platform-tests' in test['suite']:
env['TESTS_BY_MANIFEST_URL'] = {
'artifact-reference': '<decision/public/tests-by-manifest.json.gz>'}
command = [
'{workdir}/bin/test-linux.sh'.format(**run),
]
@ -318,11 +313,6 @@ def mozharness_test_on_generic_worker(config, job, taskdesc):
'task-reference': six.ensure_text(json.dumps(extra_config, sort_keys=True))
}
# Bug 1634554 - pass in decision task URL for manifest/test mapping for WPT.
if 'web-platform-tests' in test['suite']:
env['TESTS_BY_MANIFEST_URL'] = {
'artifact-reference': '<decision/public/tests-by-manifest.json.gz>'}
if is_windows:
mh_command = [
'c:\\mozilla-build\\python\\python.exe',
@ -473,11 +463,6 @@ def mozharness_test_on_script_engine_autophone(config, job, taskdesc):
'task-reference': six.ensure_text(json.dumps(extra_config, sort_keys=True))
}
# Bug 1634554 - pass in decision task URL for manifest/test mapping for WPT.
if 'web-platform-tests' in test['suite']:
env['TESTS_BY_MANIFEST_URL'] = {
'artifact-reference': '<decision/public/tests-by-manifest.json.gz>'}
script = 'test-linux.sh'
worker['context'] = config.params.file_url(
'taskcluster/scripts/tester/{}'.format(script),

Просмотреть файл

@ -119,9 +119,9 @@ def chunk_manifests(suite, platform, chunks, manifests):
that run in that chunk.
"""
manifests = set(manifests)
runtimes = {k: v for k, v in get_runtimes(platform, suite).items() if k in manifests}
if "web-platform-tests" not in suite:
runtimes = {k: v for k, v in get_runtimes(platform, suite).items() if k in manifests}
return [
c[1] for c in chunk_by_runtime(
None,
@ -130,19 +130,52 @@ def chunk_manifests(suite, platform, chunks, manifests):
).get_chunked_manifests(manifests)
]
paths = {k: v for k, v in wpt_group_translation.items() if k in manifests}
# Python2 does not support native dictionary sorting, so use an OrderedDict
# instead, appending in order of highest to lowest runtime.
runtimes = OrderedDict(sorted(runtimes.items(), key=lambda x: x[1], reverse=True))
# Keep track of test paths for each chunk, and the runtime information.
chunked_manifests = [[] for _ in range(chunks)]
chunked_manifests = [[[], 0] for _ in range(chunks)]
# Spread out the test manifests evenly across all chunks.
for index, key in enumerate(sorted(manifests)):
chunked_manifests[index % chunks].append(key)
# Begin chunking the test paths in order from highest running time to lowest.
# The keys of runtimes dictionary should match the keys of the test paths
# dictionary.
for key, rt in runtimes.items():
# Sort the chunks from fastest to slowest, based on runtime info
# at x[1], then the number of test paths.
chunked_manifests.sort(key=lambda x: (x[1], len(x[0])))
# One last sort by the number of manifests. Chunk size should be more or less
# equal in size.
chunked_manifests.sort(key=lambda x: len(x))
# Look up if there are any test paths under the key in the paths dict.
test_paths = paths[key]
if test_paths:
# Add the full set of paths that live under the key and increase the
# total runtime counter by the value reported in runtimes.
chunked_manifests[0][0].extend(test_paths)
# chunked_manifests[0][0].append(key)
chunked_manifests[0][1] += rt
# Remove the key and test_paths since it has been scheduled.
paths.pop(key)
# Same goes for the value in runtimes dict.
runtimes.pop(key)
# Sort again prior to the next step.
chunked_manifests.sort(key=lambda x: (x[1], len(x[0])))
# Spread out the remaining test paths that were not scheduled in the previous
# step. Such paths did not have runtime information associated, likely due to
# implementation status.
for index, key in enumerate(paths.keys()):
# Append both the key and value in case the value is empty.
chunked_manifests[index % chunks][0].append(key)
# One last sort by the runtime, then number of test paths.
chunked_manifests.sort(key=lambda x: (x[1], len(x[0])))
# Return just the chunked test paths.
return chunked_manifests
return [c[0] for c in chunked_manifests]
@six.add_metaclass(ABCMeta)
@ -177,6 +210,29 @@ class BaseManifestLoader(object):
class DefaultLoader(BaseManifestLoader):
"""Load manifests using metadata from the TestResolver."""
@classmethod
def get_wpt_group(cls, test):
"""Get the group for a web-platform-test that matches those created by the
WPT harness.
Args:
test (dict): The test object to compute the group for.
Returns:
str: Label representing the group name.
"""
depth = 3
path = os.path.dirname(test['name'])
# Remove path elements beyond depth of 3, because WPT harness uses
# --run-by-dir=3 by convention in Mozilla CI.
# Note, this means /_mozilla tests retain an effective depth of 2 due to
# the extra prefix element.
while path.count('/') >= depth + 1:
path = os.path.dirname(path)
return path
@memoize
def get_tests(self, suite):
suite_definition = TEST_SUITES[suite]
@ -194,7 +250,10 @@ class DefaultLoader(BaseManifestLoader):
if "web-platform-tests" in suite:
manifests = set()
for t in tests:
group = self.get_wpt_group(t)
wpt_group_translation[t['manifest']].add(group)
manifests.add(t['manifest'])
return {"active": list(manifests), "skipped": []}
manifests = set(chunk_by_runtime.get_manifest(t) for t in tests)

Просмотреть файл

@ -693,26 +693,20 @@ class TestResolver(MozbuildObject):
return True
return False
def get_wpt_group(self, test, depth=3):
"""Given a test object set the group (aka manifest) that it belongs to.
If a custom value for `depth` is provided, it will override the default
value of 3 path components.
def get_wpt_group(self, test):
"""Given a test object, set the group (aka manifest) that it belongs to.
Args:
test (dict): Test object for the particular suite and subsuite.
depth (int, optional): Custom number of path elements.
Returns:
str: The group the given test belongs to.
"""
# This takes into account that for mozilla-specific WPT tests, the path
# contains an extra '/_mozilla' prefix that must be accounted for.
depth = depth + 1 if test['name'].startswith('/_mozilla') else depth
group = os.path.dirname(test['name'])
while group.count('/') > depth:
group = os.path.dirname(group)
# Extract the first path component (top level directory) as the key.
# This value should match the path in manifest-runtimes JSON data.
# Mozilla WPT paths have one extra URL component in the front.
components = 3 if test['name'].startswith('/_mozilla') else 2
group = '/'.join(test['name'].split('/')[:components])
return group
def add_wpt_manifest_data(self):

Просмотреть файл

@ -5,7 +5,6 @@
# You can obtain one at http://mozilla.org/MPL/2.0/.
# ***** END LICENSE BLOCK *****
import copy
import gzip
import json
import os
import sys
@ -124,7 +123,6 @@ class WebPlatformTest(TestingMixin, MercurialScript, CodeCoverageMixin, AndroidM
'setup-avds',
'start-emulator',
'download-and-extract',
'download-and-process-manifest',
'create-virtualenv',
'pull',
'verify-device',
@ -241,6 +239,7 @@ class WebPlatformTest(TestingMixin, MercurialScript, CodeCoverageMixin, AndroidM
"--symbols-path=%s" % self.symbols_path,
"--stackwalk-binary=%s" % self.query_minidump_stackwalk(),
"--stackfix-dir=%s" % os.path.join(dirs["abs_test_install_dir"], "bin"),
"--run-by-dir=%i" % (3 if not mozinfo.info["asan"] else 0),
"--no-pause-after-test",
"--instrument-to-file=%s" % os.path.join(dirs["abs_blob_upload_dir"],
"wpt_instruments.txt")]
@ -284,15 +283,9 @@ class WebPlatformTest(TestingMixin, MercurialScript, CodeCoverageMixin, AndroidM
if not (self.verify_enabled or self.per_test_coverage):
mozharness_test_paths = json.loads(os.environ.get('MOZHARNESS_TEST_PATHS', '""'))
if mozharness_test_paths:
path = os.path.join(
dirs["abs_fetches_dir"], 'wpt_tests_by_group.json')
if not os.path.exists(path):
self.critical('Unable to locate web-platform-test groups file.')
cmd.append("--test-groups={}".format(path))
for key in mozharness_test_paths.keys():
keys = (['web-platform-tests-%s' % test_type for test_type in test_types] +
['web-platform-tests'])
for key in keys:
paths = mozharness_test_paths.get(key, [])
for path in paths:
if not path.startswith("/"):
@ -303,9 +296,6 @@ class WebPlatformTest(TestingMixin, MercurialScript, CodeCoverageMixin, AndroidM
path = os.path.join(dirs["abs_wpttest_dir"], path)
test_paths.add(path)
else:
# As per WPT harness, the --run-by-dir flag is incompatible with
# the --test-groups flag.
cmd.append("--run-by-dir=%i" % (3 if not mozinfo.info["asan"] else 0))
for opt in ["total_chunks", "this_chunk"]:
val = c.get(opt)
if val:
@ -362,45 +352,6 @@ class WebPlatformTest(TestingMixin, MercurialScript, CodeCoverageMixin, AndroidM
self.fatal("Could not create blobber upload directory")
# Exit
def download_and_process_manifest(self):
"""Downloads the tests-by-manifest JSON mapping generated by the decision task.
web-platform-tests are chunked in the decision task as of Bug 1608837
and this means tests are resolved by the TestResolver as part of this process.
The manifest file contains tests keyed by the groups generated in
TestResolver.get_wpt_group().
Upon successful call, a JSON file containing only the web-platform test
groups are saved in the fetch directory.
Bug:
1634554
"""
dirs = self.query_abs_dirs()
url = os.environ.get('TESTS_BY_MANIFEST_URL', '')
if not url:
self.fatal('TESTS_BY_MANIFEST_URL not defined.')
artifact_name = url.split('/')[-1]
# Save file to the MOZ_FETCHES dir.
self.download_file(url, file_name=artifact_name,
parent_dir=dirs["abs_fetches_dir"])
with gzip.open(os.path.join(dirs["abs_fetches_dir"], artifact_name), 'r') as f:
tests_by_manifest = json.loads(f.read())
# We need to filter out non-web-platform-tests without knowing what the
# groups are. Fortunately, all web-platform test 'manifests' begin with a
# forward slash.
test_groups = {key: tests_by_manifest[key] for key in tests_by_manifest.keys()
if key.startswith("/")}
outfile = os.path.join(dirs["abs_fetches_dir"], "wpt_tests_by_group.json")
with open(outfile, 'w+') as f:
json.dump(test_groups, f, indent=2, sort_keys=True)
def install(self):
if self.is_android:
self.install_apk(self.installer_path)

Просмотреть файл

@ -1,5 +1,4 @@
import hashlib
import json
import os
from six.moves.urllib.parse import urlsplit
from abc import ABCMeta, abstractmethod
@ -27,45 +26,6 @@ def do_delayed_imports():
from manifest.download import download_from_github
class TestGroupsFile(object):
"""
Mapping object representing {group name: [test ids]}
"""
def __init__(self, logger, path):
try:
with open(path) as f:
self._data = json.load(f)
except ValueError:
logger.critical("test groups file %s not valid json" % path)
raise
self.group_by_test = {}
for group, test_ids in iteritems(self._data):
for test_id in test_ids:
self.group_by_test[test_id] = group
def __contains__(self, key):
return key in self._data
def __getitem__(self, key):
return self._data[key]
def update_include_for_groups(test_groups, include):
if include is None:
# We're just running everything
return
new_include = []
for item in include:
if item in test_groups:
new_include.extend(test_groups[item])
else:
new_include.append(item)
return new_include
class TestChunker(object):
def __init__(self, total_chunks, chunk_number, **kwargs):
self.total_chunks = total_chunks
@ -332,23 +292,6 @@ class TestLoader(object):
return groups
def get_test_src(**kwargs):
test_source_kwargs = {"processes": kwargs["processes"],
"logger": kwargs["logger"]}
chunker_kwargs = {}
if kwargs["run_by_dir"] is not False:
# A value of None indicates infinite depth
test_source_cls = PathGroupedSource
test_source_kwargs["depth"] = kwargs["run_by_dir"]
chunker_kwargs["depth"] = kwargs["run_by_dir"]
elif kwargs["test_groups"]:
test_source_cls = GroupFileTestSource
test_source_kwargs["test_groups"] = kwargs["test_groups"]
else:
test_source_cls = SingleTestSource
return test_source_cls, test_source_kwargs, chunker_kwargs
class TestSource(object):
__metaclass__ = ABCMeta
@ -454,39 +397,3 @@ class PathGroupedSource(GroupedSource):
@classmethod
def group_metadata(cls, state):
return {"scope": "/%s" % "/".join(state["prev_path"])}
class GroupFileTestSource(TestSource):
@classmethod
def make_queue(cls, tests, **kwargs):
tests_by_group = cls.tests_by_group(tests, **kwargs)
test_queue = Queue()
for group_name, tests in iteritems(tests_by_group):
group_metadata = {"scope": group_name}
group = deque()
for test in tests:
group.append(test)
test.update_metadata(group_metadata)
test_queue.put((group, group_metadata))
return test_queue
@classmethod
def tests_by_group(cls, tests, **kwargs):
logger = kwargs["logger"]
test_groups = kwargs["test_groups"]
tests_by_group = defaultdict(list)
for test in tests:
try:
group = test_groups.group_by_test[test.id]
except KeyError:
logger.error("%s is missing from test groups file" % test.id)
raise
tests_by_group[group].append(test)
return tests_by_group

Просмотреть файл

@ -700,9 +700,8 @@ class TestRunnerManager(threading.Thread):
test, test_group, group_metadata = self.get_next_test()
if test is None:
return RunnerManagerState.stop()
if test_group is not self.state.test_group:
if test_group != self.state.test_group:
# We are starting a new group of tests, so force a restart
self.logger.info("Restarting browser for new test group")
restart = True
else:
test_group = self.state.test_group

Просмотреть файл

@ -1,6 +1,5 @@
from __future__ import absolute_import, print_function
import argparse
import json
import os
import sys
from collections import OrderedDict
@ -136,8 +135,6 @@ scheme host and port.""")
help="URL prefix to exclude")
test_selection_group.add_argument("--include-manifest", type=abs_path,
help="Path to manifest listing tests to include")
test_selection_group.add_argument("--test-groups", dest="test_groups_file", type=abs_path,
help="Path to json file containing a mapping {group_name: [test_ids]}")
test_selection_group.add_argument("--skip-timeout", action="store_true",
help="Skip tests that are expected to time out")
test_selection_group.add_argument("--skip-implementation-status",
@ -507,14 +504,6 @@ def check_args(kwargs):
else:
kwargs["chunk_type"] = "none"
if kwargs["test_groups_file"] is not None:
if kwargs["run_by_dir"] is not False:
print("Can't pass --test-groups and --run-by-dir")
sys.exit(1)
if not os.path.exists(kwargs["test_groups_file"]):
print("--test-groups file %s not found" % kwargs["test_groups_file"])
sys.exit(1)
if kwargs["processes"] is None:
kwargs["processes"] = 1

Просмотреть файл

@ -45,8 +45,7 @@ def setup_logging(*args, **kwargs):
return logger
def get_loader(test_paths, product, debug=None, run_info_extras=None, chunker_kwargs=None,
test_groups=None, **kwargs):
def get_loader(test_paths, product, debug=None, run_info_extras=None, chunker_kwargs=None, **kwargs):
if run_info_extras is None:
run_info_extras = {}
@ -63,12 +62,8 @@ def get_loader(test_paths, product, debug=None, run_info_extras=None, chunker_kw
manifest_filters = []
include = kwargs["include"]
if test_groups:
include = testloader.update_include_for_groups(test_groups, include)
if include or kwargs["exclude"] or kwargs["include_manifest"] or kwargs["default_exclude"]:
manifest_filters.append(testloader.TestFilter(include=include,
if kwargs["include"] or kwargs["exclude"] or kwargs["include_manifest"] or kwargs["default_exclude"]:
manifest_filters.append(testloader.TestFilter(include=kwargs["include"],
exclude=kwargs["exclude"],
manifest_path=kwargs["include_manifest"],
test_manifests=test_manifests,
@ -171,21 +166,23 @@ def run_tests(config, test_paths, product, **kwargs):
recording.set(["startup", "load_tests"])
test_groups = (testloader.TestGroupsFile(logger, kwargs["test_groups_file"])
if kwargs["test_groups_file"] else None)
test_source_kwargs = {"processes": kwargs["processes"]}
chunker_kwargs = {}
if kwargs["run_by_dir"] is False:
test_source_cls = testloader.SingleTestSource
else:
# A value of None indicates infinite depth
test_source_cls = testloader.PathGroupedSource
test_source_kwargs["depth"] = kwargs["run_by_dir"]
chunker_kwargs["depth"] = kwargs["run_by_dir"]
(test_source_cls,
test_source_kwargs,
chunker_kwargs) = testloader.get_test_src(logger=logger,
test_groups=test_groups,
**kwargs)
run_info, test_loader = get_loader(test_paths,
product.name,
run_info_extras=product.run_info_extras(**kwargs),
chunker_kwargs=chunker_kwargs,
test_groups=test_groups,
**kwargs)
logger.info("Using %i client processes" % kwargs["processes"])
skipped_tests = 0
@ -206,9 +203,7 @@ def run_tests(config, test_paths, product, **kwargs):
"host_cert_path": kwargs["host_cert_path"],
"ca_cert_path": kwargs["ca_cert_path"]}}
testharness_timeout_multipler = product.get_timeout_multiplier("testharness",
run_info,
**kwargs)
testharness_timeout_multipler = product.get_timeout_multiplier("testharness", run_info, **kwargs)
recording.set(["startup", "start_environment"])
with env.TestEnvironment(test_paths,
@ -246,13 +241,7 @@ def run_tests(config, test_paths, product, **kwargs):
for test_type in test_loader.test_types:
tests.extend(test_loader.tests[test_type])
try:
test_groups = test_source_cls.tests_by_group(tests, **test_source_kwargs)
except Exception:
logger.critical("Loading tests failed")
return False
logger.suite_start(test_groups,
logger.suite_start(test_source_cls.tests_by_group(tests, **test_source_kwargs),
name='web-platform-test',
run_info=run_info,
extra={"run_by_dir": kwargs["run_by_dir"]})