Cthulhu is no longer a fork. Now it is a screen reader written in Golang.
This commit is contained in:
1 parent
a998fe67de
commit
069fc674dc
708 files changed
+112482
-532
No files matched your search
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Firefox AT-SPI baseline on a private X server, bus, and browser profile."""
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
PAGE = Path(__file__).with_name("firefox-baseline.html")
|
||||
|
||||
|
||||
def run_inside():
|
||||
linked = os.environ.get("CTHULHU_FIREFOX_LINKED") == "1"
|
||||
page = Path(__file__).with_name("browser-linked-headings.html") if linked else PAGE
|
||||
browser = os.environ.get("CTHULHU_FIREFOX") or shutil.which("firefox")
|
||||
if not browser:
|
||||
raise RuntimeError("Firefox executable not found")
|
||||
with tempfile.TemporaryDirectory(prefix="cthulhu-firefox-profile-") as profile:
|
||||
Path(profile, "user.js").write_text(
|
||||
'user_pref("datareporting.policy.firstRunURL", "");\n'
|
||||
'user_pref("browser.startup.homepage_override.mstone", "ignore");\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
with tempfile.TemporaryFile() as log:
|
||||
environment = dict(os.environ, MOZ_ACCESSIBILITY_ENABLED="1")
|
||||
process = subprocess.Popen(
|
||||
[browser, "--no-remote", "--profile", profile, "--new-window", page.resolve().as_uri()],
|
||||
env=environment, stdout=log, stderr=log,
|
||||
)
|
||||
try:
|
||||
deadline = time.monotonic() + 25
|
||||
while time.monotonic() < deadline:
|
||||
if process.poll() is not None:
|
||||
log.seek(0)
|
||||
raise RuntimeError("Firefox exited before the probe: " + log.read().decode(errors="replace"))
|
||||
result = subprocess.run(
|
||||
["xdotool", "search", "--onlyvisible", "--name", "Cthulhu Linked Headings Probe" if linked else "Cthulhu Firefox Baseline"],
|
||||
capture_output=True, text=True,
|
||||
)
|
||||
if result.stdout.strip():
|
||||
window = result.stdout.splitlines()[0]
|
||||
subprocess.run(["xdotool", "windowfocus", window], check=True)
|
||||
break
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
raise RuntimeError("Firefox fixture window missing")
|
||||
environment["CTHULHU_NATIVE_FIREFOX"] = "1"
|
||||
environment.setdefault("GOCACHE", "/tmp/cthulhu-cache")
|
||||
if linked:
|
||||
environment["CTHULHU_NATIVE_LINKED_HEADINGS"] = "1"
|
||||
subprocess.run(
|
||||
["go", "test", "./internal/app", "-run", "^TestNativeLinkedHeadings$",
|
||||
"-count=1", "-v", "-timeout=45s"],
|
||||
cwd=ROOT, env=environment, check=True, timeout=50,
|
||||
)
|
||||
return
|
||||
subprocess.run(
|
||||
["go", "test", "./internal/atspi", "-run", "^TestNativeFirefoxBaseline$",
|
||||
"-count=1", "-v", "-timeout=45s"],
|
||||
cwd=ROOT, env=environment, check=True, timeout=55,
|
||||
)
|
||||
subprocess.run(
|
||||
["go", "test", "./internal/app", "-run", "^TestNativeBrowserTabs$",
|
||||
"-count=1", "-v", "-timeout=30s"],
|
||||
cwd=ROOT, env=environment, check=True, timeout=35,
|
||||
)
|
||||
finally:
|
||||
process.terminate()
|
||||
try:
|
||||
process.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
process.kill()
|
||||
process.wait(timeout=5)
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) == 2 and sys.argv[1] == "--inside":
|
||||
run_inside()
|
||||
return
|
||||
read_fd, write_fd = os.pipe()
|
||||
server = subprocess.Popen(
|
||||
["Xvfb", "-displayfd", str(write_fd), "-screen", "0", "800x600x24", "-nolisten", "tcp"],
|
||||
pass_fds=(write_fd,), stderr=subprocess.DEVNULL,
|
||||
)
|
||||
os.close(write_fd)
|
||||
try:
|
||||
with os.fdopen(read_fd) as reader:
|
||||
display = reader.readline().strip()
|
||||
if not display:
|
||||
raise RuntimeError("Xvfb failed to start")
|
||||
environment = dict(os.environ, DISPLAY=":" + display, XDG_SESSION_TYPE="x11")
|
||||
environment.pop("DBUS_SESSION_BUS_ADDRESS", None)
|
||||
environment.pop("AT_SPI_BUS_ADDRESS", None)
|
||||
environment.pop("WAYLAND_DISPLAY", None)
|
||||
subprocess.run(
|
||||
["dbus-run-session", "--", sys.executable, str(Path(__file__).resolve()), "--inside"],
|
||||
env=environment, check=True, timeout=90,
|
||||
)
|
||||
finally:
|
||||
server.terminate()
|
||||
server.wait(timeout=3)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in new issue
Block a user