summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test_lsfg_v2_migration.py304
1 files changed, 302 insertions, 2 deletions
diff --git a/tests/test_lsfg_v2_migration.py b/tests/test_lsfg_v2_migration.py
index 4909d8b..ee1fcba 100644
--- a/tests/test_lsfg_v2_migration.py
+++ b/tests/test_lsfg_v2_migration.py
@@ -1,3 +1,4 @@
+import asyncio
import logging
import sys
import tempfile
@@ -73,14 +74,38 @@ class ConfigurationMigrationTests(unittest.TestCase):
self.assertIn("LSFGVK_PROFILE=decky-lsfg-vk", script)
self.assertNotIn("LSFG_PROCESS", script)
- def test_active_in_uses_native_v2_tracking_instead_of_forcing_a_profile(self):
+ def test_active_in_does_not_implicitly_override_the_selected_profile(self):
config = ConfigurationManager.get_defaults()
config["active_in"] = "Game.exe, GameThread"
self.assertEqual(
ConfigurationService._profile_selection_lines("decky-lsfg-vk", config),
- ["# active_in is configured; lsfg-vk will select a matching profile automatically."],
+ ["export LSFGVK_PROFILE=decky-lsfg-vk"],
)
+ config["use_native_matching"] = True
+ self.assertEqual(
+ ConfigurationService._profile_selection_lines("decky-lsfg-vk", config),
+ ["# lsfg-vk will select a matching profile from Active In."],
+ )
+ self.assertEqual(
+ ConfigurationManager.parse_script_content("export DECKY_LSFGVK_AUTO_PROFILE=1\n"),
+ {"use_native_matching": True},
+ )
+
+ def test_cloned_profile_disables_native_matching_until_explicitly_enabled(self):
+ config = ConfigurationManager.get_defaults()
+ config["active_in"] = "Game.exe"
+ config["use_native_matching"] = True
+ profile_data = {
+ "current_profile": "decky-lsfg-vk",
+ "profiles": {"decky-lsfg-vk": config},
+ "global_config": {"dll": "", "allow_fp16": True},
+ }
+
+ cloned = ConfigurationManager.create_profile(profile_data, "Other")
+ self.assertEqual(cloned["profiles"]["Other"]["active_in"], "Game.exe")
+ self.assertFalse(cloned["profiles"]["Other"]["use_native_matching"])
+
class InstallerInfrastructureTests(unittest.TestCase):
def test_layer_archive_selection_has_no_legacy_arm_override(self):
@@ -137,6 +162,36 @@ class InstallerInfrastructureTests(unittest.TestCase):
service._create_config_file()
self.assertEqual(len(list(config_dir.glob("conf.toml.v1.bak*"))), 1)
+ def test_unrecognized_configuration_is_backed_up_before_reset(self):
+ from lsfg_vk.installation import InstallationService
+
+ with tempfile.TemporaryDirectory() as directory:
+ home = Path(directory)
+ config_dir = home / ".config" / "lsfg-vk"
+ config_dir.mkdir(parents=True)
+ config_path = config_dir / "conf.toml"
+ unsupported_config = "version = 3\n"
+ config_path.write_text(unsupported_config, encoding="utf-8")
+
+ service = InstallationService.__new__(InstallationService)
+ service.log = mock.Mock()
+ service.user_home = home
+ service.config_dir = config_dir
+ service.config_file_path = config_path
+ service.lsfg_script_path = home / "lsfg"
+ service.lsfg_launch_script_path = home / "lsfg"
+
+ with mock.patch("lsfg_vk.dll_detection.DllDetectionService") as detection_service:
+ detection_service.return_value.check_lossless_scaling_dll.return_value = {"detected": False}
+ service._create_config_file()
+
+ self.assertEqual(
+ (config_dir / "conf.toml.unrecognized.bak").read_text(encoding="utf-8"),
+ unsupported_config,
+ )
+ self.assertIn("version = 2", config_path.read_text(encoding="utf-8"))
+ self.assertEqual(service._config_recovery_backup, config_dir / "conf.toml.unrecognized.bak")
+
def test_writes_replace_the_config_atomically(self):
service = BaseService.__new__(BaseService)
service.log = mock.Mock()
@@ -152,5 +207,250 @@ class InstallerInfrastructureTests(unittest.TestCase):
replace.assert_called_once()
+class FlatpakMigrationTests(unittest.TestCase):
+ def test_install_uses_the_bundled_flatpak_asset(self):
+ from lsfg_vk.flatpak_service import FlatpakService
+
+ with tempfile.TemporaryDirectory() as directory:
+ bundle_path = Path(directory) / "org.freedesktop.Platform.VulkanLayer.lsfg_vk_23.08.flatpak"
+ bundle_path.write_bytes(b"flatpak bundle")
+
+ service = FlatpakService.__new__(FlatpakService)
+ service.log = mock.Mock()
+ service.check_flatpak_available = mock.Mock(return_value=True)
+ service._get_bundled_extension_path = mock.Mock(return_value=bundle_path)
+ service._run_flatpak_command = mock.Mock(
+ return_value=types.SimpleNamespace(returncode=0, stdout="", stderr="")
+ )
+
+ result = service.install_extension("23.08")
+
+ self.assertTrue(result["success"])
+ service._run_flatpak_command.assert_called_once_with(
+ [
+ "install",
+ "--user",
+ "--or-update",
+ "--assumeyes",
+ "--noninteractive",
+ str(bundle_path),
+ ],
+ capture_output=True,
+ text=True,
+ )
+
+ def test_update_installed_extensions_only_updates_user_runtimes_and_migrates_apps(self):
+ from lsfg_vk.flatpak_service import FlatpakService
+
+ service = FlatpakService.__new__(FlatpakService)
+ service.log = mock.Mock()
+ service.check_flatpak_available = mock.Mock(return_value=True)
+ service._get_installed_extension_versions = mock.Mock(return_value=["23.08", "25.08"])
+ service.install_extension = mock.Mock(
+ side_effect=[{"success": True}, {"success": True}]
+ )
+ service._migrate_legacy_app_overrides = mock.Mock(
+ return_value={
+ "success": True,
+ "migrated_apps": ["org.example.Game"],
+ "failed_apps": [],
+ }
+ )
+
+ result = service.update_installed_extensions()
+
+ self.assertTrue(result["success"])
+ self.assertEqual(result["updated_versions"], ["23.08", "25.08"])
+ self.assertEqual(result["migrated_apps"], ["org.example.Game"])
+ self.assertEqual(
+ service.install_extension.call_args_list,
+ [mock.call("23.08"), mock.call("25.08")],
+ )
+ service._migrate_legacy_app_overrides.assert_called_once_with()
+
+ def test_installed_runtime_scan_is_scoped_to_user_installation(self):
+ from lsfg_vk.flatpak_service import FlatpakService
+
+ service = FlatpakService.__new__(FlatpakService)
+ service._run_flatpak_command = mock.Mock(
+ return_value=types.SimpleNamespace(
+ returncode=0,
+ stdout=(
+ "lsfg-vk\torg.freedesktop.Platform.VulkanLayer.lsfgvk\t"
+ "2.0\t23.08\tx86_64\n"
+ ),
+ stderr="",
+ )
+ )
+
+ self.assertEqual(service._get_installed_extension_versions(), ["23.08"])
+ service._run_flatpak_command.assert_called_once_with(
+ ["list", "--user", "--runtime"],
+ capture_output=True,
+ text=True,
+ check=True,
+ )
+
+ def test_failed_runtime_update_leaves_legacy_overrides_untouched(self):
+ from lsfg_vk.flatpak_service import FlatpakService
+
+ service = FlatpakService.__new__(FlatpakService)
+ service.log = mock.Mock()
+ service.check_flatpak_available = mock.Mock(return_value=True)
+ service._get_installed_extension_versions = mock.Mock(return_value=["24.08"])
+ service.install_extension = mock.Mock(
+ return_value={"success": False, "error": "bundle unavailable"}
+ )
+ service._migrate_legacy_app_overrides = mock.Mock()
+
+ result = service.update_installed_extensions()
+
+ self.assertFalse(result["success"])
+ self.assertEqual(result["failed_versions"][0]["version"], "24.08")
+ service._migrate_legacy_app_overrides.assert_not_called()
+
+ def test_native_install_runs_flatpak_migration_after_success(self):
+ from lsfg_vk.plugin import Plugin
+
+ plugin = Plugin.__new__(Plugin)
+ plugin.installation_service = mock.Mock()
+ plugin.flatpak_service = mock.Mock()
+ plugin.installation_service.install.return_value = {
+ "success": True,
+ "message": "lsfg-vk v2 installed successfully",
+ "error": None,
+ }
+ plugin.flatpak_service.update_installed_extensions.return_value = {
+ "success": True,
+ "message": "Updated one Flatpak runtime",
+ "skipped": False,
+ "updated_versions": ["23.08"],
+ "failed_versions": [],
+ "migrated_apps": [],
+ "failed_apps": [],
+ }
+
+ result = asyncio.run(plugin.install_lsfg_vk())
+
+ self.assertTrue(result["success"])
+ self.assertIn("flatpak_update", result)
+ plugin.flatpak_service.update_installed_extensions.assert_called_once_with()
+
+ def test_legacy_override_detection_does_not_match_v2_environment(self):
+ from lsfg_vk.flatpak_service import FlatpakService
+
+ with tempfile.TemporaryDirectory() as directory:
+ home = Path(directory)
+ service = FlatpakService.__new__(FlatpakService)
+ service.user_home = home
+ service.config_dir = home / ".config/lsfg-vk"
+ service.config_file_path = service.config_dir / "conf.toml"
+ service.lsfg_launch_script_path = home / "lsfg"
+ service.log = mock.Mock()
+
+ self.assertTrue(
+ service._has_legacy_app_override(
+ f"LSFG_CONFIG={service.config_file_path}\n"
+ )
+ )
+ self.assertFalse(
+ service._has_legacy_app_override(
+ f"LSFGVK_CONFIG={service.config_file_path}\n"
+ )
+ )
+
+ def test_legacy_override_migration_only_touches_plugin_owned_apps(self):
+ from lsfg_vk.flatpak_service import FlatpakService
+
+ with tempfile.TemporaryDirectory() as directory:
+ home = Path(directory)
+ service = FlatpakService.__new__(FlatpakService)
+ service.user_home = home
+ service.config_dir = home / ".config/lsfg-vk"
+ service.config_file_path = service.config_dir / "conf.toml"
+ service.lsfg_launch_script_path = home / "lsfg"
+ service.log = mock.Mock()
+ service._get_flatpak_app_ids = mock.Mock(
+ return_value=["org.example.Legacy", "org.example.V2", "org.example.Other"]
+ )
+ service._get_app_override_output = mock.Mock(
+ side_effect=[
+ f"LSFG_CONFIG={service.config_file_path}\n",
+ f"LSFGVK_CONFIG={service.config_file_path}\n",
+ "",
+ ]
+ )
+ service.set_app_override = mock.Mock(return_value={"success": True})
+
+ result = service._migrate_legacy_app_overrides()
+
+ self.assertTrue(result["success"])
+ self.assertEqual(result["migrated_apps"], ["org.example.Legacy"])
+ service.set_app_override.assert_called_once_with("org.example.Legacy")
+
+ def test_v2_override_setup_and_removal_clean_legacy_overrides(self):
+ from lsfg_vk.flatpak_service import FlatpakService
+
+ with tempfile.TemporaryDirectory() as directory:
+ home = Path(directory)
+ config_dir = home / ".config" / "lsfg-vk"
+ config_dir.mkdir(parents=True)
+ config_path = config_dir / "conf.toml"
+ config_path.write_text(
+ ConfigurationManager.generate_toml_content(ConfigurationManager.get_defaults()),
+ encoding="utf-8",
+ )
+
+ service = FlatpakService.__new__(FlatpakService)
+ service.log = mock.Mock()
+ service.user_home = home
+ service.config_dir = config_dir
+ service.config_file_path = config_path
+ service.lsfg_launch_script_path = home / "lsfg"
+ service.check_flatpak_available = mock.Mock(return_value=True)
+ service._run_flatpak_command = mock.Mock(
+ return_value=types.SimpleNamespace(returncode=0, stdout="", stderr="")
+ )
+
+ app_id = "org.example.Game"
+ result = service.set_app_override(app_id)
+ self.assertTrue(result["success"])
+ setup_calls = [call.args[0] for call in service._run_flatpak_command.call_args_list]
+ self.assertIn(
+ ["override", "--user", f"--env=LSFGVK_CONFIG={config_path}", app_id],
+ setup_calls,
+ )
+ self.assertIn(
+ ["override", "--user", "--unset-env=LSFG_CONFIG", app_id],
+ setup_calls,
+ )
+ self.assertIn(
+ [
+ "override",
+ "--user",
+ f"--nofilesystem={home / '.local/share/Steam/steamapps/common/Lossless Scaling/Lossless.dll'}",
+ app_id,
+ ],
+ setup_calls,
+ )
+ self.assertIn(
+ ["override", "--user", f"--nofilesystem={home / 'lsfg'}", app_id],
+ setup_calls,
+ )
+
+ service._run_flatpak_command.reset_mock()
+ result = service.remove_app_override(app_id)
+ self.assertTrue(result["success"])
+ removal_calls = [call.args[0] for call in service._run_flatpak_command.call_args_list]
+ self.assertIn(
+ ["override", "--user", "--unset-env=LSFG_CONFIG", app_id],
+ removal_calls,
+ )
+ self.assertIn(
+ ["override", "--user", f"--nofilesystem={home / 'lsfg'}", app_id],
+ removal_calls,
+ )
+
+
if __name__ == "__main__":
unittest.main()