From 34a215b03707bd82f4131f306682a2a45ac99374 Mon Sep 17 00:00:00 2001 From: R1kaB3rN <100738684+R1kaB3rN@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:38:03 -0800 Subject: [PATCH 1/5] umu_run: refactor set_steam_game_property to return display on success --- umu/umu_run.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/umu/umu_run.py b/umu/umu_run.py index db5523970..f62e9c480 100755 --- a/umu/umu_run.py +++ b/umu/umu_run.py @@ -377,10 +377,10 @@ def get_window_ids(d: display.Display) -> set[str] | None: def set_steam_game_property( d: display.Display, - window_ids: list[str] | set[str], + window_ids: set[str], steam_assigned_appid: int, -) -> None: - """Set Steam's assigned layer ID on a list of windows.""" +) -> display.Display: + """Set Steam's assigned app ID on a list of windows.""" log.debug("Steam app ID: %s", steam_assigned_appid) for window_id in window_ids: try: @@ -404,6 +404,8 @@ def set_steam_game_property( ) log.exception(e) + return d + def get_gamescope_baselayer_appid( d: display.Display, From 4f578b6bd091e5b3ed2a85b161df07abda37aea1 Mon Sep 17 00:00:00 2001 From: R1kaB3rN <100738684+R1kaB3rN@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:38:32 -0800 Subject: [PATCH 2/5] umu_run: refactor set_gamescope_baselayer_appid to return display on success --- umu/umu_run.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/umu/umu_run.py b/umu/umu_run.py index f62e9c480..515e9f1c7 100755 --- a/umu/umu_run.py +++ b/umu/umu_run.py @@ -466,7 +466,7 @@ def rearrange_gamescope_baselayer_appid( def set_gamescope_baselayer_appid( d: display.Display, rearranged: list[int] -) -> None: +) -> display.Display | None: """Set a new gamescope GAMESCOPECTRL_BASELAYER_APPID on the primary root window.""" try: # Intern the atom for GAMESCOPECTRL_BASELAYER_APPID @@ -478,12 +478,15 @@ def set_gamescope_baselayer_appid( GamescopeAtom.BaselayerAppId.value, ", ".join(map(str, rearranged)), ) + return d except Exception as e: log.error( "Error setting %s property", GamescopeAtom.BaselayerAppId.value ) log.exception(e) + return None + def get_steam_appid(env: MutableMapping) -> int: """Get the Steam app ID from the host environment variables.""" From 6c36e300272ccaa22956b50dd5dfd8b92dde7e4e Mon Sep 17 00:00:00 2001 From: R1kaB3rN <100738684+R1kaB3rN@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:40:12 -0800 Subject: [PATCH 3/5] umu_test: add tests for get_gamescope_baselayer_appid --- umu/umu_test.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/umu/umu_test.py b/umu/umu_test.py index 8dacd60c0..e082d51ec 100644 --- a/umu/umu_test.py +++ b/umu/umu_test.py @@ -5,6 +5,7 @@ import tarfile import unittest from argparse import Namespace +from array import array from concurrent.futures import ThreadPoolExecutor from pathlib import Path from pwd import getpwuid @@ -13,6 +14,12 @@ from tempfile import TemporaryDirectory, mkdtemp from unittest.mock import MagicMock, patch +from Xlib.display import Display +from Xlib.error import DisplayConnectionError +from Xlib.protocol.rq import Event +from Xlib.X import CreateNotify +from Xlib.xobject.drawable import Window + sys.path.append(str(Path(__file__).parent.parent)) from umu import __main__, umu_proton, umu_run, umu_runtime, umu_util @@ -176,6 +183,41 @@ def tearDown(self): if self.test_cache_home.exists(): rmtree(self.test_cache_home.as_posix()) + def test_get_gamescope_baselayer_appid_err(self): + """Test get_gamescope_baselayer_appid on error. + + Expects function be fail safe, handling any exceptions when getting + GAMESCOPECTRL_BASELAYER_APPID + """ + mock_display = MagicMock(spec=Display) + mock_display.screen.side_effect = DisplayConnectionError( + mock_display, "foo" + ) + + result = umu_run.get_gamescope_baselayer_appid(mock_display) + self.assertTrue( + result is None, f"Expected a value, received: {result}" + ) + + def test_get_gamescope_baselayer_appid(self): + """Test get_gamescope_baselayer_appid.""" + mock_display = MagicMock(spec=Display) + mock_screen = MagicMock() + mock_root = MagicMock() + mock_prop = MagicMock() + result = None + + mock_display.screen.return_value = mock_screen + mock_display.get_atom.return_value = 0 + mock_screen.root = mock_root + mock_root.get_full_property.return_value = mock_prop + mock_prop.value = array("I", [1, 2, 3]) + + result = umu_run.get_gamescope_baselayer_appid(mock_display) + self.assertTrue( + result == [1, 2, 3], f"Expected a value, received: {result}" + ) + def test_get_steam_layer_id(self): """Test get_steam_layer_id. From a24c7385980a4eb5ac6214f37f79e69dbe3c2aec Mon Sep 17 00:00:00 2001 From: R1kaB3rN <100738684+R1kaB3rN@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:40:36 -0800 Subject: [PATCH 4/5] umu_test: add tests set_steam_game_propert --- umu/umu_test.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/umu/umu_test.py b/umu/umu_test.py index e082d51ec..a4c01ffdf 100644 --- a/umu/umu_test.py +++ b/umu/umu_test.py @@ -218,6 +218,48 @@ def test_get_gamescope_baselayer_appid(self): result == [1, 2, 3], f"Expected a value, received: {result}" ) + def test_set_steam_game_property_err(self): + """Test set_steam_game_property on error. + + Expects function be fail safe, handling any exceptions when setting + a new value for STEAM_GAME. + """ + mock_display = MagicMock(spec=Display) + mock_window_ids = {"1", "2", "3"} + mock_appid = 123 + + mock_display.create_resource_object.side_effect = ( + DisplayConnectionError(mock_display, "foo") + ) + + result = umu_run.set_steam_game_property( + mock_display, mock_window_ids, mock_appid + ) + + self.assertTrue( + result is mock_display, f"Expected Display, received: {result}" + ) + mock_display.create_resource_object.assert_called() + + def test_set_steam_game_property(self): + """Test set_steam_game_property.""" + mock_display = MagicMock(spec=Display) + mock_window = MagicMock(spec=Window) + mock_window_ids = {"1", "2", "3"} + mock_appid = 123 + + mock_display.create_resource_object.return_value = mock_window + mock_display.get_atom.return_value = 0 + + result = umu_run.set_steam_game_property( + mock_display, mock_window_ids, mock_appid + ) + self.assertTrue( + result is mock_display, f"Expected Display, received: {result}" + ) + mock_display.create_resource_object.assert_called() + mock_display.get_atom.assert_called() + def test_get_steam_layer_id(self): """Test get_steam_layer_id. From 9e23cb63a060be2fcde4abc16b5eae9963c31eb1 Mon Sep 17 00:00:00 2001 From: R1kaB3rN <100738684+R1kaB3rN@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:41:04 -0800 Subject: [PATCH 5/5] umu_test: add tests for get_window_ids --- umu/umu_test.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/umu/umu_test.py b/umu/umu_test.py index a4c01ffdf..a25ffe915 100644 --- a/umu/umu_test.py +++ b/umu/umu_test.py @@ -260,6 +260,61 @@ def test_set_steam_game_property(self): mock_display.create_resource_object.assert_called() mock_display.get_atom.assert_called() + def test_get_window_ids_err(self): + """Test get_window_ids on error. + + Expects function to be fail safe, so any exceptions should be handled + when returning child windows. + """ + mock_display = MagicMock(spec=Display) + mock_event = MagicMock(spec=Event) + mock_screen = MagicMock() + mock_root = MagicMock() + mock_query_tree = MagicMock() + + mock_event.type = CreateNotify + mock_display.next_event.return_value = mock_event + + mock_display.screen.return_value = mock_screen + mock_screen.root = mock_root + mock_root.query_tree.side_effect = DisplayConnectionError( + mock_display, "foo" + ) + mock_query_tree.children = set() + + result = umu_run.get_window_ids(mock_display) + + # Assertions + self.assertTrue(result is None, f"Expected None, received: {result}") + mock_display.next_event.assert_called_once() + mock_display.screen.assert_called_once() + mock_screen.root.query_tree.assert_called_once() + + def test_get_window_ids(self): + """Test get_window_ids.""" + mock_display = MagicMock(spec=Display) + mock_event = MagicMock(spec=Event) + mock_screen = MagicMock() + mock_root = MagicMock() + mock_query_tree = MagicMock() + + mock_event.type = CreateNotify + mock_display.next_event.return_value = mock_event + + mock_display.screen.return_value = mock_screen + mock_screen.root = mock_root + mock_root.query_tree.return_value = mock_query_tree + mock_query_tree.children = set() + + result = umu_run.get_window_ids(mock_display) + + self.assertTrue( + isinstance(result, set), f"Expected a set, received: {result}" + ) + mock_display.next_event.assert_called_once() + mock_display.screen.assert_called_once() + mock_screen.root.query_tree.assert_called_once() + def test_get_steam_layer_id(self): """Test get_steam_layer_id.