Bug 1663417 - make scriptinfo compatible with xpcshell tests r=sparky

Differential Revision: https://phabricator.services.mozilla.com/D89372
This commit is contained in:
Tarek Ziadé 2020-09-10 23:15:09 +00:00
parent 0bf97a3ebc
commit 9c8bb6e963
10 changed files with 143 additions and 23 deletions

View File

@ -1,5 +1,12 @@
"use strict";
var perfMetadata = {
owner: "Network Team",
name: "http3 raw",
description:
"XPCShell tests that verifies the lib integration against a local server",
};
var performance = performance || {};
performance.now = (function() {
return (

View File

@ -133,7 +133,7 @@ def run_tests(mach_cmd, **kwargs):
# XXX this doc is specific to browsertime scripts
# maybe we want to move it
if flavor == "doc":
from mozperftest.test.browsertime.script import ScriptInfo
from mozperftest.script import ScriptInfo
for test in kwargs["tests"]:
print(ScriptInfo(test))

View File

@ -5,6 +5,7 @@ from collections import defaultdict
import re
import textwrap
from pathlib import Path
from enum import Enum
import esprima
@ -42,10 +43,18 @@ Description:
"""
XPCSHELL_FUNCS = "add_task", "run_test", "run_next_test"
class MissingFieldError(Exception):
pass
class ScriptType(Enum):
XPCSHELL = 1
BROWSERTIME = 2
class ScriptInfo(defaultdict):
"""Loads and parses a Browsertime test script."""
@ -53,12 +62,45 @@ class ScriptInfo(defaultdict):
super(ScriptInfo, self).__init__()
self.script = Path(path)
self["filename"] = str(self.script)
self.script_type = ScriptType.BROWSERTIME
with self.script.open() as f:
self.parsed = esprima.parseScript(f.read())
# looking for the exports statement
for stmt in self.parsed.body:
# detecting if the script has add_task()
if (
stmt.type == "ExpressionStatement"
and stmt.expression is not None
and stmt.expression.callee is not None
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 is None
):
continue
self.scan_properties(decl.init.properties)
continue
# or the module.exports map ?
if (
stmt.type != "ExpressionStatement"
or stmt.expression.left is None
@ -70,21 +112,7 @@ class ScriptInfo(defaultdict):
continue
# now scanning the properties
for prop in stmt.expression.right.properties:
if prop.value.type == "Identifier":
value = prop.value.name
elif prop.value.type == "Literal":
value = prop.value.value
elif prop.value.type == "TemplateLiteral":
# ugly
value = prop.value.quasis[0].value.cooked.replace("\n", " ")
value = re.sub(r"\s+", " ", value).strip()
elif prop.value.type == "ArrayExpression":
value = [e.value for e in prop.value.elements]
else:
raise ValueError(prop.value.type)
self[prop.key.name] = value
self.scan_properties(stmt.expression.right.properties)
# If the fields found, don't match our known ones, then an error is raised
for field, required in METADATA:
@ -93,6 +121,23 @@ class ScriptInfo(defaultdict):
if field not in self:
raise MissingFieldError(field)
def scan_properties(self, properties):
for prop in properties:
if prop.value.type == "Identifier":
value = prop.value.name
elif prop.value.type == "Literal":
value = prop.value.value
elif prop.value.type == "TemplateLiteral":
# ugly
value = prop.value.quasis[0].value.cooked.replace("\n", " ")
value = re.sub(r"\s+", " ", value).strip()
elif prop.value.type == "ArrayExpression":
value = [e.value for e in prop.value.elements]
else:
raise ValueError(prop.value.type)
self[prop.key.name] = value
def __str__(self):
"""Used to generate docs."""
d = defaultdict(lambda: "N/A")

View File

@ -12,7 +12,7 @@ from pathlib import Path
from mozperftest.utils import install_package
from mozperftest.test.noderunner import NodeRunner
from mozperftest.test.browsertime.script import ScriptInfo
from mozperftest.script import ScriptInfo
BROWSERTIME_SRC_ROOT = Path(__file__).parent

View File

@ -14,3 +14,18 @@ add_task(async function dummy_test() {
info("perfMetrics", {"metrics3": 3});
await true;
});
var perfMetadata = {
owner: "Performance Testing Team",
name: "Example",
description: "The description of the example test.",
longDescription: `
This is a longer description of the test perhaps including information
about how it should be run locally or links to relevant information.
`,
usage: "explains how to use it",
supportedBrowsers: ["Firefox"],
supportedPlatforms: ["Desktop"],
};

View File

@ -0,0 +1,29 @@
/* 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/. */
"use strict";
var perfMetadata = {
owner: "Performance Testing Team",
name: "Example",
description: "The description of the example test.",
longDescription: `
This is a longer description of the test perhaps including information
about how it should be run locally or links to relevant information.
`,
usage: `
./mach perftest
python/mozperftest/mozperftest/tests/data/samples/test_xpcshell_flavor2.js
`,
supportedBrowsers: ["Firefox"],
supportedPlatforms: ["Desktop"],
};
function run_next_test() {
// do something
}
function run_test() {
// do something
}

View File

@ -14,6 +14,7 @@ HERE = Path(__file__).parent
EXAMPLE_TESTS_DIR = os.path.join(HERE, "data", "samples")
EXAMPLE_TEST = os.path.join(EXAMPLE_TESTS_DIR, "perftest_example.js")
EXAMPLE_XPCSHELL_TEST = Path(EXAMPLE_TESTS_DIR, "test_xpcshell.js")
EXAMPLE_XPCSHELL_TEST2 = Path(EXAMPLE_TESTS_DIR, "test_xpcshell_flavor2.js")
BT_DATA = Path(HERE, "data", "browsertime-results", "browsertime.json")
BT_DATA_VIDEO = Path(HERE, "data", "browsertime-results-video", "browsertime.json")
DMG = Path(HERE, "data", "firefox.dmg")

View File

@ -5,16 +5,32 @@
import mozunit
import pytest
from mozperftest.test.browsertime.script import ScriptInfo, MissingFieldError
from mozperftest.tests.support import EXAMPLE_TEST, HERE
from mozperftest.script import ScriptInfo, MissingFieldError, ScriptType
from mozperftest.tests.support import (
EXAMPLE_TEST,
HERE,
EXAMPLE_XPCSHELL_TEST,
EXAMPLE_XPCSHELL_TEST2,
)
def test_scriptinfo():
def test_scriptinfo_bt():
info = ScriptInfo(EXAMPLE_TEST)
assert info["author"] == "N/A"
display = str(info)
assert "The description of the example test." in display
assert info.script_type == ScriptType.BROWSERTIME
@pytest.mark.parametrize("script", [EXAMPLE_XPCSHELL_TEST, EXAMPLE_XPCSHELL_TEST2])
def test_scriptinfo_xpcshell(script):
info = ScriptInfo(script)
assert info["author"] == "N/A"
display = str(info)
assert "The description of the example test." in display
assert info.script_type == ScriptType.XPCSHELL
def test_scriptinfo_failure():

View File

@ -9,8 +9,15 @@ from setuptools import setup
PACKAGE_NAME = "mozperftest"
PACKAGE_VERSION = "0.2"
deps = ["regex", "jsonschema", "mozlog >= 6.0", "mozdevice >= 4.0.0", "mozproxy",
"mozinfo", "mozfile"]
deps = [
"regex",
"jsonschema",
"mozlog >= 6.0",
"mozdevice >= 4.0.0",
"mozproxy",
"mozinfo",
"mozfile",
]
setup(
name=PACKAGE_NAME,

View File

@ -10,7 +10,7 @@ import re
from perfdocs.utils import read_yaml
from manifestparser import TestManifest
from mozperftest.test.browsertime.script import ScriptInfo
from mozperftest.script import ScriptInfo
"""
This file is for framework specific gatherers since manifests