summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxXJSONDeruloXx <danielhimebauch@gmail.com>2025-07-22 11:11:44 -0400
committerxXJSONDeruloXx <danielhimebauch@gmail.com>2025-07-22 11:11:44 -0400
commitc02343e68874efd57c2e312cb6b7e4f02222e43a (patch)
tree31e7a46aca624de9eeb778f2337b2c0d9906b628
parent97bb41947bd44a712ad26905771a9d2cc4692878 (diff)
downloaddecky-lsfg-vk-c02343e68874efd57c2e312cb6b7e4f02222e43a.tar.gz
decky-lsfg-vk-c02343e68874efd57c2e312cb6b7e4f02222e43a.zip
add workaround env vars, rm old tests
-rw-r--r--package.json2
-rw-r--r--py_modules/lsfg_vk/config_schema.py28
-rw-r--r--py_modules/lsfg_vk/configuration.py19
-rw-r--r--py_modules/lsfg_vk/plugin.py9
-rw-r--r--shared_config.py14
-rw-r--r--src/api/lsfgApi.ts4
-rw-r--r--src/components/ConfigurationSection.tsx18
-rw-r--r--src/config/configSchema.ts6
-rw-r--r--src/config/generatedConfigSchema.ts18
-rw-r--r--tests/conftest.py31
-rw-r--r--tests/test_configuration.py190
-rw-r--r--tests/test_dll_detection.py129
-rw-r--r--tests/test_installation.py150
13 files changed, 106 insertions, 512 deletions
diff --git a/package.json b/package.json
index 9fcf10d..ee18530 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "decky-lossless-scaling-vk",
- "version": "0.6.9",
+ "version": "0.6.10",
"description": "Use Lossless Scaling on the Steam Deck using the lsfg-vk vulkan layer",
"type": "module",
"scripts": {
diff --git a/py_modules/lsfg_vk/config_schema.py b/py_modules/lsfg_vk/config_schema.py
index c82d1d3..6a68db1 100644
--- a/py_modules/lsfg_vk/config_schema.py
+++ b/py_modules/lsfg_vk/config_schema.py
@@ -73,6 +73,20 @@ SCRIPT_ONLY_FIELDS = {
field_type=ConfigFieldType.BOOLEAN,
default=False,
description="disable Steam Deck mode (unlocks hidden settings in some games)"
+ ),
+
+ "mangohud_workaround": ConfigField(
+ name="mangohud_workaround",
+ field_type=ConfigFieldType.BOOLEAN,
+ default=False,
+ description="Enables a transparent mangohud overlay, sometimes fixes issues with 2X multiplier in game mode"
+ ),
+
+ "disable_vkbasalt": ConfigField(
+ name="disable_vkbasalt",
+ field_type=ConfigFieldType.BOOLEAN,
+ default=False,
+ description="Disables vkBasalt layer which can conflict with LSFG (Reshade, some Decky plugins)"
)
}
@@ -91,6 +105,8 @@ class ConfigurationData(TypedDict):
dxvk_frame_rate: int
enable_wow64: bool
disable_steamdeck_mode: bool
+ mangohud_workaround: bool
+ disable_vkbasalt: bool
class ConfigurationManager:
@@ -335,6 +351,10 @@ class ConfigurationManager:
script_values["enable_wow64"] = value == "1"
elif key == "SteamDeck":
script_values["disable_steamdeck_mode"] = value == "0"
+ elif key == "MANGOHUD":
+ script_values["mangohud_workaround"] = value == "1"
+ elif key == "DISABLE_VKBASALT":
+ script_values["disable_vkbasalt"] = value == "1"
except (ValueError, KeyError, IndexError) as e:
# If parsing fails, log the error and return empty dict (will use defaults)
@@ -368,7 +388,9 @@ class ConfigurationManager:
experimental_present_mode: str = "fifo",
dxvk_frame_rate: int = 0,
enable_wow64: bool = False,
- disable_steamdeck_mode: bool = False) -> ConfigurationData:
+ disable_steamdeck_mode: bool = False,
+ mangohud_workaround: bool = False,
+ disable_vkbasalt: bool = False) -> ConfigurationData:
"""Create configuration from individual arguments"""
return cast(ConfigurationData, {
"dll": dll,
@@ -379,5 +401,7 @@ class ConfigurationManager:
"experimental_present_mode": experimental_present_mode,
"dxvk_frame_rate": dxvk_frame_rate,
"enable_wow64": enable_wow64,
- "disable_steamdeck_mode": disable_steamdeck_mode
+ "disable_steamdeck_mode": disable_steamdeck_mode,
+ "mangohud_workaround": mangohud_workaround,
+ "disable_vkbasalt": disable_vkbasalt
})
diff --git a/py_modules/lsfg_vk/configuration.py b/py_modules/lsfg_vk/configuration.py
index 47d0ebc..82982e5 100644
--- a/py_modules/lsfg_vk/configuration.py
+++ b/py_modules/lsfg_vk/configuration.py
@@ -65,7 +65,9 @@ class ConfigurationService(BaseService):
experimental_present_mode: str = "fifo",
dxvk_frame_rate: int = 0,
enable_wow64: bool = False,
- disable_steamdeck_mode: bool = False) -> ConfigurationResponse:
+ disable_steamdeck_mode: bool = False,
+ mangohud_workaround: bool = False,
+ disable_vkbasalt: bool = False) -> ConfigurationResponse:
"""Update TOML configuration
Args:
@@ -78,6 +80,8 @@ class ConfigurationService(BaseService):
dxvk_frame_rate: Frame rate cap for DirectX games, before frame multiplier (0 = disabled)
enable_wow64: Whether to enable PROTON_USE_WOW64=1 for 32-bit games
disable_steamdeck_mode: Whether to disable Steam Deck mode
+ mangohud_workaround: Whether to enable MangoHud workaround with transparent overlay
+ disable_vkbasalt: Whether to disable vkBasalt layer
Returns:
ConfigurationResponse with success status
@@ -86,7 +90,8 @@ class ConfigurationService(BaseService):
# Create configuration from individual arguments
config = ConfigurationManager.create_config_from_args(
dll, multiplier, flow_scale, performance_mode, hdr_mode,
- experimental_present_mode, dxvk_frame_rate, enable_wow64, disable_steamdeck_mode
+ experimental_present_mode, dxvk_frame_rate, enable_wow64, disable_steamdeck_mode,
+ mangohud_workaround, disable_vkbasalt
)
# Generate TOML content using centralized manager
@@ -108,7 +113,8 @@ class ConfigurationService(BaseService):
f"performance_mode={performance_mode}, hdr_mode={hdr_mode}, "
f"experimental_present_mode='{experimental_present_mode}', "
f"dxvk_frame_rate={dxvk_frame_rate}, "
- f"enable_wow64={enable_wow64}, disable_steamdeck_mode={disable_steamdeck_mode}")
+ f"enable_wow64={enable_wow64}, disable_steamdeck_mode={disable_steamdeck_mode}, "
+ f"mangohud_workaround={mangohud_workaround}, disable_vkbasalt={disable_vkbasalt}")
return self._success_response(ConfigurationResponse,
"lsfg configuration updated successfully",
@@ -214,6 +220,13 @@ class ConfigurationService(BaseService):
if config.get("disable_steamdeck_mode", False):
lines.append("export SteamDeck=0")
+ if config.get("mangohud_workaround", False):
+ lines.append("export MANGOHUD=1")
+ lines.append("export MANGOHUD_CONFIG=alpha=0.01,background_alpha=0.01")
+
+ if config.get("disable_vkbasalt", False):
+ lines.append("export DISABLE_VKBASALT=1")
+
# Add DXVK_FRAME_RATE if dxvk_frame_rate is set
dxvk_frame_rate = config.get("dxvk_frame_rate", 0)
if dxvk_frame_rate > 0:
diff --git a/py_modules/lsfg_vk/plugin.py b/py_modules/lsfg_vk/plugin.py
index 425d7e7..7deed71 100644
--- a/py_modules/lsfg_vk/plugin.py
+++ b/py_modules/lsfg_vk/plugin.py
@@ -189,7 +189,9 @@ class Plugin:
experimental_present_mode: str = "fifo",
dxvk_frame_rate: int = 0,
enable_wow64: bool = False,
- disable_steamdeck_mode: bool = False) -> Dict[str, Any]:
+ disable_steamdeck_mode: bool = False,
+ mangohud_workaround: bool = False,
+ disable_vkbasalt: bool = False) -> Dict[str, Any]:
"""Update lsfg TOML configuration
Args:
@@ -202,13 +204,16 @@ class Plugin:
dxvk_frame_rate: Frame rate cap for DirectX games, before frame multiplier (0 = disabled)
enable_wow64: Whether to enable PROTON_USE_WOW64=1 for 32-bit games
disable_steamdeck_mode: Whether to disable Steam Deck mode
+ mangohud_workaround: Whether to enable MangoHud workaround with transparent overlay
+ disable_vkbasalt: Whether to disable vkBasalt layer
Returns:
ConfigurationResponse dict with success status
"""
return self.configuration_service.update_config(
dll, multiplier, flow_scale, performance_mode, hdr_mode,
- experimental_present_mode, dxvk_frame_rate, enable_wow64, disable_steamdeck_mode
+ experimental_present_mode, dxvk_frame_rate, enable_wow64, disable_steamdeck_mode,
+ mangohud_workaround, disable_vkbasalt
)
async def update_dll_path(self, dll_path: str) -> Dict[str, Any]:
diff --git a/shared_config.py b/shared_config.py
index 46bfc84..518294d 100644
--- a/shared_config.py
+++ b/shared_config.py
@@ -81,6 +81,20 @@ CONFIG_SCHEMA_DEF = {
"fieldType": ConfigFieldType.BOOLEAN,
"default": False,
"description": "disable Steam Deck mode (unlocks hidden settings in some games)"
+ },
+
+ "mangohud_workaround": {
+ "name": "mangohud_workaround",
+ "fieldType": ConfigFieldType.BOOLEAN,
+ "default": False,
+ "description": "Enables a transparent mangohud overlay, sometimes fixes issues with 2X multiplier in game mode"
+ },
+
+ "disable_vkbasalt": {
+ "name": "disable_vkbasalt",
+ "fieldType": ConfigFieldType.BOOLEAN,
+ "default": False,
+ "description": "Disables vkBasalt layer which can conflict with LSFG (Reshade, some Decky plugins)"
}
}
diff --git a/src/api/lsfgApi.ts b/src/api/lsfgApi.ts
index 74caa57..0b221e9 100644
--- a/src/api/lsfgApi.ts
+++ b/src/api/lsfgApi.ts
@@ -101,14 +101,14 @@ export const getLaunchScriptContent = callable<[], FileContentResult>("get_launc
// Updated config function using centralized configuration
export const updateLsfgConfig = callable<
- [string, number, number, boolean, boolean, string, number, boolean, boolean],
+ [string, number, number, boolean, boolean, string, number, boolean, boolean, boolean, boolean],
ConfigUpdateResult
>("update_lsfg_config");
// Helper function to create config update from configuration object
export const updateLsfgConfigFromObject = async (config: ConfigurationData): Promise<ConfigUpdateResult> => {
const args = ConfigurationManager.createArgsFromConfig(config);
- return updateLsfgConfig(...args as [string, number, number, boolean, boolean, string, number, boolean, boolean]);
+ return updateLsfgConfig(...args as [string, number, number, boolean, boolean, string, number, boolean, boolean, boolean, boolean]);
};
// Self-updater API functions
diff --git a/src/components/ConfigurationSection.tsx b/src/components/ConfigurationSection.tsx
index 59ad880..26099e7 100644
--- a/src/components/ConfigurationSection.tsx
+++ b/src/components/ConfigurationSection.tsx
@@ -154,6 +154,24 @@ export function ConfigurationSection({
onChange={(value) => onConfigChange('disable_steamdeck_mode', value)}
/>
</PanelSectionRow>
+
+ <PanelSectionRow>
+ <ToggleField
+ label="MangoHud Workaround"
+ description="Enables a transparent mangohud overlay, sometimes fixes issues with 2X multiplier in game mode"
+ checked={config.mangohud_workaround}
+ onChange={(value) => onConfigChange('mangohud_workaround', value)}
+ />
+ </PanelSectionRow>
+
+ <PanelSectionRow>
+ <ToggleField
+ label="Disable vkBasalt"
+ description="Disables vkBasalt layer which can conflict with LSFG (Reshade, some Decky plugins)"
+ checked={config.disable_vkbasalt}
+ onChange={(value) => onConfigChange('disable_vkbasalt', value)}
+ />
+ </PanelSectionRow>
</>
);
}
diff --git a/src/config/configSchema.ts b/src/config/configSchema.ts
index 4ab0d25..979d3c9 100644
--- a/src/config/configSchema.ts
+++ b/src/config/configSchema.ts
@@ -52,7 +52,7 @@ export class ConfigurationManager {
/**
* Create args array from config object for lsfg API calls
*/
- static createArgsFromConfig(config: ConfigurationData): [string, number, number, boolean, boolean, string, number, boolean, boolean] {
+ static createArgsFromConfig(config: ConfigurationData): [string, number, number, boolean, boolean, string, number, boolean, boolean, boolean, boolean] {
return [
config.dll,
config.multiplier,
@@ -62,7 +62,9 @@ export class ConfigurationManager {
config.experimental_present_mode,
config.dxvk_frame_rate,
config.enable_wow64,
- config.disable_steamdeck_mode
+ config.disable_steamdeck_mode,
+ config.mangohud_workaround,
+ config.disable_vkbasalt
];
}
diff --git a/src/config/generatedConfigSchema.ts b/src/config/generatedConfigSchema.ts
index 5f0e368..cb08252 100644
--- a/src/config/generatedConfigSchema.ts
+++ b/src/config/generatedConfigSchema.ts
@@ -71,6 +71,18 @@ export const CONFIG_SCHEMA: Record<string, ConfigField> = {
default: false,
description: "disable Steam Deck mode (unlocks hidden settings in some games)"
},
+ mangohud_workaround: {
+ name: "mangohud_workaround",
+ fieldType: ConfigFieldType.BOOLEAN,
+ default: false,
+ description: "Enables a transparent mangohud overlay, sometimes fixes issues with 2X multiplier in game mode"
+ },
+ disable_vkbasalt: {
+ name: "disable_vkbasalt",
+ fieldType: ConfigFieldType.BOOLEAN,
+ default: false,
+ description: "Disables vkBasalt layer which can conflict with LSFG (Reshade, some Decky plugins)"
+ },
};
// Type-safe configuration data structure
@@ -84,6 +96,8 @@ export interface ConfigurationData {
dxvk_frame_rate: number;
enable_wow64: boolean;
disable_steamdeck_mode: boolean;
+ mangohud_workaround: boolean;
+ disable_vkbasalt: boolean;
}
// Helper functions
@@ -102,6 +116,8 @@ export function getDefaults(): ConfigurationData {
dxvk_frame_rate: 0,
enable_wow64: false,
disable_steamdeck_mode: false,
+ mangohud_workaround: false,
+ disable_vkbasalt: false,
};
}
@@ -116,6 +132,8 @@ export function getFieldTypes(): Record<string, ConfigFieldType> {
dxvk_frame_rate: ConfigFieldType.INTEGER,
enable_wow64: ConfigFieldType.BOOLEAN,
disable_steamdeck_mode: ConfigFieldType.BOOLEAN,
+ mangohud_workaround: ConfigFieldType.BOOLEAN,
+ disable_vkbasalt: ConfigFieldType.BOOLEAN,
};
}
diff --git a/tests/conftest.py b/tests/conftest.py
deleted file mode 100644
index 9ac31a0..0000000
--- a/tests/conftest.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""
-Test configuration for the lsfg-vk plugin tests.
-"""
-
-import pytest
-from unittest.mock import Mock
-
-
-@pytest.fixture
-def mock_logger():
- """Provide a mock logger for testing"""
- return Mock()
-
-
-@pytest.fixture
-def mock_decky_logger(monkeypatch):
- """Mock decky.logger for tests that import decky"""
- mock_logger = Mock()
-
- # Create a mock decky module
- mock_decky = Mock()
- mock_decky.logger = mock_logger
-
- # Monkeypatch the import
- monkeypatch.setattr('lsfg_vk.base_service.decky', mock_decky)
- monkeypatch.setattr('lsfg_vk.installation.decky', mock_decky)
- monkeypatch.setattr('lsfg_vk.dll_detection.decky', mock_decky)
- monkeypatch.setattr('lsfg_vk.configuration.decky', mock_decky)
- monkeypatch.setattr('lsfg_vk.plugin.decky', mock_decky)
-
- return mock_logger
diff --git a/tests/test_configuration.py b/tests/test_configuration.py
deleted file mode 100644
index 3e0ad79..0000000
--- a/tests/test_configuration.py
+++ /dev/null
@@ -1,190 +0,0 @@
-"""
-Tests for the configuration service.
-"""
-
-import tempfile
-from pathlib import Path
-from unittest.mock import Mock
-
-from lsfg_vk.configuration import ConfigurationService
-from lsfg_vk.config_schema import ConfigurationManager
-
-
-def test_parse_script_content():
- """Test parsing of script content with current environment variable format"""
-
- # Test script content matching current format
- script_content = """#!/bin/bash
-# lsfg-vk launch script generated by decky-lossless-scaling-vk plugin
-# This script sets up the environment for lsfg-vk to work with the plugin configuration
-export PROTON_USE_WOW64=1
-export SteamDeck=0
-export DXVK_FRAME_RATE=18
-export LSFG_PROCESS=decky-lsfg-vk
-exec "$@"
-"""
-
- script_values = ConfigurationManager.parse_script_content(script_content)
-
- assert script_values["enable_wow64"] is True
- assert script_values["disable_steamdeck_mode"] is True # SteamDeck=0 means disable
- assert script_values["dxvk_frame_rate"] == 18
-
-
-def test_parse_script_content_minimal():
- """Test parsing when only required exports are present"""
-
- script_content = """#!/bin/bash
-# lsfg-vk launch script generated by decky-lossless-scaling-vk plugin
-export LSFG_PROCESS=decky-lsfg-vk
-exec "$@"
-"""
-
- script_values = ConfigurationManager.parse_script_content(script_content)
-
- # Should be empty dict since no tracked env vars are present
- assert script_values == {}
-
-
-def test_merge_config_with_script():
- """Test merging TOML config with script environment variables"""
-
- # Get defaults
- toml_config = ConfigurationManager.get_defaults()
-
- # Script values from parsing
- script_values = {
- "enable_wow64": True,
- "disable_steamdeck_mode": True,
- "dxvk_frame_rate": 30
- }
-
- merged = ConfigurationManager.merge_config_with_script(toml_config, script_values)
-
- # TOML fields should be preserved
- assert merged["multiplier"] == 1 # default from TOML
- assert merged["flow_scale"] == 0.8 # default from TOML
- assert merged["performance_mode"] is True # default from TOML
-
- # Script fields should be overlaid
- assert merged["enable_wow64"] is True
- assert merged["disable_steamdeck_mode"] is True
- assert merged["dxvk_frame_rate"] == 30
-
- with tempfile.TemporaryDirectory() as temp_dir:
- temp_home = Path(temp_dir)
-
- service = ConfigurationService(logger=mock_logger)
- service.user_home = temp_home
- service.lsfg_script_path = temp_home / "lsfg"
-
- script_content = """#!/bin/bash
-
-# export ENABLE_LSFG=1
-export LSFG_MULTIPLIER=2
-export LSFG_FLOW_SCALE=1.0
-# export LSFG_HDR=1
-# export LSFG_PERF_MODE=1
-# export MESA_VK_WSI_PRESENT_MODE=immediate # - disable vsync
-
-exec "$@"
-"""
-
- config = service._parse_script_content(script_content)
-
- assert config["enable_lsfg"] is False
- assert config["multiplier"] == 2
- assert config["flow_scale"] == 1.0
- assert config["hdr"] is False
- assert config["perf_mode"] is False
- assert config["immediate_mode"] is False
-
-
-def test_generate_script_content():
- """Test script content generation"""
- mock_logger = Mock()
-
- with tempfile.TemporaryDirectory() as temp_dir:
- temp_home = Path(temp_dir)
-
- service = ConfigurationService(logger=mock_logger)
- service.user_home = temp_home
- service.lsfg_script_path = temp_home / "lsfg"
-
- # Test with no toggles enabled
- config = {
- "enable_wow64": False,
- "disable_steamdeck_mode": False
- }
- content = service._generate_script_content(config)
-
- assert "#!/bin/bash" in content
- assert "export LSFG_PROCESS=decky-lsfg-vk" in content
- assert "export PROTON_USE_WOW64=1" not in content
- assert "export SteamDeck=0" not in content
- assert 'exec "$@"' in content
-
- # Test with both toggles enabled
- config = {
- "enable_wow64": True,
- "disable_steamdeck_mode": True
- }
- content = service._generate_script_content(config)
-
- assert "#!/bin/bash" in content
- assert "export PROTON_USE_WOW64=1" in content
- assert "export SteamDeck=0" in content
- assert "export LSFG_PROCESS=decky-lsfg-vk" in content
- assert 'exec "$@"' in content
-
-
-def test_config_roundtrip():
- """Test that we can write config and read it back correctly"""
- mock_logger = Mock()
-
- with tempfile.TemporaryDirectory() as temp_dir:
- temp_home = Path(temp_dir)
-
- service = ConfigurationService(logger=mock_logger)
- service.user_home = temp_home
- service.lsfg_script_path = temp_home / "lsfg"
-
- # Update config
- result = service.update_config(
- dll="/path/to/dll",
- multiplier=3,
- flow_scale=1.5,
- performance_mode=False,
- hdr_mode=True,
- experimental_present_mode="immediate",
- dxvk_frame_rate=30,
- enable_wow64=True,
- disable_steamdeck_mode=False
- )
-
- assert result["success"] is True
-
- # Read it back
- read_result = service.get_config()
-
- assert read_result["success"] is True
- config = read_result["config"]
- assert config["dll"] == "/path/to/dll"
- assert config["multiplier"] == 3
- assert config["flow_scale"] == 1.5
- assert config["performance_mode"] is False
- assert config["hdr_mode"] is True
- assert config["experimental_present_mode"] == "immediate"
- assert config["dxvk_frame_rate"] == 30
- assert config["enable_wow64"] is True
- assert config["disable_steamdeck_mode"] is False
-
- assert read_result["success"] is True
- config = read_result["config"]
-
- assert config["enable_lsfg"] is True
- assert config["multiplier"] == 3
- assert config["flow_scale"] == 1.5
- assert config["hdr"] is True
- assert config["perf_mode"] is False
- assert config["immediate_mode"] is True
diff --git a/tests/test_dll_detection.py b/tests/test_dll_detection.py
deleted file mode 100644
index e50d733..0000000
--- a/tests/test_dll_detection.py
+++ /dev/null
@@ -1,129 +0,0 @@
-"""
-Tests for the DLL detection service.
-"""
-
-import os
-import tempfile
-from pathlib import Path
-from unittest.mock import Mock, patch
-
-from lsfg_vk.dll_detection import DllDetectionService
-from lsfg_vk.constants import LOSSLESS_DLL_NAME
-
-
-def test_dll_detection_via_env_variable():
- """Test DLL detection via LSFG_DLL_PATH environment variable"""
- mock_logger = Mock()
-
- with tempfile.TemporaryDirectory() as temp_dir:
- # Create a fake DLL file
- dll_path = Path(temp_dir) / LOSSLESS_DLL_NAME
- dll_path.write_text("fake dll content")
-
- service = DllDetectionService(logger=mock_logger)
-
- # Test with environment variable set
- with patch.dict(os.environ, {"LSFG_DLL_PATH": str(dll_path)}):
- result = service.check_lossless_scaling_dll()
-
- assert result["detected"] is True
- assert result["path"] == str(dll_path)
- assert "LSFG_DLL_PATH" in result["source"]
- assert result["error"] is None
-
-
-def test_dll_detection_via_xdg_data_home():
- """Test DLL detection via XDG_DATA_HOME"""
- mock_logger = Mock()
-
- with tempfile.TemporaryDirectory() as temp_dir:
- # Create the expected directory structure
- steam_dir = Path(temp_dir) / "Steam" / "steamapps" / "common" / "Lossless Scaling"
- steam_dir.mkdir(parents=True)
-
- dll_path = steam_dir / LOSSLESS_DLL_NAME
- dll_path.write_text("fake dll content")
-
- service = DllDetectionService(logger=mock_logger)
-
- # Test with XDG_DATA_HOME set, no LSFG_DLL_PATH
- with patch.dict(os.environ, {"XDG_DATA_HOME": temp_dir}, clear=True):
- result = service.check_lossless_scaling_dll()
-
- assert result["detected"] is True
- assert result["path"] == str(dll_path)
- assert "XDG_DATA_HOME" in result["source"]
- assert result["error"] is None
-
-
-def test_dll_detection_via_home_local_share():
- """Test DLL detection via HOME/.local/share"""
- mock_logger = Mock()
-
- with tempfile.TemporaryDirectory() as temp_dir:
- # Create the expected directory structure
- steam_dir = Path(temp_dir) / ".local" / "share" / "Steam" / "steamapps" / "common" / "Lossless Scaling"
- steam_dir.mkdir(parents=True)
-
- dll_path = steam_dir / LOSSLESS_DLL_NAME
- dll_path.write_text("fake dll content")
-
- service = DllDetectionService(logger=mock_logger)
-
- # Test with HOME set, no other env vars
- env = {"HOME": temp_dir}
- with patch.dict(os.environ, env, clear=True):
- result = service.check_lossless_scaling_dll()
-
- assert result["detected"] is True
- assert result["path"] == str(dll_path)
- assert "HOME/.local/share" in result["source"]
- assert result["error"] is None
-
-
-def test_dll_detection_not_found():
- """Test DLL detection when DLL is not found"""
- mock_logger = Mock()
-
- service = DllDetectionService(logger=mock_logger)
-
- # Test with no environment variables set
- with patch.dict(os.environ, {}, clear=True):
- result = service.check_lossless_scaling_dll()
-
- assert result["detected"] is False
- assert result["path"] is None
- assert result["source"] is None
- assert "not found" in result["message"]
- assert result["error"] is None
-
-
-def test_dll_detection_priority():
- """Test that LSFG_DLL_PATH takes priority over other locations"""
- mock_logger = Mock()
-
- with tempfile.TemporaryDirectory() as temp_dir1, tempfile.TemporaryDirectory() as temp_dir2:
- # Create DLL in both locations
- dll_path1 = Path(temp_dir1) / LOSSLESS_DLL_NAME
- dll_path1.write_text("fake dll content 1")
-
- steam_dir = Path(temp_dir2) / "Steam" / "steamapps" / "common" / "Lossless Scaling"
- steam_dir.mkdir(parents=True)
- dll_path2 = steam_dir / LOSSLESS_DLL_NAME
- dll_path2.write_text("fake dll content 2")
-
- service = DllDetectionService(logger=mock_logger)
-
- # Set both environment variables
- env = {
- "LSFG_DLL_PATH": str(dll_path1),
- "XDG_DATA_HOME": temp_dir2
- }
-
- with patch.dict(os.environ, env, clear=True):
- result = service.check_lossless_scaling_dll()
-
- # Should prefer LSFG_DLL_PATH
- assert result["detected"] is True
- assert result["path"] == str(dll_path1)
- assert "LSFG_DLL_PATH" in result["source"]
diff --git a/tests/test_installation.py b/tests/test_installation.py
deleted file mode 100644
index 2b3690e..0000000
--- a/tests/test_installation.py
+++ /dev/null
@@ -1,150 +0,0 @@
-"""
-Tests for the installation service.
-"""
-
-import os
-import tempfile
-import zipfile
-from pathlib import Path
-from unittest.mock import Mock, patch
-
-import pytest
-from pyfakefs.fake_filesystem_unittest import TestCase
-
-from lsfg_vk.installation import InstallationService
-from lsfg_vk.constants import LIB_FILENAME, JSON_FILENAME, ZIP_FILENAME
-
-
-class TestInstallationService(TestCase):
- """Test cases for InstallationService using pyfakefs"""
-
- def setUp(self):
- """Set up fake filesystem"""
- self.setUpPyfakefs()
- self.mock_logger = Mock()
-
- # Create a test home directory
- self.test_home = Path("/home/testuser")
- self.fs.create_dir(self.test_home)
-
- # Patch Path.home() to return our test home
- with patch('lsfg_vk.base_service.Path.home', return_value=self.test_home):
- self.service = InstallationService(logger=self.mock_logger)
-
- def test_check_installation_no_files(self):
- """Test installation check when no files are installed"""
- result = self.service.check_installation()
-
- assert result["installed"] is False
- assert result["lib_exists"] is False
- assert result["json_exists"] is False
- assert result["script_exists"] is False
- assert result["error"] is None
-
- def test_check_installation_all_files_exist(self):
- """Test installation check when all files exist"""
- # Create the files
- self.service.lib_file.parent.mkdir(parents=True, exist_ok=True)
- self.service.lib_file.touch()
-
- self.service.json_file.parent.mkdir(parents=True, exist_ok=True)
- self.service.json_file.touch()
-
- self.service.lsfg_script_path.touch()
-
- result = self.service.check_installation()
-
- assert result["installed"] is True
- assert result["lib_exists"] is True
- assert result["json_exists"] is True
- assert result["script_exists"] is True
- assert result["error"] is None
-
- def test_create_zip_for_testing(self):
- """Helper to create a test zip file"""
- # Create temp directory for zip contents
- zip_content_dir = Path("/tmp/zip_content")
- self.fs.create_dir(zip_content_dir)
-
- # Create test files
- lib_file = zip_content_dir / LIB_FILENAME
- json_file = zip_content_dir / JSON_FILENAME
-
- lib_file.write_text("fake library content")
- json_file.write_text('{"layer": {"name": "VK_LAYER_LS_frame_generation"}}')
-
- # Create zip file
- zip_path = Path("/tmp/test.zip")
- with zipfile.ZipFile(zip_path, 'w') as zip_file:
- zip_file.write(lib_file, LIB_FILENAME)
- zip_file.write(json_file, JSON_FILENAME)
-
- return zip_path
-
- @patch('lsfg_vk.installation.Path.home')
- def test_install_success(self, mock_home):
- """Test successful installation"""
- mock_home.return_value = self.test_home
-
- # Create the plugin directory and zip file
- plugin_dir = Path("/plugin")
- bin_dir = plugin_dir / "bin"
- self.fs.create_dir(bin_dir)
-
- # Create a test zip file
- zip_path = self.test_create_zip_for_testing()
- zip_dest = bin_dir / ZIP_FILENAME
-
- # Copy our test zip to the expected location
- with open(zip_path, 'rb') as src, open(zip_dest, 'wb') as dst:
- dst.write(src.read())
-
- # Mock the plugin directory detection
- with patch('lsfg_vk.installation.Path.__file__', f"{plugin_dir}/lsfg_vk/installation.py"):
- result = self.service.install()
-
- assert result["success"] is True
- assert "successfully" in result["message"]
- assert result["error"] is None
-
- # Check that files were created
- assert self.service.lib_file.exists()
- assert self.service.json_file.exists()
- assert self.service.lsfg_script_path.exists()
-
- def test_uninstall_no_files(self):
- """Test uninstall when no files exist"""
- result = self.service.uninstall()
-
- assert result["success"] is True
- assert "No lsfg-vk files found" in result["message"]
- assert result["removed_files"] is None
-
- def test_uninstall_with_files(self):
- """Test uninstall when files exist"""
- # Create the files
- self.service.lib_file.parent.mkdir(parents=True, exist_ok=True)
- self.service.lib_file.touch()
-
- self.service.json_file.parent.mkdir(parents=True, exist_ok=True)
- self.service.json_file.touch()
-
- self.service.lsfg_script_path.touch()
-
- result = self.service.uninstall()
-
- assert result["success"] is True
- assert "uninstalled successfully" in result["message"]
- assert len(result["removed_files"]) == 3
-
- # Check that files were removed
- assert not self.service.lib_file.exists()
- assert not self.service.json_file.exists()
- assert not self.service.lsfg_script_path.exists()
-
-
-def test_installation_service_with_mock_logger():
- """Test that InstallationService accepts a mock logger"""
- mock_logger = Mock()
- service = InstallationService(logger=mock_logger)
- assert service.log == mock_logger