Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .taskcluster.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ tasks:
owner: ${owner}
source: ${event.repository.clone_url}
payload:
image: ghcr.io/web-platform-tests/wpt:2
image: ghcr.io/web-platform-tests/wpt:3
maxRunTime: 7200
artifacts:
public/results:
Expand Down
1 change: 1 addition & 0 deletions lint.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.wbn
TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.avif
TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.annexb
TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.crx
TRAILING WHITESPACE, INDENT TABS, CR AT EOL: *.tlb

## .gitignore
W3C-TEST.ORG: .gitignore
Expand Down
2 changes: 1 addition & 1 deletion tools/ci/tc/tasks/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ components:
workerType: ci
schedulerId: taskcluster-github
deadline: "24 hours"
image: ghcr.io/web-platform-tests/wpt:2
image: ghcr.io/web-platform-tests/wpt:3
maxRunTime: 7200
artifacts:
public/results:
Expand Down
3 changes: 3 additions & 0 deletions tools/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ RUN apt-get -qqy update \
glib-networking-services \
gstreamer1.0-plugins-bad \
gstreamer1.0-gl \
libatspi2.0-dev \
libcairo2-dev \
libgirepository1.0-dev \
libosmesa6-dev \
libproxy1-plugin-webkit \
libvirt-daemon-system \
Expand Down
16 changes: 16 additions & 0 deletions tools/manifest/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,22 @@ def to_json(self) -> Tuple[Optional[Text], Dict[Text, Any]]:
return rv


class AccessibilityAPIMappingTest(URLManifestItem):
__slots__ = ()

item_type = "aamtest"

@property
def timeout(self) -> Optional[Text]:
return self._extras.get("timeout")

def to_json(self) -> Tuple[Optional[Text], Dict[Text, Any]]:
rv = super().to_json()
if self.timeout is not None:
rv[-1]["timeout"] = self.timeout
return rv


class SupportFile(ManifestItem):
__slots__ = ()

Expand Down
4 changes: 3 additions & 1 deletion tools/manifest/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

from . import jsonlib
from . import vcs
from .item import (ConformanceCheckerTest,
from .item import (AccessibilityAPIMappingTest,
ConformanceCheckerTest,
CrashTest,
ManifestItem,
ManualTest,
Expand Down Expand Up @@ -46,6 +47,7 @@ class InvalidCacheError(Exception):
"crashtest": CrashTest,
"manual": ManualTest,
"wdspec": WebDriverSpecTest,
"aamtest": AccessibilityAPIMappingTest,
"conformancechecker": ConformanceCheckerTest,
"visual": VisualTest,
"spec": SpecItem,
Expand Down
31 changes: 27 additions & 4 deletions tools/manifest/sourcefile.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
import html5lib

from . import XMLParser
from .item import (ConformanceCheckerTest,
from .item import (AccessibilityAPIMappingTest,
ConformanceCheckerTest,
CrashTest,
ManifestItem,
ManualTest,
Expand All @@ -33,7 +34,7 @@
# because relative import beyond toplevel throws *ImportError*!
from metadata.webfeatures.schema import WEB_FEATURES_YML_FILENAME # type: ignore

wd_pattern = "*.py"
py_pattern = "*.py"
js_meta_re = re.compile(br"//\s*META:\s*(\w*)=(.*)$")
python_meta_re = re.compile(br"#\s*META:\s*(\w*)=(.*)$")

Expand Down Expand Up @@ -395,7 +396,16 @@ def name_is_webdriver(self) -> bool:
(rel_path_parts[:2] == ("infrastructure", "webdriver") and
len(rel_path_parts) > 2)) and
self.filename not in ("__init__.py", "conftest.py") and
fnmatch(self.filename, wd_pattern))
fnmatch(self.filename, py_pattern))

@property
def name_is_wai_aria_aam(self) -> bool:
"""Check if the file name matches the conditions for the file to
be a WAI-ARIA AAM spec test file"""
rel_path_parts = self.rel_path_parts
return ((rel_path_parts[0] == "wai-aria-aam" and len(rel_path_parts) > 1) and
self.filename not in ("__init__.py", "conftest.py") and
fnmatch(self.filename, py_pattern))

@property
def name_is_reference(self) -> bool:
Expand Down Expand Up @@ -474,7 +484,7 @@ def pac_nodes(self) -> List[ElementTree.Element]:
def script_metadata(self) -> Optional[List[Tuple[Text, Text]]]:
if self.name_is_worker or self.name_is_multi_global or self.name_is_window or self.name_is_extension:
regexp = js_meta_re
elif self.name_is_webdriver:
elif self.name_is_webdriver or self.name_is_wai_aria_aam:
regexp = python_meta_re
else:
return None
Expand Down Expand Up @@ -899,6 +909,9 @@ def possible_types(self) -> Set[Text]:
if self.name_is_webdriver:
return {WebDriverSpecTest.item_type}

if self.name_is_wai_aria_aam:
return {AccessibilityAPIMappingTest.item_type}

if self.name_is_visual:
return {VisualTest.item_type}

Expand Down Expand Up @@ -986,6 +999,16 @@ def manifest_items(self) -> Tuple[Text, List[ManifestItem]]:
timeout=self.timeout
)]

elif self.name_is_wai_aria_aam:
rv = AccessibilityAPIMappingTest.item_type, [
AccessibilityAPIMappingTest(
self.tests_root,
self.rel_path,
self.url_base,
self.rel_url,
timeout=self.timeout
)]

elif self.name_is_visual:
rv = VisualTest.item_type, [
VisualTest(
Expand Down
9 changes: 9 additions & 0 deletions tools/mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ follow_imports = silent
follow_imports = silent

# Ignore missing or untyped libraries.
[mypy-ApplicationServices.*]
ignore_missing_imports = True

[mypy-Cocoa.*]
ignore_missing_imports = True

Expand All @@ -51,9 +54,15 @@ ignore_missing_imports = True
[mypy-Quartz.*]
ignore_missing_imports = True

[mypy-comtypes.*]
ignore_missing_imports = True

[mypy-dnslib.*]
ignore_missing_imports = True

[mypy-gi.*]
ignore_missing_imports = True

[mypy-marionette_driver.*]
ignore_missing_imports = True

Expand Down
4 changes: 4 additions & 0 deletions tools/wpt/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,10 @@ def setup_wptrunner(venv, **kwargs):
if not venv.skip_virtualenv_setup:
requirements = [os.path.join(wpt_root, "tools", "wptrunner", "requirements.txt")]
requirements.extend(setup_cls.requirements())

if "aamtest" in kwargs["test_types"]:
requirements.append(os.path.join(wpt_root, "tools", "wptrunner", "requirements_platform_accessibility.txt"))

venv.install_requirements(*requirements)

affected_revish = kwargs.get("affected")
Expand Down
2 changes: 1 addition & 1 deletion tools/wpt/testfiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ def affected_testfiles(files_changed: Iterable[Text],
nontests_changed = set(files_changed)
wpt_manifest = load_manifest(manifest_path, manifest_update)

test_types = ["crashtest", "print-reftest", "reftest", "testharness", "wdspec"]
test_types = ["crashtest", "print-reftest", "reftest", "testharness", "wdspec", "aamtest"]
support_files = {os.path.join(wpt_root, path)
for _, path, _ in wpt_manifest.itertypes("support")}
wdspec_test_files = {os.path.join(wpt_root, path)
Expand Down
8 changes: 8 additions & 0 deletions tools/wptrunner/requirements_platform_accessibility.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
comtypes==1.4.11; sys_platform == 'win32'
PyGObject==3.50.1; sys_platform == 'linux' and python_version >= '3.9'
PyGObject==3.48.2; sys_platform == 'linux' and python_version < '3.9'
pyobjc-framework-Accessibility==11.1; sys_platform == 'darwin' and python_version >= '3.9'
pyobjc-framework-ApplicationServices==11.1; sys_platform == 'darwin' and python_version >= '3.9'
pyobjc==10.3.2; sys_platform == 'darwin' and python_version < '3.9'
pyobjc-framework-Accessibility==10.3.2; sys_platform == 'darwin' and python_version < '3.9'
pyobjc-framework-ApplicationServices==10.3.2; sys_platform == 'darwin' and python_version < '3.9'
18 changes: 13 additions & 5 deletions tools/wptrunner/wptrunner/browsers/chrome.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# mypy: allow-untyped-defs

import os
import re
import time

Expand Down Expand Up @@ -33,6 +34,7 @@
"reftest": "ChromeDriverRefTestExecutor",
"print-reftest": "ChromeDriverPrintRefTestExecutor",
"wdspec": "WdspecExecutor",
"aamtest": "WdspecExecutor",
"crashtest": "ChromeDriverCrashTestExecutor"},
"browser_kwargs": "browser_kwargs",
"executor_kwargs": "executor_kwargs",
Expand Down Expand Up @@ -222,6 +224,13 @@ def executor_kwargs(logger, test_type, test_environment, run_info_data, subsuite
if test_type == "wdspec":
executor_kwargs["binary_args"] = chrome_options["args"]

if test_type == "aamtest":
# Necessary to force chrome to register in AT-SPI2.
os.environ["ACCESSIBILITY_ENABLED"] = "1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems this will set ACCESSIBILITY_ENABLED=1 in the main wptrunner process permanently. If so, chrome instances for later test types could inadvertently inherit this environment variable, inducing flakiness.

I think it would be better to add {"env": {"ACCESSIBILITY_ENABLED": "1"}} to browser_kwargs for test_type=aamtest:

def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
return {"binary": kwargs["binary"],
"webdriver_binary": kwargs["webdriver_binary"],
"webdriver_args": kwargs.get("webdriver_args"),
"leak_check": kwargs.get("leak_check", False)}

... which will be plumbed to the chrome(driver) process tree here:

Going to/from the aamtest type will always induce a browser restart, which will clear ACCESSIBILITY_ENABLED=1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thanks for catching this and the pointers!

I immediately ran into a problem, though, to get it to work I need to update this line:

self.env = os.environ.copy() if env is None else env

To:

self.env = {**os.environ, **env} if env else os.environ.copy()

It doesn't look like any other product uses the env key in their return from browser_kwargs, so I think this change might be fine to do?

As another possibility, firefox_android.py returns a "env_extras" key:

browser_kwargs["env_extras"] = dict([x.split('=') for x in kwargs.get("env", [])])

Which seems to be used the way I want to use self.env (as additional env variables, not the complete set)... but it is only used within firefox_android.py, and has a really confusing name collision with the "def env_extra()", which seems to be something very different (defined in all products but only used in sauce.py).

Do you have an opinion about either direction? treat "env" as an addition environment variable with the one-line fix above, or return "env_extras" instead and add code to have it handled as additional env variables in either chrome.py... or maybe base.py?

if "--force-renderer-accessibility" not in chrome_options["args"]:
chrome_options["args"].append("--force-renderer-accessibility")
executor_kwargs["binary_args"] = chrome_options["args"]

executor_kwargs["capabilities"] = capabilities

return executor_kwargs
Expand Down Expand Up @@ -256,11 +265,10 @@ def __init__(self,
self._require_webdriver_bidi: Optional[bool] = None

def restart_on_test_type_change(self, new_test_type: str, old_test_type: str) -> bool:
# Restart the test runner when switch from/to wdspec tests. Wdspec test
# is using a different protocol class so a restart is always needed.
if "wdspec" in [old_test_type, new_test_type]:
return True
return False
# Restart the test runner when switch from/to wdspec or aamtest tests.
# These tests use a different protocol class so a restart is always needed.
wdspec_types = {"wdspec", "aamtest"}
return old_test_type in wdspec_types or new_test_type in wdspec_types

def create_output_handler(self, cmd: List[str]) -> OutputHandler:
return ChromeDriverOutputHandler(
Expand Down
1 change: 1 addition & 0 deletions tools/wptrunner/wptrunner/browsers/chromium.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"reftest": "WebDriverRefTestExecutor",
"print-reftest": "ChromeDriverPrintRefTestExecutor",
"wdspec": "WdspecExecutor",
"aamtest": "WdspecExecutor",
"crashtest": "WebDriverCrashtestExecutor"},
"browser_kwargs": "browser_kwargs",
"executor_kwargs": "executor_kwargs",
Expand Down
1 change: 1 addition & 0 deletions tools/wptrunner/wptrunner/browsers/edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"reftest": "EdgeDriverRefTestExecutor",
"print-reftest": "EdgeDriverPrintRefTestExecutor",
"wdspec": "WdspecExecutor",
"aamtest": "WdspecExecutor",
"crashtest": "WebDriverCrashtestExecutor"},
"browser_kwargs": "browser_kwargs",
"executor_kwargs": "executor_kwargs",
Expand Down
25 changes: 19 additions & 6 deletions tools/wptrunner/wptrunner/browsers/firefox.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@
__wptrunner__ = {"product": "firefox",
"check_args": "check_args",
"browser": {None: "FirefoxBrowser",
"wdspec": "FirefoxWdSpecBrowser"},
"wdspec": "FirefoxWdSpecBrowser",
"aamtest": "FirefoxWdSpecBrowser"},
"executor": {"crashtest": "MarionetteCrashtestExecutor",
"testharness": "MarionetteTestharnessExecutor",
"reftest": "MarionetteRefTestExecutor",
"print-reftest": "MarionettePrintRefTestExecutor",
"wdspec": "MarionetteWdspecExecutor"},
"wdspec": "MarionetteWdspecExecutor",
"aamtest": "MarionetteWdspecExecutor",},
"browser_kwargs": "browser_kwargs",
"executor_kwargs": "executor_kwargs",
"env_extras": "env_extras",
Expand All @@ -71,7 +73,7 @@ def get_timeout_multiplier(test_type, run_info_data, **kwargs):
return 4 * multiplier
else:
return 2 * multiplier
elif test_type == "wdspec":
elif test_type in ("wdspec", "aamtest"):
if (run_info_data.get("asan") or
run_info_data.get("ccov") or
run_info_data.get("debug")):
Expand Down Expand Up @@ -126,7 +128,7 @@ def browser_kwargs(logger, test_type, run_info_data, config, subsuite, **kwargs)
"gmp_path": kwargs["gmp_path"] if "gmp_path" in kwargs else None,
"debug_test": kwargs["debug_test"]}

if test_type == "wdspec":
if test_type in ("wdspec", "aamtest"):
browser_kwargs["webdriver_binary"] = kwargs["webdriver_binary"]
browser_kwargs["webdriver_args"] = kwargs["webdriver_args"].copy()

Expand All @@ -145,6 +147,15 @@ def browser_kwargs(logger, test_type, run_info_data, config, subsuite, **kwargs)
browser_kwargs["test_type"] = test_type
browser_kwargs["timeout_multiplier"] = get_timeout_multiplier(test_type, run_info_data, **kwargs)

if test_type == "aamtest":
# Enable accessibility in the browser.
if ('accessibility.force_disabled', '-1') not in browser_kwargs["extra_prefs"]:
browser_kwargs["extra_prefs"].append(('accessibility.force_disabled', '-1'))
# Cache all attributes immediately for testing.
if ('accessibility.enable_all_cache_domains', 'true') not in browser_kwargs["extra_prefs"]:
browser_kwargs["extra_prefs"].append(('accessibility.enable_all_cache_domains', 'true'))


browser_kwargs["extra_prefs"].extend(subsuite.config.get("prefs", []))
return browser_kwargs

Expand Down Expand Up @@ -172,7 +183,8 @@ def executor_kwargs(logger, test_type, test_environment, run_info_data,
else:
cache_screenshots = major_version < 14
executor_kwargs["cache_screenshots"] = cache_screenshots
if test_type == "wdspec":

if test_type in ("wdspec", "aamtest"):
options = {"args": []}
if kwargs["binary"]:
executor_kwargs["webdriver_args"].extend(["--binary", kwargs["binary"]])
Expand Down Expand Up @@ -775,7 +787,7 @@ def _get_default_prefs(self):
if self.test_type == "print-reftest":
prefs["print.always_print_silent"] = True

if self.test_type == "wdspec":
if self.test_type in ("wdspec", "aamtest"):
prefs.update(
{
"remote.prefs.recommended": True,
Expand Down Expand Up @@ -978,6 +990,7 @@ def __init__(self, logger, binary, package_name, prefs_root, webdriver_binary, w

self.env = self.get_env(binary, debug_info, headless, gmp_path, chaos_mode_flags, e10s)

# Todo: need test type to use "aam" test in profile_creator_cls
profile_creator = profile_creator_cls(logger,
prefs_root,
config,
Expand Down
1 change: 1 addition & 0 deletions tools/wptrunner/wptrunner/browsers/servo.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"reftest": "ServoRefTestExecutor",
"crashtest": "ServoCrashtestExecutor",
"wdspec": "WdspecExecutor",
"aamtest": "WdspecExecutor",
},
"browser_kwargs": "browser_kwargs",
"executor_kwargs": "executor_kwargs",
Expand Down
2 changes: 1 addition & 1 deletion tools/wptrunner/wptrunner/executors/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def executor_kwargs(test_type, test_environment, run_info_data, subsuite, **kwar
executor_kwargs["screenshot_cache"] = screenshot_cache
executor_kwargs["reftest_screenshot"] = kwargs["reftest_screenshot"]

if test_type == "wdspec":
if test_type in ("wdspec", "aamtest"):
executor_kwargs["binary"] = kwargs["binary"]
executor_kwargs["binary_args"] = kwargs["binary_args"].copy()
executor_kwargs["webdriver_binary"] = kwargs["webdriver_binary"]
Expand Down
16 changes: 10 additions & 6 deletions tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def run(path, server_config, session_config, timeout=0):

config = session_config.copy()
config["wptserve"] = server_config.as_dict()
config["timeout"] = timeout

with open(config_path, "w") as f:
json.dump(config, f)
Expand Down Expand Up @@ -144,12 +145,15 @@ def record_error(self, report, message):
self.record(report.nodeid, "ERROR", message, report.longrepr)

def record_skip(self, report):
self.record(
report.nodeid,
"ERROR",
"In-test skip decorators are disallowed, "
"please use WPT metadata to ignore tests.",
)
if "PRECONDITION_FAILED" in report.longrepr[2]:
self.record(report.nodeid, "PRECONDITION_FAILED")
else:
self.record(
report.nodeid,
"ERROR",
"In-test skip decorators are disallowed, "
"please use WPT metadata to ignore tests.",
)

def record(self, test, status, message=None, stack=None):
if stack is not None:
Expand Down
Loading