Bug 1644368 - improved scriptinfo r=sparky

Move scriptinfo to where it belongs and clean it

Differential Revision: https://phabricator.services.mozilla.com/D78870
This commit is contained in:
Tarek Ziadé 2020-06-10 22:44:19 +00:00
Родитель 0f65ce3de2
Коммит a677101fc4
6 изменённых файлов: 72 добавлений и 66 удалений

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

@ -94,7 +94,7 @@ def run_tests(mach_cmd, **kwargs):
try_options = json.loads(os.environ["PERFTEST_OPTIONS"])
kwargs.update(try_options)
from mozperftest.utils import build_test_list, install_package
from mozperftest.utils import build_test_list
from mozperftest import MachEnvironment, Metadata
flavor = kwargs["flavor"]
@ -106,13 +106,10 @@ def run_tests(mach_cmd, **kwargs):
mach_cmd.log_manager.add_terminal_logging(level=log_level)
try:
# XXX this doc is specific to browsertime scripts
# maybe we want to move it
if flavor == "doc":
location = os.path.join(
mach_cmd.topsrcdir, "third_party", "python", "esprima"
)
install_package(mach_cmd.virtualenv_manager, location)
from mozperftest.scriptinfo import ScriptInfo
from mozperftest.test.browsertime.script import ScriptInfo
for test in kwargs["tests"]:
print(ScriptInfo(test))

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

@ -10,13 +10,13 @@ import re
import shutil
from pathlib import Path
from mozperftest.scriptinfo import ScriptInfo
from mozperftest.utils import install_package
from mozperftest.test.noderunner import NodeRunner
from mozperftest.test.browsertime.setup import (
system_prerequisites,
append_system_env,
)
from mozperftest.test.browsertime.script import ScriptInfo
BROWSERTIME_SRC_ROOT = Path(__file__).parent
@ -89,7 +89,7 @@ class BrowsertimeRunner(NodeRunner):
self._mach_context = mach_cmd._mach_context
self.virtualenv_manager = mach_cmd.virtualenv_manager
self._created_dirs = []
self._test_info = {}
self._test_script = None
self._setup_helper = None
self.get_binary_path = mach_cmd.get_binary_path
@ -128,8 +128,13 @@ class BrowsertimeRunner(NodeRunner):
super(BrowsertimeRunner, self).setup()
install_url = self.get_arg("install-url")
if self.get_arg("tests"):
self._test_info = ScriptInfo(self.get_arg("tests")[0])
tests = self.get_arg("tests", [])
if len(tests) != 1:
# we don't support auto-discovery (no test passed) or multiple
# tests here yet.
raise NotImplementedError()
self._test_script = ScriptInfo(tests[0])
# installing Python deps on the fly
for dep in ("Pillow==%s" % PILLOW_VERSION, "pyssim==%s" % PYSSIM_VERSION):
@ -303,7 +308,6 @@ class BrowsertimeRunner(NodeRunner):
def _one_cycle(self, metadata, result_dir):
profile = self.get_arg("profile-directory")
test_script = self.get_arg("tests")[0]
args = [
"--resultDir",
@ -312,7 +316,7 @@ class BrowsertimeRunner(NodeRunner):
profile,
"--iterations",
str(self.get_arg("iterations")),
test_script,
self._test_script["filename"],
]
if self.get_arg("verbose"):
@ -341,10 +345,7 @@ class BrowsertimeRunner(NodeRunner):
raise NodeException(exit_code)
metadata.add_result(
{
"results": str(result_dir),
"name": self._test_info.get("name", ("browsertime",))[0],
}
{"results": str(result_dir), "name": self._test_script["name"]}
)
return metadata

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

@ -3,32 +3,27 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from collections import defaultdict
import re
import os
import textwrap
from pathlib import Path
# This import will fail if esprima is not installed.
# The package is vendored in python/third_party and also available at PyPI
# The mach perftest command will make sure it's installed when --flavor doc
# is being used.
import esprima
METADATA = set(
[
"setUp",
"tearDown",
"test",
"owner",
"author",
"name",
"description",
"longDescription",
"usage",
"supportedBrowsers",
"supportedPlatforms",
"filename",
]
)
# list of metadata, each item is the name and if the field is mandatory
METADATA = [
("setUp", False),
("tearDown", False),
("test", True),
("owner", True),
("author", False),
("name", True),
("description", True),
("longDescription", False),
("usage", False),
("supportedBrowsers", False),
("supportedPlatforms", False),
("filename", True),
]
_INFO = """\
@ -47,18 +42,19 @@ Description:
"""
class MetadataDict(defaultdict):
def __missing__(self, key):
return "N/A"
class MissingFieldError(Exception):
pass
class ScriptInfo(MetadataDict):
def __init__(self, script):
class ScriptInfo(defaultdict):
"""Loads and parses a Browsertime test script."""
def __init__(self, path):
super(ScriptInfo, self).__init__()
filename = os.path.basename(script)
self["filename"] = script, filename
self.script = script
with open(script) as f:
self.script = Path(path)
self["filename"] = str(self.script)
with self.script.open() as f:
self.parsed = esprima.parseScript(f.read())
# looking for the exports statement
@ -66,6 +62,7 @@ class ScriptInfo(MetadataDict):
if (
stmt.type != "ExpressionStatement"
or stmt.expression.left is None
or stmt.expression.left.property is None
or stmt.expression.left.property.name != "exports"
or stmt.expression.right is None
or stmt.expression.right.properties is None
@ -86,21 +83,33 @@ class ScriptInfo(MetadataDict):
value = [e.value for e in prop.value.elements]
else:
raise ValueError(prop.value.type)
# line wrapping
if isinstance(value, str):
repr = "\n".join(textwrap.wrap(value, break_on_hyphens=False))
elif isinstance(value, list):
repr = ", ".join(value)
self[prop.key.name] = value, repr
self[prop.key.name] = value
# If the fields found, don't match our known ones,
# then an error is raised
assert set(list(self.keys())) - METADATA == set()
# If the fields found, don't match our known ones, then an error is raised
for field, required in METADATA:
if not required:
continue
if field not in self:
raise MissingFieldError(field)
def __str__(self):
reprs = dict((k, v[1]) for k, v in self.items())
d = MetadataDict()
d.update(reprs)
d.update({"filename_underline": "-" * len(self["filename"])})
"""Used to generate docs."""
d = {}
for field, value in self.items():
if field == "filename":
d[field] = self.script.name
continue
# line wrapping
if isinstance(value, str):
value = "\n".join(textwrap.wrap(value, break_on_hyphens=False))
elif isinstance(value, list):
value = ", ".join(value)
d[field] = value
d["filename_underline"] = "-" * len(d["filename"])
return _INFO % d
def __missing__(self, key):
return "N/A"

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

@ -6,6 +6,8 @@
var someVar;
someVar = 2;
async function setUp(context) {
context.log.info("setUp example!");
}

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

@ -19,7 +19,7 @@ skip-if = python == 2
[test_profile.py]
[test_proxy.py]
[test_runner.py]
[test_scriptinfo.py]
[test_script.py]
[test_single_json_transformer.py]
[test_logcat_transformer.py]
[test_transformer.py]

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

@ -5,7 +5,7 @@
import mozunit
import pytest
from mozperftest.scriptinfo import ScriptInfo, METADATA
from mozperftest.test.browsertime.script import ScriptInfo, MissingFieldError
from mozperftest.tests.support import EXAMPLE_TEST, HERE
@ -16,13 +16,10 @@ def test_scriptinfo():
display = str(info)
assert "The description of the example test." in display
# Ensure that all known fields are in the script info
assert set(list(info.keys())) - METADATA == set()
def test_scriptinfo_failure():
bad_example = HERE / "data" / "failing-samples" / "perftest_doc_failure_example.js"
with pytest.raises(AssertionError):
with pytest.raises(MissingFieldError):
ScriptInfo(bad_example)