2016-09-13 13:20:20 +00:00
|
|
|
import argparse
|
|
|
|
import imp
|
|
|
|
import os
|
|
|
|
import sys
|
2017-01-28 08:49:11 +00:00
|
|
|
from collections import defaultdict
|
2016-09-13 13:20:20 +00:00
|
|
|
|
|
|
|
from mozlog.structured import commandline
|
|
|
|
from wptrunner.wptcommandline import get_test_paths, set_from_config
|
2017-01-28 08:49:11 +00:00
|
|
|
|
|
|
|
manifest = None
|
|
|
|
|
|
|
|
def do_delayed_imports(wpt_dir):
|
|
|
|
global manifest
|
|
|
|
sys.path.insert(0, os.path.join(wpt_dir, "tools", "manifest"))
|
|
|
|
import manifest
|
2016-09-13 13:20:20 +00:00
|
|
|
|
|
|
|
def create_parser():
|
|
|
|
p = argparse.ArgumentParser()
|
|
|
|
p.add_argument("--check-clean", action="store_true",
|
|
|
|
help="Check that updating the manifest doesn't lead to any changes")
|
|
|
|
commandline.add_logging_group(p)
|
|
|
|
|
|
|
|
return p
|
|
|
|
|
|
|
|
|
|
|
|
def update(logger, wpt_dir, check_clean=True):
|
|
|
|
localpaths = imp.load_source("localpaths",
|
|
|
|
os.path.join(wpt_dir, "tests", "tools", "localpaths.py"))
|
|
|
|
kwargs = {"config": os.path.join(wpt_dir, "wptrunner.ini"),
|
|
|
|
"tests_root": None,
|
|
|
|
"metadata_root": None}
|
|
|
|
|
|
|
|
set_from_config(kwargs)
|
|
|
|
config = kwargs["config"]
|
|
|
|
test_paths = get_test_paths(config)
|
|
|
|
|
2017-01-28 08:49:11 +00:00
|
|
|
do_delayed_imports(wpt_dir)
|
|
|
|
|
2016-09-13 13:20:20 +00:00
|
|
|
if check_clean:
|
2017-01-28 08:49:11 +00:00
|
|
|
return _check_clean(logger, test_paths)
|
|
|
|
|
|
|
|
return _update(logger, test_paths)
|
|
|
|
|
|
|
|
|
|
|
|
def _update(logger, test_paths):
|
|
|
|
for url_base, paths in test_paths.iteritems():
|
|
|
|
manifest_path = os.path.join(paths["metadata_path"], "MANIFEST.json")
|
|
|
|
m = manifest.manifest.load(paths["tests_path"], manifest_path)
|
|
|
|
manifest.update.update(paths["tests_path"], m, working_copy=True)
|
|
|
|
manifest.manifest.write(m, manifest_path)
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
def _check_clean(logger, test_paths):
|
|
|
|
manifests_by_path = {}
|
|
|
|
rv = 0
|
|
|
|
for url_base, paths in test_paths.iteritems():
|
|
|
|
tests_path = paths["tests_path"]
|
|
|
|
manifest_path = os.path.join(paths["metadata_path"], "MANIFEST.json")
|
|
|
|
old_manifest = manifest.manifest.load(tests_path, manifest_path)
|
|
|
|
new_manifest = manifest.manifest.Manifest.from_json(tests_path,
|
|
|
|
old_manifest.to_json())
|
|
|
|
manifest.update.update(tests_path, new_manifest, working_copy=True)
|
|
|
|
manifests_by_path[manifest_path] = (old_manifest, new_manifest)
|
|
|
|
|
|
|
|
for manifest_path, (old_manifest, new_manifest) in manifests_by_path.iteritems():
|
|
|
|
if not diff_manifests(logger, manifest_path, old_manifest, new_manifest):
|
|
|
|
rv = 1
|
|
|
|
if rv:
|
|
|
|
logger.error("Manifest %s is outdated, use |mach wpt-manifest-update| to fix." % manifest_path)
|
2016-09-13 13:20:20 +00:00
|
|
|
|
|
|
|
return rv
|
|
|
|
|
2017-01-28 08:49:11 +00:00
|
|
|
|
|
|
|
def diff_manifests(logger, manifest_path, old_manifest, new_manifest):
|
|
|
|
"""Lint the differences between old and new versions of a
|
|
|
|
manifest. Differences are considered significant (and so produce
|
|
|
|
lint errors) if they produce a meaningful difference in the actual
|
|
|
|
tests run.
|
|
|
|
|
|
|
|
:param logger: mozlog logger to use for output
|
|
|
|
:param manifest_path: Path to the manifest being linted
|
|
|
|
:param old_manifest: Manifest object representing the initial manifest
|
|
|
|
:param new_manifest: Manifest object representing the updated manifest
|
|
|
|
"""
|
|
|
|
logger.info("Diffing old and new manifests %s" % manifest_path)
|
|
|
|
old_items, new_items = defaultdict(set), defaultdict(set)
|
|
|
|
for manifest, items in [(old_manifest, old_items),
|
|
|
|
(new_manifest, new_items)]:
|
|
|
|
for test_type, path, tests in manifest:
|
|
|
|
for test in tests:
|
|
|
|
test_id = [test.id]
|
|
|
|
test_id.extend(tuple(item) if isinstance(item, list) else item
|
|
|
|
for item in test.meta_key())
|
|
|
|
if hasattr(test, "references"):
|
|
|
|
test_id.extend(tuple(item) for item in test.references)
|
|
|
|
test_id = tuple(test_id)
|
|
|
|
items[path].add((test_type, test_id))
|
|
|
|
|
|
|
|
old_paths = set(old_items.iterkeys())
|
|
|
|
new_paths = set(new_items.iterkeys())
|
|
|
|
|
|
|
|
added_paths = new_paths - old_paths
|
|
|
|
deleted_paths = old_paths - new_paths
|
|
|
|
|
|
|
|
common_paths = new_paths & old_paths
|
2016-09-13 13:20:20 +00:00
|
|
|
|
|
|
|
clean = True
|
|
|
|
|
2017-01-28 08:49:11 +00:00
|
|
|
for path in added_paths:
|
|
|
|
clean = False
|
|
|
|
log_error(logger, manifest_path, "%s in source but not in manifest." % path)
|
|
|
|
for path in deleted_paths:
|
|
|
|
clean = False
|
|
|
|
log_error(logger, manifest_path, "%s in manifest but removed from source." % path)
|
|
|
|
|
|
|
|
for path in common_paths:
|
|
|
|
old_tests = old_items[path]
|
|
|
|
new_tests = new_items[path]
|
|
|
|
added_tests = new_tests - old_tests
|
|
|
|
removed_tests = old_tests - new_tests
|
|
|
|
if added_tests or removed_tests:
|
2016-09-13 13:20:20 +00:00
|
|
|
clean = False
|
2017-01-28 08:49:11 +00:00
|
|
|
log_error(logger, manifest_path, "%s changed test types or metadata" % path)
|
|
|
|
|
2016-09-13 13:20:20 +00:00
|
|
|
if clean:
|
2017-01-28 08:49:11 +00:00
|
|
|
# Manifest currently has some list vs tuple inconsistencies that break
|
|
|
|
# a simple equality comparison.
|
|
|
|
new_paths = {(key, value[0], value[1])
|
|
|
|
for (key, value) in new_manifest.to_json()["paths"].iteritems()}
|
|
|
|
old_paths = {(key, value[0], value[1])
|
|
|
|
for (key, value) in old_manifest.to_json()["paths"].iteritems()}
|
|
|
|
if old_paths != new_paths:
|
|
|
|
logger.warning("Manifest %s contains correct tests but file hashes changed; please update" % manifest_path)
|
2016-09-13 13:20:20 +00:00
|
|
|
|
|
|
|
return clean
|
|
|
|
|
2017-01-28 08:49:11 +00:00
|
|
|
def log_error(logger, manifest_path, msg):
|
|
|
|
logger.lint_error(path=manifest_path,
|
|
|
|
message=msg,
|
|
|
|
lineno=0,
|
|
|
|
source="",
|
|
|
|
linter="wpt-manifest")
|