Files
cthulhu/tests/native_i3.py

68 lines
3.0 KiB
Python

#!/usr/bin/env python3
"""Exercise actual i3 IPC on a private Xvfb display; never touch the live WM."""
import os
from pathlib import Path
import subprocess
import sys
import tempfile
sys.dont_write_bytecode = True
from native_test_session import run_private_session
from native_x11 import wait_for
ROOT = Path(__file__).resolve().parents[1]
def inside():
env = dict(os.environ, GOCACHE="/tmp/cthulhu-go-cache", GOPROXY="off")
subprocess.run(["go", "test", "./internal/i3ipc", "-run", "^TestNativeI3Unavailable$", "-count=1", "-v"],
cwd=ROOT, env=dict(env, CTHULHU_NATIVE_I3_UNAVAILABLE="1"), check=True, timeout=60)
with tempfile.TemporaryDirectory(prefix="cthulhu-i3-") as directory:
config = Path(directory) / "config"
config.write_text('font pango:monospace 8\nfocus_follows_mouse no\n'
'mode "personal" {\n bindsym Escape mode "default"\n}\n'
'mode "ratpoison" {\n bindsym Escape mode "default"\n}\n'
'mode "panel" {\n bindsym Escape mode "default"\n}\n'
'mode --pango_markup "<b>marked &amp; mode</b>" {\n bindsym Escape mode "default"\n}\n')
with (Path(directory) / "i3.log").open("w+") as log:
wm = subprocess.Popen(["i3", "-c", str(config)], env=env, stdout=log, stderr=log)
try:
def ready():
if wm.poll() is not None:
log.seek(0)
raise RuntimeError(log.read())
result = subprocess.run(["i3", "--get-socketpath"], env=env, capture_output=True, text=True)
return result.returncode == 0 and Path(result.stdout.strip()).is_socket()
wait_for(ready, "private i3 did not start")
subprocess.run(["go", "test", "./internal/i3ipc", "-run", "^TestNativeI3(Events|EmptyWorkspaceFocus)$", "-count=1", "-v", "-timeout=30s"],
cwd=ROOT, env=dict(env, CTHULHU_NATIVE_I3="1"), check=True, timeout=60)
finally:
wm.terminate()
wm.wait(timeout=5)
def main():
if "--inside" in sys.argv:
inside()
return
read_fd, write_fd = os.pipe()
server = subprocess.Popen(["Xvfb", "-displayfd", str(write_fd), "-screen", "0", "1024x768x24", "-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()
assert display, "Xvfb failed"
env = dict(os.environ, DISPLAY=":" + display)
for key in ("DBUS_SESSION_BUS_ADDRESS", "AT_SPI_BUS_ADDRESS", "WAYLAND_DISPLAY", "I3SOCK"):
env.pop(key, None)
run_private_session(["dbus-run-session", "--", sys.executable, str(Path(__file__).resolve()), "--inside"],
env=env, check=True, timeout=150)
finally:
server.terminate()
server.wait(timeout=5)
if __name__ == "__main__":
main()