Backed out 3 changesets (bug 1536804) for /css/css-* failures CLOSED TREE

Backed out changeset e8758002d7d4 (bug 1536804)
Backed out changeset 795287b1e059 (bug 1536804)
Backed out changeset 9a680e886248 (bug 1536804)
This commit is contained in:
Bogdan Tara 2019-03-26 18:41:16 +02:00
Родитель c2cd4db477
Коммит f81aa92481
7 изменённых файлов: 143 добавлений и 578 удалений

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

@ -25,7 +25,6 @@ jobs-from:
- node.yml
- python.yml
- webidl.yml
- wpt-metadata.yml
- wpt-manifest.yml
# This is used by run-task based tasks to lookup which build task it

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

@ -1,31 +0,0 @@
job-defaults:
platform: lint/opt
treeherder:
kind: test
tier: 2
worker-type: aws-provisioner-v1/gecko-t-linux-xlarge
worker:
docker-image: {in-tree: "lint"}
max-run-time: 1800
summary:
description: Summarize wpt metadata
treeherder:
symbol: wpt-meta
index:
product: source
job-name: source-wpt-metadata-summary
run:
using: mach
mach: wpt-metadata-summary --out-dir=/builds/worker/artifacts
worker:
artifacts:
- type: directory
path: /builds/worker/artifacts
name: public
max-run-time: 2700
when:
files-changed:
- 'testing/web-platform/meta/**'
- 'testing/web-platform/mozilla/meta/**'
- 'testing/web-platform/metasummary.py'

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

@ -345,11 +345,6 @@ def create_parser_manifest_update():
return manifestupdate.create_parser()
def create_parser_metadata_summary():
import metasummary
return metasummary.create_parser()
@CommandProvider
class MachCommands(MachCommandBase):
def setup(self):
@ -437,12 +432,3 @@ class MachCommands(MachCommandBase):
wpt_runner = WebPlatformTestsRunner(wpt_setup)
logger = wpt_runner.setup_logging(**params)
return 0 if wpt_runner.update_manifest(logger, **params) else 1
@Command("wpt-metadata-summary",
category="testing",
description="Create a json summary of the wpt metadata",
parser=create_parser_metadata_summary)
def wpt_summary(self, **params):
import metasummary
wpt_setup = self._spawn(WebPlatformTestsRunnerSetup)
return metasummary.run(wpt_setup.topsrcdir, wpt_setup.topobjdir, **params)

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

@ -1,299 +0,0 @@
import argparse
import json
import logging
import os
import urlparse
from collections import defaultdict
import manifestupdate
from wptrunner import expected
from wptrunner.wptmanifest.serializer import serialize
from wptrunner.wptmanifest.backends import base
here = os.path.dirname(__file__)
logger = logging.getLogger(__name__)
class Compiler(base.Compiler):
def visit_KeyValueNode(self, node):
key_name = node.data
values = []
for child in node.children:
values.append(self.visit(child))
self.output_node.set(key_name, values)
def visit_ConditionalNode(self, node):
assert len(node.children) == 2
# For conditional nodes, just return the subtree
return node.children[0], self.visit(node.children[1])
def visit_UnaryExpressionNode(self, node):
raise NotImplementedError
def visit_BinaryExpressionNode(self, node):
raise NotImplementedError
def visit_UnaryOperatorNode(self, node):
raise NotImplementedError
def visit_BinaryOperatorNode(self, node):
raise NotImplementedError
class ExpectedManifest(base.ManifestItem):
def __init__(self, node, test_path, url_base):
"""Object representing all the tests in a particular manifest
:param name: Name of the AST Node associated with this object.
Should always be None since this should always be associated with
the root node of the AST.
:param test_path: Path of the test file associated with this manifest.
:param url_base: Base url for serving the tests in this manifest
"""
if test_path is None:
raise ValueError("ExpectedManifest requires a test path")
if url_base is None:
raise ValueError("ExpectedManifest requires a base url")
base.ManifestItem.__init__(self, node)
self.child_map = {}
self.test_path = test_path
self.url_base = url_base
def append(self, child):
"""Add a test to the manifest"""
base.ManifestItem.append(self, child)
self.child_map[child.id] = child
@property
def url(self):
return urlparse.urljoin(self.url_base,
"/".join(self.test_path.split(os.path.sep)))
class DirectoryManifest(base.ManifestItem):
pass
class TestManifestItem(base.ManifestItem):
def __init__(self, node, **kwargs):
"""Tree node associated with a particular test in a manifest
:param name: name of the test"""
base.ManifestItem.__init__(self, node)
self.subtests = {}
@property
def id(self):
return urlparse.urljoin(self.parent.url, self.name)
def append(self, node):
"""Add a subtest to the current test
:param node: AST Node associated with the subtest"""
child = base.ManifestItem.append(self, node)
self.subtests[child.name] = child
def get_subtest(self, name):
"""Get the SubtestNode corresponding to a particular subtest, by name
:param name: Name of the node to return"""
if name in self.subtests:
return self.subtests[name]
return None
class SubtestManifestItem(TestManifestItem):
pass
def data_cls_getter(output_node, visited_node):
# visited_node is intentionally unused
if output_node is None:
return ExpectedManifest
if isinstance(output_node, ExpectedManifest):
return TestManifestItem
if isinstance(output_node, TestManifestItem):
return SubtestManifestItem
raise ValueError
def get_manifest(metadata_root, test_path, url_base):
"""Get the ExpectedManifest for a particular test path, or None if there is no
metadata stored for that test path.
:param metadata_root: Absolute path to the root of the metadata directory
:param test_path: Path to the test(s) relative to the test root
:param url_base: Base url for serving the tests in this manifest
:param run_info: Dictionary of properties of the test run for which the expectation
values should be computed.
"""
manifest_path = expected.expected_path(metadata_root, test_path)
try:
with open(manifest_path) as f:
return compile(f,
data_cls_getter=data_cls_getter,
test_path=test_path,
url_base=url_base)
except IOError:
return None
def get_dir_manifest(path):
"""Get the ExpectedManifest for a particular test path, or None if there is no
metadata stored for that test path.
:param path: Full path to the ini file
:param run_info: Dictionary of properties of the test run for which the expectation
values should be computed.
"""
try:
with open(path) as f:
return compile(f, data_cls_getter=lambda x,y: DirectoryManifest)
except IOError:
return None
def compile(stream, data_cls_getter=None, **kwargs):
return base.compile(Compiler,
stream,
data_cls_getter=data_cls_getter,
**kwargs)
def create_parser():
parser = argparse.ArgumentParser()
parser.add_argument("--out-dir", help="Directory to store output files")
return parser
def run(src_root, obj_root, logger_=None, **kwargs):
logger_obj = logger_ if logger_ is not None else logger
manifests = manifestupdate.run(src_root, obj_root, logger_obj, **kwargs)
rv = {}
dirs_seen = set()
for meta_root, test_path, test_metadata in iter_tests(manifests):
for dir_path in get_dir_paths(meta_root, test_path):
if dir_path not in dirs_seen:
dirs_seen.add(dir_path)
dir_manifest = get_dir_manifest(dir_path)
rel_path = os.path.relpath(dir_path, meta_root)
if dir_manifest:
add_manifest(rv, rel_path, dir_manifest)
else:
break
add_manifest(rv, test_path, test_metadata)
if kwargs["out_dir"]:
if not os.path.exists(kwargs["out_dir"]):
os.makedirs(kwargs["out_dir"])
out_path = os.path.join(kwargs["out_dir"], "summary.json")
with open(out_path, "w") as f:
json.dump(rv, f)
else:
print json.dumps(rv, indent=2)
def get_dir_paths(test_root, test_path):
if not os.path.isabs(test_path):
test_path = os.path.join(test_root, test_path)
dir_path = os.path.dirname(test_path)
while dir_path != test_root:
yield os.path.join(dir_path, "__dir__.ini")
dir_path = os.path.dirname(dir_path)
assert len(dir_path) >= len(test_root)
def iter_tests(manifests):
for manifest in manifests.iterkeys():
for test_type, test_path, tests in manifest:
url_base = manifests[manifest]["url_base"]
metadata_base = manifests[manifest]["metadata_path"]
expected_manifest = get_manifest(metadata_base, test_path, url_base)
if expected_manifest:
yield metadata_base, test_path, expected_manifest
def add_manifest(target, path, metadata):
dir_name = os.path.dirname(path)
key = [dir_name]
add_metadata(target, key, metadata)
key.append("_tests")
for test_metadata in metadata.children:
key.append(test_metadata.name)
add_metadata(target, key, test_metadata)
key.append("_subtests")
for subtest_metadata in test_metadata.children:
key.append(subtest_metadata.name)
add_metadata(target,
key,
subtest_metadata)
key.pop()
key.pop()
key.pop()
simple_props = ["disabled", "min-asserts", "max-asserts", "lsan-allowed",
"leak-allowed", "bug"]
statuses = set(["CRASH"])
def add_metadata(target, key, metadata):
if not is_interesting(metadata):
return
for part in key:
if part not in target:
target[part] = {}
target = target[part]
for prop in simple_props:
if metadata.has_key(prop):
target[prop] = get_condition_value_list(metadata, prop)
if metadata.has_key("expected"):
values = metadata.get("expected")
by_status = defaultdict(list)
for item in values:
if isinstance(item, tuple):
condition, status = item
else:
condition = None
status = item
by_status[status].append(condition)
for status in statuses:
if status in by_status:
target["expected_%s" % status] = [serialize(item) if item else None
for item in by_status[status]]
def get_condition_value_list(metadata, key):
conditions = []
for item in metadata.get(key):
if isinstance(item, tuple):
assert len(item) == 2
conditions.append((serialize(item[0]), item[1]))
else:
conditions.append((None, item))
return conditions
def is_interesting(metadata):
if any(metadata.has_key(prop) for prop in simple_props):
return True
if metadata.has_key("expected"):
for item in metadata.get("expected"):
if isinstance(item, tuple):
if item[1] in statuses:
return True
elif item in statuses:
return True
return False

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

@ -2,7 +2,7 @@ import os
import urlparse
from wptmanifest.backends import static
from wptmanifest.backends.base import ManifestItem
from wptmanifest.backends.static import ManifestItem
import expected
@ -98,7 +98,7 @@ def leak_threshold(node):
class ExpectedManifest(ManifestItem):
def __init__(self, node, test_path, url_base):
def __init__(self, name, test_path, url_base):
"""Object representing all the tests in a particular manifest
:param name: Name of the AST Node associated with this object.
@ -107,14 +107,13 @@ class ExpectedManifest(ManifestItem):
:param test_path: Path of the test file associated with this manifest.
:param url_base: Base url for serving the tests in this manifest
"""
name = node.data
if name is not None:
raise ValueError("ExpectedManifest should represent the root node")
if test_path is None:
raise ValueError("ExpectedManifest requires a test path")
if url_base is None:
raise ValueError("ExpectedManifest requires a base url")
ManifestItem.__init__(self, node)
ManifestItem.__init__(self, name)
self.child_map = {}
self.test_path = test_path
self.url_base = url_base
@ -230,14 +229,13 @@ class DirectoryManifest(ManifestItem):
def lsan_max_stack_depth(self):
return int_prop("lsan-max-stack-depth", self)
class TestNode(ManifestItem):
def __init__(self, node, **kwargs):
def __init__(self, name):
"""Tree node associated with a particular test in a manifest
:param name: name of the test"""
assert node.data is not None
ManifestItem.__init__(self, node, **kwargs)
assert name is not None
ManifestItem.__init__(self, name)
self.updated_expected = []
self.new_expected = []
self.subtests = {}
@ -320,6 +318,12 @@ class TestNode(ManifestItem):
class SubtestNode(TestNode):
def __init__(self, name):
"""Tree node associated with a particular subtest in a manifest
:param name: name of the subtest"""
TestNode.__init__(self, name)
@property
def is_empty(self):
if self._data:

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

@ -1,222 +0,0 @@
import abc
from ..node import NodeVisitor
from ..parser import parse
class Compiler(NodeVisitor):
__metaclass__ = abc.ABCMeta
def compile(self, tree, data_cls_getter=None, **kwargs):
self._kwargs = kwargs
return self._compile(tree, data_cls_getter, **kwargs)
def _compile(self, tree, data_cls_getter=None, **kwargs):
"""Compile a raw AST into a form where conditional expressions
are represented by ConditionalValue objects that can be evaluated
at runtime.
tree - The root node of the wptmanifest AST to compile
data_cls_getter - A function taking two parameters; the previous
output node and the current ast node and returning
the class of the output node to use for the current
ast node
"""
if data_cls_getter is None:
self.data_cls_getter = lambda x, y: ManifestItem
else:
self.data_cls_getter = data_cls_getter
self.tree = tree
self.output_node = self._initial_output_node(tree, **kwargs)
self.visit(tree)
if hasattr(self.output_node, "set_defaults"):
self.output_node.set_defaults()
assert self.output_node is not None
return self.output_node
def _initial_output_node(self, node, **kwargs):
return self.data_cls_getter(None, None)(node, **kwargs)
def visit_DataNode(self, node):
if node != self.tree:
output_parent = self.output_node
self.output_node = self.data_cls_getter(self.output_node, node)(node, **self._kwargs)
else:
output_parent = None
assert self.output_node is not None
for child in node.children:
self.visit(child)
if output_parent is not None:
# Append to the parent *after* processing all the node data
output_parent.append(self.output_node)
self.output_node = self.output_node.parent
assert self.output_node is not None
@abc.abstractmethod
def visit_KeyValueNode(self, node):
pass
def visit_ListNode(self, node):
return [self.visit(child) for child in node.children]
def visit_ValueNode(self, node):
return node.data
def visit_AtomNode(self, node):
return node.data
@abc.abstractmethod
def visit_ConditionalNode(self, node):
pass
def visit_StringNode(self, node):
indexes = [self.visit(child) for child in node.children]
def value(x):
rv = node.data
for index in indexes:
rv = rv[index(x)]
return rv
return value
def visit_NumberNode(self, node):
if "." in node.data:
return lambda x: float(node.data)
else:
return lambda x: int(node.data)
def visit_VariableNode(self, node):
indexes = [self.visit(child) for child in node.children]
def value(x):
data = x[node.data]
for index in indexes:
data = data[index(x)]
return data
return value
def visit_IndexNode(self, node):
assert len(node.children) == 1
return self.visit(node.children[0])
@abc.abstractmethod
def visit_UnaryExpressionNode(self, node):
pass
@abc.abstractmethod
def visit_BinaryExpressionNode(self, node):
pass
@abc.abstractmethod
def visit_UnaryOperatorNode(self, node):
pass
@abc.abstractmethod
def visit_BinaryOperatorNode(self, node):
pass
class ManifestItem(object):
def __init__(self, node, **kwargs):
self.parent = None
self.node = node
self.children = []
self._data = {}
def __repr__(self):
return "<ManifestItem %s>" % (self.node.data)
def __str__(self):
rv = [repr(self)]
for item in self.children:
rv.extend(" %s" % line for line in str(item).split("\n"))
return "\n".join(rv)
def set_defaults(self):
pass
@property
def is_empty(self):
if self._data:
return False
return all(child.is_empty for child in self.children)
@property
def root(self):
node = self
while node.parent is not None:
node = node.parent
return node
@property
def name(self):
return self.node.data
def get(self, key):
for node in [self, self.root]:
if key in node._data:
return node._data[key]
raise KeyError
def set(self, name, value):
self._data[name] = value
def remove(self):
if self.parent:
self.parent.children.remove(child)
self.parent = None
def iterchildren(self, name=None):
for item in self.children:
if item.name == name or name is None:
yield item
def has_key(self, key):
for node in [self, self.root]:
if key in node._data:
return True
return False
def _flatten(self):
rv = {}
for node in [self, self.root]:
for name, value in node._data.iteritems():
if name not in rv:
rv[name] = value
return rv
def iteritems(self):
for item in self._flatten().iteritems():
yield item
def iterkeys(self):
for item in self._flatten().iterkeys():
yield item
def itervalues(self):
for item in self._flatten().itervalues():
yield item
def append(self, child):
child.parent = self
self.children.append(child)
return child
def compile_ast(compiler, ast, data_cls_getter=None, **kwargs):
return compiler().compile(ast,
data_cls_getter=data_cls_getter,
**kwargs)
def compile(compiler, stream, data_cls_getter=None, **kwargs):
return compile_ast(compiler,
parse(stream),
data_cls_getter=data_cls_getter,
**kwargs)

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

@ -1,10 +1,10 @@
import operator
import base
from ..node import NodeVisitor
from ..parser import parse
class Compiler(base.Compiler):
class Compiler(NodeVisitor):
"""Compiler backend that evaluates conditional expressions
to give static output"""
@ -26,7 +26,29 @@ class Compiler(base.Compiler):
self._kwargs = kwargs
self.expr_data = expr_data
return self._compile(tree, data_cls_getter, **kwargs)
if data_cls_getter is None:
self.data_cls_getter = lambda x, y: ManifestItem
else:
self.data_cls_getter = data_cls_getter
self.output_node = None
self.visit(tree)
return self.output_node
def visit_DataNode(self, node):
output_parent = self.output_node
if self.output_node is None:
assert node.parent is None
self.output_node = self.data_cls_getter(None, None)(None, **self._kwargs)
else:
self.output_node = self.data_cls_getter(self.output_node, node)(node.data)
for child in node.children:
self.visit(child)
if output_parent is not None:
output_parent.append(self.output_node)
self.output_node = self.output_node.parent
def visit_KeyValueNode(self, node):
key_name = node.data
@ -39,6 +61,15 @@ class Compiler(base.Compiler):
if key_value is not None:
self.output_node.set(key_name, key_value)
def visit_ValueNode(self, node):
return node.data
def visit_AtomNode(self, node):
return node.data
def visit_ListNode(self, node):
return [self.visit(child) for child in node.children]
def visit_ConditionalNode(self, node):
assert len(node.children) == 2
if self.visit(node.children[0]):
@ -50,12 +81,23 @@ class Compiler(base.Compiler):
value = self.visit(child)(value)
return value
def visit_NumberNode(self, node):
if "." in node.data:
return float(node.data)
else:
return int(node.data)
def visit_VariableNode(self, node):
value = self.expr_data[node.data]
for child in node.children:
value = self.visit(child)(value)
return value
def visit_IndexNode(self, node):
assert len(node.children) == 1
index = self.visit(node.children[0])
return lambda x: x[index]
def visit_UnaryExpressionNode(self, node):
assert len(node.children) == 2
operator = self.visit(node.children[0])
@ -81,6 +123,92 @@ class Compiler(base.Compiler):
"!=": operator.ne}[node.data]
class ManifestItem(object):
def __init__(self, name, **kwargs):
self.parent = None
self.name = name
self.children = []
self._data = {}
def __repr__(self):
return "<ManifestItem %s>" % (self.name)
def __str__(self):
rv = [repr(self)]
for item in self.children:
rv.extend(" %s" % line for line in str(item).split("\n"))
return "\n".join(rv)
def set_defaults(self):
pass
@property
def is_empty(self):
if self._data:
return False
return all(child.is_empty for child in self.children)
@property
def root(self):
node = self
while node.parent is not None:
node = node.parent
return node
def has_key(self, key):
for node in [self, self.root]:
if key in node._data:
return True
return False
def get(self, key):
for node in [self, self.root]:
if key in node._data:
return node._data[key]
raise KeyError
def set(self, name, value):
self._data[name] = value
def remove(self):
if self.parent:
self.parent._remove_child(self)
def _remove_child(self, child):
self.children.remove(child)
child.parent = None
def iterchildren(self, name=None):
for item in self.children:
if item.name == name or name is None:
yield item
def _flatten(self):
rv = {}
for node in [self, self.root]:
for name, value in node._data.iteritems():
if name not in rv:
rv[name] = value
return rv
def iteritems(self):
for item in self._flatten().iteritems():
yield item
def iterkeys(self):
for item in self._flatten().iterkeys():
yield item
def itervalues(self):
for item in self._flatten().itervalues():
yield item
def append(self, child):
child.parent = self
self.children.append(child)
return child
def compile_ast(ast, expr_data, data_cls_getter=None, **kwargs):
return Compiler().compile(ast,
expr_data,