Minimize D-Bus requirements for tests (#5265)

This PR minimizes the D-Bus requirements for tests. It does this by
using dbus-daemon directly instead of dbus-launch. The latter is meant
for graphical applications and therefor has X11 dependencies. It also
leaves the D-Bus daemon running after the tests are done. This will
accumulate dbus-daemon processes over time which is not ideal.

I've also considered using dbus-run-session since it is meant to launch
processes with a private D-Bus session. For Python tests one could
launch it like so:
dbus-run-session -- python3 -m pytest ...

Then `DBUS_SESSION_BUS_ADDRESS` would be used automatically by the
`MessageBus` class. However, to keep the current behavior of the tests,
launching the D-Bus daemon manually is the better option.
This commit is contained in:
Stefan Agner 2024-08-22 19:04:34 +02:00 committed by GitHub
parent 7366673eea
commit 695a23a454
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 19 additions and 10 deletions

View File

@ -313,7 +313,7 @@ jobs:
- name: Install additional system dependencies - name: Install additional system dependencies
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y --no-install-recommends libpulse0 libudev1 dbus dbus-x11 sudo apt-get install -y --no-install-recommends libpulse0 libudev1 dbus-daemon
- name: Register Python problem matcher - name: Register Python problem matcher
run: | run: |
echo "::add-matcher::.github/workflows/matchers/python.json" echo "::add-matcher::.github/workflows/matchers/python.json"

View File

@ -1,6 +1,7 @@
"""Common test functions.""" """Common test functions."""
import asyncio import asyncio
from collections.abc import AsyncGenerator, Generator
from functools import partial from functools import partial
from inspect import unwrap from inspect import unwrap
import os import os
@ -115,20 +116,28 @@ async def docker() -> DockerAPI:
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def dbus_session() -> None: def dbus_session() -> Generator[str, None, None]:
"""Start a dbus session.""" """Start a dbus session.
dbus_launch = subprocess.run(["dbus-launch"], stdout=subprocess.PIPE, check=False)
envs = dbus_launch.stdout.decode(encoding="utf-8").rstrip()
for env in envs.split("\n"): Returns session address.
name, value = env.split("=", 1) """
os.environ[name] = value with subprocess.Popen(
[
"dbus-daemon",
"--nofork",
"--print-address",
"--session",
],
stdout=subprocess.PIPE,
) as proc:
yield proc.stdout.readline().decode("utf-8").strip()
proc.terminate()
@pytest.fixture @pytest.fixture
async def dbus_session_bus(dbus_session) -> MessageBus: async def dbus_session_bus(dbus_session) -> AsyncGenerator[MessageBus, None, None]:
"""Return message bus connected to session dbus.""" """Return message bus connected to session dbus."""
bus = await MessageBus(bus_type=BusType.SESSION).connect() bus = await MessageBus(bus_type=BusType.SESSION, bus_address=dbus_session).connect()
yield bus yield bus
bus.disconnect() bus.disconnect()