import unittest from unittest import mock from cthulhu.wine_access_manager import PrefixProcess, WineAccessManager class WineAccessManagerTest(unittest.TestCase): def test_prefix_prefers_explicit_wineprefix(self): environment = { "WINEPREFIX": "/tmp/custom-prefix", "STEAM_COMPAT_DATA_PATH": "/tmp/compat", } self.assertEqual( WineAccessManager._prefix_from_environ(environment), "/tmp/custom-prefix" ) def test_prefix_uses_proton_pfx(self): environment = {"STEAM_COMPAT_DATA_PATH": "/tmp/compat"} self.assertEqual(WineAccessManager._prefix_from_environ(environment), "/tmp/compat/pfx") @mock.patch("cthulhu.wine_access_manager.os.access", return_value=True) @mock.patch( "cthulhu.wine_access_manager.os.readlink", return_value="/opt/proton/files/bin/wine64-preloader", ) def test_preloader_resolves_to_runtime_loader(self, _readlink, _access): self.assertEqual( WineAccessManager._loader_for_process(100, {}), "/opt/proton/files/bin/wine64", ) @mock.patch("cthulhu.wine_access_manager.subprocess.Popen") def test_launch_preserves_prefix_and_runtime_loader(self, popen): process = mock.Mock() process.poll.return_value = None popen.return_value = process manager = WineAccessManager("/usr/bin/cthulhu-wine-access.exe") state = PrefixProcess() manager._ensure_running( "/tmp/prefix", state, {"DBUS_SESSION_BUS_ADDRESS": "unix:path=/run/user/1000/bus"}, "/opt/proton/files/bin/wine64", 10.0, ) environment = popen.call_args.kwargs["env"] self.assertEqual(environment["WINEPREFIX"], "/tmp/prefix") self.assertEqual(environment["WINELOADER"], "/opt/proton/files/bin/wine64") self.assertEqual(environment[manager.MANAGED_ENVIRONMENT_KEY], "1") self.assertEqual( environment["DBUS_SESSION_BUS_ADDRESS"], "unix:path=/run/user/1000/bus" ) self.assertEqual(popen.call_args.args[0], ["/usr/bin/cthulhu-wine-access.exe"]) @mock.patch("cthulhu.wine_access_manager.subprocess.Popen") def test_disabled_surfaces_are_passed_to_helper(self, popen): process = mock.Mock() process.poll.return_value = None popen.return_value = process manager = WineAccessManager("/usr/bin/cthulhu-wine-access.exe") manager.dialogReaderEnabled = False manager.controllerEnabled = False manager._ensure_running("/tmp/prefix", PrefixProcess(), {}, None, 10.0) self.assertEqual( popen.call_args.args[0], [ "/usr/bin/cthulhu-wine-access.exe", "--no-dialog-reader", "--no-controller", ], ) def test_short_lived_helper_gets_restart_backoff(self): manager = WineAccessManager("/usr/bin/cthulhu-wine-access.exe") state = PrefixProcess() state.process = mock.Mock() state.process.poll.return_value = 0 state.startedAt = 9.0 manager._record_exit(state, 10.0) self.assertIsNone(state.process) self.assertEqual(state.failures, 1) self.assertEqual(state.nextStart, 12.0) @mock.patch.object(WineAccessManager, "_loader_for_process", return_value=None) @mock.patch.object( WineAccessManager, "_read_environ", return_value={"WINEPREFIX": "/tmp/exported-prefix"}, ) @mock.patch("cthulhu.wine_access_manager.Path.iterdir") @mock.patch("cthulhu.wine_access_manager.os.getuid", return_value=1000) def test_discovery_ignores_non_wine_processes( self, _getuid, iterdir, _read_environ, _loader ): entry = mock.Mock() entry.name = "123" entry.stat.return_value.st_uid = 1000 iterdir.return_value = [entry] self.assertEqual(WineAccessManager("/tmp/helper").discover_prefixes(), {}) @mock.patch.object(WineAccessManager, "_loader_for_process") @mock.patch.object( WineAccessManager, "_read_environ", return_value={ "WINEPREFIX": "/tmp/prefix", WineAccessManager.MANAGED_ENVIRONMENT_KEY: "1", }, ) @mock.patch("cthulhu.wine_access_manager.Path.iterdir") @mock.patch("cthulhu.wine_access_manager.os.getuid", return_value=1000) def test_discovery_ignores_managed_helper_processes( self, _getuid, iterdir, _read_environ, loader ): entry = mock.Mock() entry.name = "123" entry.stat.return_value.st_uid = 1000 iterdir.return_value = [entry] self.assertEqual(WineAccessManager("/tmp/helper").discover_prefixes(), {}) loader.assert_not_called() if __name__ == "__main__": unittest.main()