Merge origin/testing into hunter

This commit is contained in:
hjozwiak committed 2026-11-03 10:35:41 -05:00
commit a4d427099e
19 files changed
+424 -35

No files matched your search

+18 -2
View File
@@ -3,10 +3,12 @@
# Authors: Storm Dragon, Angus Kola
# SPDX-License-Identifier: GPL-3.0-or-later
"""Launch native tests with disposable runtime sockets and private D-Bus."""
import errno
import os
import subprocess
import sys
import tempfile
import time
def run_private_session(command, *, env, **kwargs):
@@ -20,12 +22,26 @@ def run_private_session(command, *, env, **kwargs):
# Keep this path short: AT-SPI falls back from named sockets if its
# generated socket path is 100 bytes or longer.
with tempfile.TemporaryDirectory(prefix="cth-run-", dir="/tmp") as runtimeDir:
sessionEnv = dict(env, XDG_RUNTIME_DIR=runtimeDir)
runtime = tempfile.TemporaryDirectory(prefix="cth-run-", dir="/tmp")
try:
sessionEnv = dict(env, XDG_RUNTIME_DIR=runtime.name)
for name in ("DBUS_SESSION_BUS_ADDRESS", "DBUS_STARTER_ADDRESS", "DBUS_STARTER_BUS_TYPE",
"AT_SPI_BUS_ADDRESS", "WAYLAND_DISPLAY"):
sessionEnv.pop(name, None)
return subprocess.run(command, env=sessionEnv, **kwargs)
finally:
# Activated document portals tear down their FUSE mount after D-Bus
# exits. Wait for that teardown instead of hiding a test's result with
# a transient disconnected-mount error, or ignoring cleanup failures.
deadline = time.monotonic() + 5
while True:
try:
runtime.cleanup()
break
except OSError as error:
if error.errno not in (errno.ENOTCONN, errno.EBUSY) or time.monotonic() >= deadline:
raise
time.sleep(0.05)
def main():
+55
View File
@@ -4,6 +4,7 @@
# SPDX-License-Identifier: GPL-3.0-or-later
"""Runtime isolation and real AT-SPI socket collision regressions."""
import ast
import errno
import json
import os
from pathlib import Path
@@ -55,6 +56,60 @@ print(json.dumps(dict(runtime=str(runtime), mode=stat.S_IMODE(runtime.stat().st_
self.assertEqual(caught.exception.returncode, 7)
self.assertFalse(Path(caught.exception.stdout.strip()).exists())
def test_portal_teardown_retry_preserves_child_failure(self):
originalCleanup = tempfile.TemporaryDirectory.cleanup
attempts = []
def cleanup(runtime):
attempts.append(runtime.name)
if len(attempts) <= 2:
errorCode = (errno.ENOTCONN, errno.EBUSY)[len(attempts) - 1]
raise OSError(errorCode, "Document portal is shutting down")
originalCleanup(runtime)
with patch("native_test_session.tempfile.TemporaryDirectory.cleanup", cleanup), \
patch("native_test_session.time.sleep") as pause:
with self.assertRaises(subprocess.CalledProcessError) as caught:
run_private_session(
["dbus-run-session", "--", sys.executable, "-c", "raise SystemExit(7)"],
env=os.environ, capture_output=True, check=True, timeout=15)
self.assertEqual(caught.exception.returncode, 7)
self.assertEqual(len(attempts), 3)
self.assertEqual(pause.call_count, 2)
self.assertFalse(Path(attempts[0]).exists())
def test_cleanup_does_not_hide_unrelated_errors(self):
originalCleanup = tempfile.TemporaryDirectory.cleanup
def cleanup(runtime):
originalCleanup(runtime)
raise PermissionError(errno.EACCES, "Cleanup denied")
with patch("native_test_session.tempfile.TemporaryDirectory.cleanup", cleanup), \
patch("native_test_session.time.sleep") as pause:
with self.assertRaises(PermissionError):
run_private_session(
["dbus-run-session", "--", sys.executable, "-c", "pass"],
env=os.environ, capture_output=True, check=True, timeout=15)
pause.assert_not_called()
def test_portal_teardown_wait_is_bounded(self):
originalCleanup = tempfile.TemporaryDirectory.cleanup
def cleanup(runtime):
originalCleanup(runtime)
raise OSError(errno.ENOTCONN, "Document portal did not unmount")
with patch("native_test_session.tempfile.TemporaryDirectory.cleanup", cleanup), \
patch("native_test_session.time.monotonic", side_effect=[0, 6]), \
patch("native_test_session.time.sleep") as pause:
with self.assertRaises(OSError) as caught:
run_private_session(
["dbus-run-session", "--", sys.executable, "-c", "pass"],
env=os.environ, capture_output=True, check=True, timeout=15)
self.assertEqual(caught.exception.errno, errno.ENOTCONN)
pause.assert_not_called()
def test_rejects_dbus_before_xvfb_without_launching(self):
with patch("native_test_session.subprocess.run") as launch:
with self.assertRaisesRegex(ValueError, "Start Xvfb before D-Bus"):