flatpak / libportal

libportal - Flatpak portal library
https://libportal.org
GNU Lesser General Public License v3.0
80 stars 39 forks source link

Test suite fails with dbusmock 0.30.0 or leaks multiple dbus-daemon instances with older versions #136

Closed smcv closed 10 months ago

smcv commented 10 months ago

Originally reported in a Debian QA rebuild as https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1058245.

To reproduce

Be in a container (pid namespace) where no unwanted dbus-daemon processes are running. (I used a podman container with no dbus-daemon processes at all, but it's OK if the "real" system, session and/or AT-SPI buses are already running.)

Build libportal, then run:

xvfb-run -a -s "-noreset" \
env LC_ALL=C.UTF-8 MESON_TESTTHREADS=4 \
meson test --timeout-multiplier 3 -C obj-x86_64-linux-gnu/

where obj-x86_64-linux-gnu/ is the build directory. (This is how the Debian packaging runs the test suite.)

Expected result

Tests pass. No libportal-related dbus-daemon processes remain running (it's OK if the system, session and/or AT-SPI buses are still running from before).

Actual result with python3-dbusmock 0.29.1-2

The tests pass, but 27 dbus-daemon processes are still running afterwards:

$ pgrep dbus-daem|xargs ps
    PID TTY      STAT   TIME COMMAND
  11681 ?        Ss     0:00 dbus-daemon --fork --print-address=1 --print-pid=1 --config-file=/tmp/dbusmock_data_4t6qy
  11688 ?        Ss     0:00 dbus-daemon --fork --print-address=1 --print-pid=1 --config-file=/tmp/dbusmock_data_4t6qy
...
  11792 ?        Ss     0:00 dbus-daemon --fork --print-address=1 --print-pid=1 --config-file=/tmp/dbusmock_data_81inv
  11796 ?        Ss     0:00 dbus-daemon --fork --print-address=1 --print-pid=1 --config-file=/tmp/dbusmock_data_81inv

Actual result with python3-dbusmock 0.30.0-2

The tests fail, with a dbusmock assertion failure:

____________________ TestRemoteDesktop.test_connect_to_eis _____________________

self = <pyportaltest.test_remotedesktop.TestRemoteDesktop testMethod=test_connect_to_eis>

    def test_connect_to_eis(self):
      setup = self.create_session(start_session=True)

pyportaltest/test_remotedesktop.py:428: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
pyportaltest/test_remotedesktop.py:62: in create_session
    self.setup_daemon(params=params, extra_templates=extra_templates)
pyportaltest/__init__.py:99: in setup_daemon
    self.start_session_bus()
/usr/lib/python3/dist-packages/dbusmock/testcase.py:296: in start_session_bus
    cls.__start_bus('session')
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

cls = <class 'pyportaltest.test_remotedesktop.TestRemoteDesktop'>
bus_type = 'session'

    @classmethod
    def __start_bus(cls, bus_type) -> None:
        bustype = BusType(bus_type)
        old_pid = getattr(DBusTestCase, f"{bustype.value}_bus_pid")
>       assert old_pid is None, f"PID {old_pid} still alive?"
E       AssertionError: PID 3954437 still alive?

/usr/lib/python3/dist-packages/dbusmock/testcase.py:284: AssertionError

Root cause

It appears that dbusmock starts and stops temporary session buses on a per-class basis (they're stopped in tearDownClass()) rather than on a per-test-case basis (they are not stopped in tearDown()). In older versions, starting more than one session bus per DBusTestCase subclass would result in only the last session bus being torn down, with all of the others being leaked. In newer versions, there's an assertion to stop that from happening, so the tests will now just fail.