# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/.
java.lang.StringIndexOutOfBoundsException: Range [19, 9) out of bounds for length 9 import json import os import re import textwrap import traceback from collections import defaultdict from enum import Enum from html.parser import HTMLParser from pathlib import Path
import esprima
# 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),
("options", False),
("supportedBrowsers", False),
("supportedPlatforms", False),
("filename", True),
("tags", False),
]
class HTMLScriptParser(HTMLParser): def handle_data(self, data): if self.script_content isNone:
self.script_content = [] if"perfMetadata"in data:
self.script_content.append(data) if any(func_name in data for func_name in XPCSHELL_FUNCS):
self.script_content.append(data)
class ScriptInfo(defaultdict): """Loads and parses a Browsertime test script."""
# If the fields found, don't match our known ones, then an error is raised for field, required in METADATA: ifnot required or self.script_type == ScriptType.alert: continue if field notin self: raise MissingFieldError(path, field)
if self.get("options", {}).get("default", {}).get("manifest_flavor"): # Only mochitest tests have a manifest flavor
self.script_type = ScriptType.mochitest
# looking for the exports statement
found_perfmetadata = False for stmt in self.parsed.body: # detecting if the script has add_task() if (
stmt.type == "ExpressionStatement" and stmt.expression isnotNone and stmt.expression.callee isnotNone and stmt.expression.callee.type == "Identifier" and stmt.expression.callee.name in XPCSHELL_FUNCS
):
self["test"] = "xpcshell"
self.script_type = ScriptType.xpcshell continue
# plain xpcshell tests functions markers if stmt.type == "FunctionDeclaration"and stmt.id.name in XPCSHELL_FUNCS:
self["test"] = "xpcshell"
self.script_type = ScriptType.xpcshell continue
# is this the perfMetdatata plain var ? if stmt.type == "VariableDeclaration": for decl in stmt.declarations: if (
decl.type != "VariableDeclarator" or decl.id.type != "Identifier" or decl.id.name != "perfMetadata" or decl.init isNone
): continue
found_perfmetadata = True
self.scan_properties(decl.init.properties) continue
# or the module.exports map ? if (
stmt.type != "ExpressionStatement" or stmt.expression.left isNone or stmt.expression.left.property isNone or stmt.expression.left.property.name != "exports" or stmt.expression.right isNone or stmt.expression.right.properties isNone
): continue
# now scanning the properties
found_perfmetadata = True
self.scan_properties(stmt.expression.right.properties)
# Pass through all the scripts and gather up the data such as # the test itself, and the perfMetadata. These can be in separate # scripts, but later scripts override earlier ones if there # are redefinitions.
found_perfmetadata = False for script_content in html_parser.script_content:
self.script_content = script_content try:
self._parse_script_content()
found_perfmetadata = True except MissingPerfMetadataError: pass ifnot found_perfmetadata: raise MissingPerfMetadataError()
# Mochitest gets detected as xpcshell during parsing # since they use similar methods to run tests
self.script_type = ScriptType.mochitest
def parse_value(self, value): if value.type == "Identifier": return value.name
if value.type == "Literal": return value.value
if value.type == "TemplateLiteral": # ugly
value = value.quasis[0].value.cooked.replace("\n", " ") return re.sub(r"\s+", " ", value).strip()
if value.type == "ArrayExpression": return [self.parse_value(e) for e in value.elements]
if value.type == "ObjectExpression":
elements = {} for prop in value.properties:
sub_name, sub_value = self.parse_property(prop)
elements[sub_name] = sub_value return elements
def scan_properties(self, properties): for prop in properties:
name, value = self.parse_property(prop)
self[name] = value
def __str__(self): """Used to generate docs."""
def _render(value, level=0): ifnot isinstance(value, (list, tuple, dict)): ifnot isinstance(value, str):
value = str(value) # line wrapping return"\n".join(textwrap.wrap(value, break_on_hyphens=False))
# options if isinstance(value, dict): if level > 0: return",".join([f"{k}:{v}"for k, v in value.items()])
res = [] for key, val in value.items(): if isinstance(val, bool):
res.append(f" --{key.replace('_', '-')}") else:
val = _render(val, level + 1) # noqa
res.append(f" --{key.replace('_', '-')} {val}")
return"\n".join(res)
# simple flat list return", ".join([_render(v, level + 1) for v in value])
options = ""
d = defaultdict(lambda: "N/A") for field, value in self.items(): if field == "longDescription": continue if field == "filename":
d[field] = self.script.name continue if field == "options": for plat in"default", "linux", "mac", "win": if plat notin value: continue
options += f":{plat.capitalize()} options:\n\n::\n\n{_render(value[plat])}\n" else:
d[field] = _render(value)
d["filename_underline"] = "=" * len(d["filename"])
info = _INFO % d if"tags"in self:
info += f":tags: {','.join(self['tags'])}\n"
info += options
info += f"\n**{self['description']}**\n" if"longDescription"in self:
info += f"\n{self['longDescription']}\n"
def update_args(self, **args): """Updates arguments with options from the script.""" from mozperftest.utils import simple_platform
# Order of precedence: # cli options > platform options > default options
options = self.get("options", {})
result = options.get("default", {})
result.update(options.get(simple_platform(), {}))
result.update(args)
# XXX this is going away, see https://bugzilla.mozilla.org/show_bug.cgi?id=1675102 for opt, val in result.items(): if opt.startswith("visualmetrics") or"metrics"notin opt: continue ifnot isinstance(val, list): raise BadOptionTypeError("Metrics should be defined within a list") for metric in val: ifnot isinstance(metric, dict): raise BadOptionTypeError( "Each individual metrics must be defined within a JSON-like object"
)
if self.script_type == ScriptType.xpcshell:
result["flavor"] = "xpcshell" if self.script_type == ScriptType.mochitest:
result["flavor"] = "mochitest" if self.script_type == ScriptType.custom:
result["flavor"] = "custom-script"
return result
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.7Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.