Skip to content
This repository has been archived by the owner on Dec 18, 2018. It is now read-only.

Commit

Permalink
Allow per-product configuration of properties to use in metadata cond…
Browse files Browse the repository at this point in the history
…itionals.

This allows for servo to switch on the render backend, and gecko
on the e10s state, for example
  • Loading branch information
jgraham committed Nov 19, 2015
1 parent 24eddf3 commit 064d8c0
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 35 deletions.
8 changes: 7 additions & 1 deletion wptrunner/browsers/firefox.py
Expand Up @@ -28,7 +28,8 @@
"browser_kwargs": "browser_kwargs",
"executor_kwargs": "executor_kwargs",
"env_options": "env_options",
"run_info_extras": "run_info_extras"}
"run_info_extras": "run_info_extras",
"update_properties": "update_properties"}


def check_args(**kwargs):
Expand Down Expand Up @@ -73,9 +74,14 @@ def env_options():
"certificate_domain": "web-platform.test",
"supports_debugger": True}


def run_info_extras(**kwargs):
return {"e10s": kwargs["gecko_e10s"]}


def update_properties():
return ["debug", "e10s", "os", "version", "processor", "bits"], {"debug", "e10s"}

class FirefoxBrowser(Browser):
used_ports = set()

Expand Down
14 changes: 12 additions & 2 deletions wptrunner/browsers/servo.py
Expand Up @@ -17,7 +17,9 @@
"reftest": "ServoRefTestExecutor"},
"browser_kwargs": "browser_kwargs",
"executor_kwargs": "executor_kwargs",
"env_options": "env_options"}
"env_options": "env_options",
"run_info_extras": "run_info_extras",
"update_properties": "update_properties"}


def check_args(**kwargs):
Expand Down Expand Up @@ -47,8 +49,16 @@ def env_options():
"supports_debugger": True}


def run_info_extras(**kwargs):
return {"backend": kwargs["servo_backend"]}


def update_properties():
return ["debug", "os", "version", "processor", "bits", "backend"], None


def render_arg(render_backend):
return {"cpu": "--cpu"}[render_backend]
return {"cpu": "--cpu", "webrender": "--webrender"}[render_backend]


class ServoBrowser(NullBrowser):
Expand Down
12 changes: 11 additions & 1 deletion wptrunner/browsers/servodriver.py
Expand Up @@ -23,7 +23,9 @@
"reftest": "ServoWebDriverRefTestExecutor"},
"browser_kwargs": "browser_kwargs",
"executor_kwargs": "executor_kwargs",
"env_options": "env_options"}
"env_options": "env_options",
"run_info_extras": "run_info_extras",
"update_properties": "update_properties"}

hosts_text = """127.0.0.1 web-platform.test
127.0.0.1 www.web-platform.test
Expand Down Expand Up @@ -59,6 +61,14 @@ def env_options():
"supports_debugger": True}


def run_info_extras(**kwargs):
return {"backend": kwargs["servo_backend"]}


def update_properties():
return ["debug", "os", "version", "processor", "bits", "backend"], None


def make_hosts_file():
hosts_fd, hosts_path = tempfile.mkstemp()
with os.fdopen(hosts_fd, "w") as f:
Expand Down
46 changes: 32 additions & 14 deletions wptrunner/manifestupdate.py
Expand Up @@ -49,7 +49,8 @@ def data_cls_getter(output_node, visited_node):


class ExpectedManifest(ManifestItem):
def __init__(self, node, test_path=None, url_base=None):
def __init__(self, node, test_path=None, url_base=None, property_order=None,
boolean_properties=None):
"""Object representing all the tests in a particular manifest
:param node: AST Node associated with this object. If this is None,
Expand All @@ -65,6 +66,8 @@ def __init__(self, node, test_path=None, url_base=None):
self.url_base = url_base
assert self.url_base is not None
self.modified = False
self.boolean_properties = boolean_properties
self.property_order = property_order

def append(self, child):
ManifestItem.append(self, child)
Expand Down Expand Up @@ -229,7 +232,10 @@ def coalesce_expected(self):
self.set("expected", status, condition=None)
final_conditionals.append(self._data["expected"][-1])
else:
for conditional_node, status in group_conditionals(self.new_expected):
for conditional_node, status in group_conditionals(
self.new_expected,
property_order=self.root.property_order,
boolean_properties=self.root.boolean_properties):
if status != unconditional_status:
self.set("expected", status, condition=conditional_node.children[0])
final_conditionals.append(self._data["expected"][-1])
Expand Down Expand Up @@ -308,7 +314,7 @@ def is_empty(self):
return True


def group_conditionals(values):
def group_conditionals(values, property_order=None, boolean_properties=None):
"""Given a list of Result objects, return a list of
(conditional_node, status) pairs representing the conditional
expressions that are required to match each status
Expand All @@ -320,6 +326,14 @@ def group_conditionals(values):
for prop_name, prop_value in run_info.iteritems():
by_property[(prop_name, prop_value)].add(status)

if property_order is None:
property_order = ["debug", "os", "version", "processor", "bits"]

if boolean_properties is None:
boolean_properties = set(["debug"])
else:
boolean_properties = set(boolean_properties)

# If we have more than one value, remove any properties that are common
# for all the values
if len(values) > 1:
Expand All @@ -329,10 +343,11 @@ def group_conditionals(values):

properties = set(item[0] for item in by_property.iterkeys())

prop_order = ["debug", "e10s", "os", "version", "processor", "bits"]
if property_order is None:
property_order = ["debug", "os", "version", "processor", "bits"]
include_props = []

for prop in prop_order:
for prop in property_order:
if prop in properties:
include_props.append(prop)

Expand All @@ -343,28 +358,26 @@ def group_conditionals(values):
if prop_set in conditions:
continue

expr = make_expr(prop_set, status)
expr = make_expr(prop_set, status, boolean_properties=boolean_properties)
conditions[prop_set] = (expr, status)

return conditions.values()


def make_expr(prop_set, status):
def make_expr(prop_set, status, boolean_properties=None):
"""Create an AST that returns the value ``status`` given all the
properties in prop_set match."""
root = ConditionalNode()

assert len(prop_set) > 0

no_value_props = set(["debug", "e10s"])

expressions = []
for prop, value in prop_set:
number_types = (int, float, long)
value_cls = (NumberNode
if type(value) in number_types
else StringNode)
if prop not in no_value_props:
if prop not in boolean_properties:
expressions.append(
BinaryExpressionNode(
BinaryOperatorNode("=="),
Expand Down Expand Up @@ -397,7 +410,8 @@ def make_expr(prop_set, status):
return root


def get_manifest(metadata_root, test_path, url_base):
def get_manifest(metadata_root, test_path, url_base, property_order=None,
boolean_properties=None):
"""Get the ExpectedManifest for a particular test path, or None if there is no
metadata stored for that test path.
Expand All @@ -408,13 +422,17 @@ def get_manifest(metadata_root, test_path, url_base):
manifest_path = expected.expected_path(metadata_root, test_path)
try:
with open(manifest_path) as f:
return compile(f, test_path, url_base)
return compile(f, test_path, url_base, property_order=property_order,
boolean_properties=boolean_properties)
except IOError:
return None


def compile(manifest_file, test_path, url_base):
def compile(manifest_file, test_path, url_base, property_order=None,
boolean_properties=None):
return conditional.compile(manifest_file,
data_cls_getter=data_cls_getter,
test_path=test_path,
url_base=url_base)
url_base=url_base,
property_order=property_order,
boolean_properties=boolean_properties)
44 changes: 32 additions & 12 deletions wptrunner/metadata.py
Expand Up @@ -32,7 +32,7 @@ def load_test_manifests(serve_root, test_paths):

def update_expected(test_paths, serve_root, log_file_names,
rev_old=None, rev_new="HEAD", ignore_existing=False,
sync_root=None):
sync_root=None, property_order=None, boolean_properties=None):
"""Update the metadata files for web-platform-tests based on
the results obtained in a previous run"""

Expand All @@ -51,7 +51,9 @@ def update_expected(test_paths, serve_root, log_file_names,

expected_map_by_manifest = update_from_logs(manifests,
*log_file_names,
ignore_existing=ignore_existing)
ignore_existing=ignore_existing,
property_order=property_order,
boolean_properties=boolean_properties)

for test_manifest, expected_map in expected_map_by_manifest.iteritems():
url_base = manifests[test_manifest]["url_base"]
Expand Down Expand Up @@ -127,14 +129,19 @@ def unexpected_changes(manifests, change_data, files_changed):


def update_from_logs(manifests, *log_filenames, **kwargs):
ignore_existing = kwargs.pop("ignore_existing", False)
ignore_existing = kwargs.get("ignore_existing", False)
property_order = kwargs.get("property_order")
boolean_properties = kwargs.get("boolean_properties")

expected_map = {}
id_test_map = {}

for test_manifest, paths in manifests.iteritems():
expected_map_manifest, id_path_map_manifest = create_test_tree(paths["metadata_path"],
test_manifest)
expected_map_manifest, id_path_map_manifest = create_test_tree(
paths["metadata_path"],
test_manifest,
property_order=property_order,
boolean_properties=boolean_properties)
expected_map[test_manifest] = expected_map_manifest
id_test_map.update(id_path_map_manifest)

Expand Down Expand Up @@ -284,15 +291,22 @@ def test_end(self, data):
del self.test_cache[test_id]


def create_test_tree(metadata_path, test_manifest):
def create_test_tree(metadata_path, test_manifest, property_order=None,
boolean_properties=None):
expected_map = {}
id_test_map = {}
exclude_types = frozenset(["stub", "helper", "manual"])
include_types = set(manifest.item_types) - exclude_types
for test_path, tests in test_manifest.itertypes(*include_types):
expected_data = load_expected(test_manifest, metadata_path, test_path, tests)
expected_data = load_expected(test_manifest, metadata_path, test_path, tests,
property_order=property_order,
boolean_properties=boolean_properties)
if expected_data is None:
expected_data = create_expected(test_manifest, test_path, tests)
expected_data = create_expected(test_manifest,
test_path,
tests,
property_order=property_order,
boolean_properties=boolean_properties)

for test in tests:
id_test_map[test.id] = (test_manifest, test)
Expand All @@ -301,17 +315,23 @@ def create_test_tree(metadata_path, test_manifest):
return expected_map, id_test_map


def create_expected(test_manifest, test_path, tests):
expected = manifestupdate.ExpectedManifest(None, test_path, test_manifest.url_base)
def create_expected(test_manifest, test_path, tests, property_order=None,
boolean_properties=None):
expected = manifestupdate.ExpectedManifest(None, test_path, test_manifest.url_base,
property_order=property_order,
boolean_properties=boolean_properties)
for test in tests:
expected.append(manifestupdate.TestNode.create(test.item_type, test.id))
return expected


def load_expected(test_manifest, metadata_path, test_path, tests):
def load_expected(test_manifest, metadata_path, test_path, tests, property_order=None,
boolean_properties=None):
expected_manifest = manifestupdate.get_manifest(metadata_path,
test_path,
test_manifest.url_base)
test_manifest.url_base,
property_order=property_order,
boolean_properties=boolean_properties)
if expected_manifest is None:
return

Expand Down
10 changes: 10 additions & 0 deletions wptrunner/products.py
Expand Up @@ -55,3 +55,13 @@ def load_product(config, product):
browser_cls, browser_kwargs,
executor_classes, executor_kwargs,
env_options, run_info_extras)


def load_product_update(config, product):
module = product_module(config, product)
data = module.__wptrunner__

update_properties = (getattr(module, data["update_properties"])()
if "update_properties" in data else (None, None))

return update_properties
20 changes: 17 additions & 3 deletions wptrunner/update/metadata.py
Expand Up @@ -4,10 +4,21 @@

import os

from .. import metadata
from .. import metadata, products

from base import Step, StepRunner

class GetUpdatePropertyList(Step):
provides = ["property_order", "boolean_properties"]


def create(self, state):
property_order, boolean_properties = products.load_product_update(
state.config, state.product)
state.property_order = property_order
state.boolean_properties = boolean_properties


class UpdateExpected(Step):
"""Do the metadata update on the local checkout"""

Expand All @@ -24,7 +35,9 @@ def create(self, state):
state.run_log,
rev_old=None,
ignore_existing=state.ignore_existing,
sync_root=sync_root)
sync_root=sync_root,
property_order=state.property_order,
boolean_properties=state.boolean_properties)


class CreateMetadataPatch(Step):
Expand Down Expand Up @@ -57,5 +70,6 @@ def create(self, state):

class MetadataUpdateRunner(StepRunner):
"""(Sub)Runner for updating metadata"""
steps = [UpdateExpected,
steps = [GetUpdatePropertyList,
UpdateExpected,
CreateMetadataPatch]
2 changes: 2 additions & 0 deletions wptrunner/update/update.py
Expand Up @@ -91,6 +91,8 @@ def create(self, state):
state.ignore_existing = kwargs["ignore_existing"]
state.no_patch = kwargs["no_patch"]
state.suite_name = kwargs["suite_name"]
state.product = kwargs["product"]
state.config = kwargs["config"]
runner = MetadataUpdateRunner(self.logger, state)
runner.run()

Expand Down

0 comments on commit 064d8c0

Please sign in to comment.