summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorxXJSONDeruloXx <danielhimebauch@gmail.com>2026-09-09 19:16:30 -0400
committerxXJSONDeruloXx <danielhimebauch@gmail.com>2026-09-09 20:20:58 -0400
commitcc1e6f47dd9838b066822162a607d2859c043aff (patch)
tree532915c1e98c068ab8324d71a0dab160bb53de68 /tests
parent102a4a0f0ce4af303a12e7f6f1a4454f4e572a17 (diff)
downloaddecky-lsfg-vk-cc1e6f47dd9838b066822162a607d2859c043aff.tar.gz
decky-lsfg-vk-cc1e6f47dd9838b066822162a607d2859c043aff.zip
refactor: unify flatpak targets with steam profiles
Diffstat (limited to 'tests')
-rw-r--r--tests/test_flatpak_overrides.py158
-rw-r--r--tests/test_flatpak_service.py231
-rw-r--r--tests/test_steam_service.py77
-rw-r--r--tests/test_wrapper_service.py79
4 files changed, 386 insertions, 159 deletions
diff --git a/tests/test_flatpak_overrides.py b/tests/test_flatpak_overrides.py
deleted file mode 100644
index ed3ef6a..0000000
--- a/tests/test_flatpak_overrides.py
+++ /dev/null
@@ -1,158 +0,0 @@
-import sys
-import tempfile
-import types
-import unittest
-from pathlib import Path
-from unittest.mock import Mock
-
-
-sys.modules.setdefault(
- "decky",
- types.SimpleNamespace(DECKY_USER_HOME="/home/deck", logger=Mock()),
-)
-sys.modules.setdefault("tomllib", types.SimpleNamespace(loads=Mock()))
-sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "py_modules"))
-
-from lsfg_vk.flatpak_service import FlatpakService
-
-
-class FlatpakOverrideTests(unittest.TestCase):
- def setUp(self):
- self.tempdir = tempfile.TemporaryDirectory()
- home = Path(self.tempdir.name) / "home" / "deck"
- home.mkdir(parents=True)
- self.service = FlatpakService()
- self.service.user_home = home
- self.service.config_dir = home / ".config/lsfg-vk"
- self.service.config_file_path = self.service.config_dir / "conf.toml"
- self.service.legacy_script_path = home / "lsfg"
- self.service.check_flatpak_available = Mock(return_value=True)
- self.service._run_flatpak_command = Mock(
- return_value=types.SimpleNamespace(returncode=0, stderr="", stdout="")
- )
- self.app_id = "com.example.Game"
- self.override_path = self.service._override_file_path(self.app_id)
-
- def tearDown(self):
- self.tempdir.cleanup()
- sys.modules.pop("lsfg_vk.plugin", None)
- sys.modules.pop("lsfg_vk", None)
-
- def _paths(self):
- return self.service._override_paths()
-
- def _write_override(self, content):
- self.override_path.parent.mkdir(parents=True, exist_ok=True)
- self.override_path.write_text(content, encoding="utf-8")
-
- def _show_response(self, content):
- return types.SimpleNamespace(returncode=0, stderr="", stdout=content)
-
- def test_set_cleans_legacy_entries_and_verifies_readback(self):
- paths = self._paths()
- self._write_override(
- "[Context]\n"
- f"filesystems=/home/deck/keep;{paths['config_dir']}:rw;!{paths['legacy_home']};"
- f"{paths['legacy_script']};{paths['legacy_dll']}:ro;{paths['dll_dir']}:ro;\n"
- "unset-environment=KEEP_UNSET;LSFG_CONFIG;\n\n"
- "[Environment]\n"
- "KEEP_ENV=1\n"
- "LSFG_CONFIG=\n"
- "LSFGVK_CONFIG=old\n"
- "ENABLE_GAMESCOPE_WSI=1\n"
- "DXVK_HDR=1\n"
- )
- expected = (
- "[Context]\n"
- f"filesystems={paths['config_dir']}:rw;{paths['dll_dir']}:ro\n"
- "[Environment]\n"
- f"LSFGVK_CONFIG={paths['config_file']}\n"
- "ENABLE_GAMESCOPE_WSI=0\n"
- "DXVK_HDR=0\n"
- )
- self.service._run_flatpak_command.side_effect = [
- self._show_response(""),
- self._show_response(expected),
- ]
-
- response = self.service.set_app_override(self.app_id)
- command_args = self.service._run_flatpak_command.call_args_list[0].args[0]
- cleaned = self.override_path.read_text(encoding="utf-8")
-
- self.assertTrue(response["success"])
- self.assertIn("--env=ENABLE_GAMESCOPE_WSI=0", command_args)
- self.assertIn("--env=DXVK_HDR=0", command_args)
- self.assertNotIn("--nofilesystem=/home/deck", command_args)
- self.assertNotIn("--unset-env=LSFG_CONFIG", command_args)
- self.assertIn("/home/deck/keep", cleaned)
- self.assertIn("KEEP_ENV=1", cleaned)
- self.assertNotIn("LSFG_CONFIG", cleaned)
- self.assertNotIn(paths["legacy_home"], cleaned)
-
- def test_set_reports_failed_readback(self):
- paths = self._paths()
- self.service._run_flatpak_command.side_effect = [
- self._show_response(""),
- self._show_response(
- f"[Context]\nfilesystems={paths['config_dir']};{paths['dll_dir']}\n"
- f"[Environment]\nLSFGVK_CONFIG={paths['config_file']}\n"
- ),
- ]
-
- response = self.service.set_app_override(self.app_id)
-
- self.assertFalse(response["success"])
- self.assertIn("verified", response["error"])
-
- def test_remove_cleans_known_entries_preserves_unrelated_and_verifies(self):
- paths = self._paths()
- self._write_override(
- "[Context]\n"
- f"filesystems=/home/deck/keep;{paths['config_dir']};!{paths['legacy_home']};"
- f"{paths['legacy_dll']};{paths['legacy_script']}\n"
- "unset-environment=KEEP_UNSET;LSFG_CONFIG;ENABLE_GAMESCOPE_WSI\n\n"
- "[Environment]\n"
- "KEEP_ENV=1\n"
- "LSFGVK_CONFIG=/old/path\n"
- "DXVK_HDR=0\n"
- )
- self.service._run_flatpak_command.side_effect = [
- self._show_response(
- "[Context]\nfilesystems=/home/deck/keep\n"
- "[Environment]\nKEEP_ENV=1\n"
- )
- ]
-
- response = self.service.remove_app_override(self.app_id)
- cleaned = self.override_path.read_text(encoding="utf-8")
-
- self.assertTrue(response["success"])
- self.assertEqual(self.service._run_flatpak_command.call_count, 1)
- self.assertIn("/home/deck/keep", cleaned)
- self.assertIn("KEEP_UNSET", cleaned)
- self.assertIn("KEEP_ENV", cleaned)
- for name in ("LSFGVK_CONFIG", "LSFG_CONFIG", "ENABLE_GAMESCOPE_WSI", "DXVK_HDR"):
- self.assertNotIn(name, cleaned)
- for path in paths.values():
- if path != paths["config_file"]:
- self.assertNotIn(path, cleaned)
-
- def test_remove_reports_failed_readback(self):
- self._write_override("[Context]\nfilesystems=/home/deck/keep\n")
- paths = self._paths()
- self.service._run_flatpak_command.side_effect = [
- self._show_response(
- f"[Context]\nfilesystems={paths['config_dir']};{paths['dll_dir']}\n"
- f"[Environment]\nLSFGVK_CONFIG={paths['config_file']}\n"
- "ENABLE_GAMESCOPE_WSI=0\nDXVK_HDR=0\n"
- )
- ]
-
- response = self.service.remove_app_override(self.app_id)
-
- self.assertFalse(response["success"])
- self.assertIn("verified", response["error"])
-
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/tests/test_flatpak_service.py b/tests/test_flatpak_service.py
new file mode 100644
index 0000000..38dfcb5
--- /dev/null
+++ b/tests/test_flatpak_service.py
@@ -0,0 +1,231 @@
+import json
+import sys
+import tempfile
+import types
+import unittest
+from pathlib import Path
+from unittest.mock import Mock
+
+
+sys.modules.setdefault(
+ "decky",
+ types.SimpleNamespace(DECKY_USER_HOME="/home/deck", logger=Mock()),
+)
+sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "py_modules"))
+
+from lsfg_vk.flatpak_service import FlatpakService
+
+
+class FlatpakServiceTests(unittest.TestCase):
+ def setUp(self):
+ self.tempdir = tempfile.TemporaryDirectory()
+ self.home = Path(self.tempdir.name) / "home" / "deck"
+ self.home.mkdir(parents=True)
+ self.service = FlatpakService()
+ self.service.user_home = self.home
+ self.service.config_dir = self.home / ".config/lsfg-vk"
+ self.service.config_file_path = self.service.config_dir / "conf.toml"
+ self.service.check_flatpak_available = Mock(return_value=True)
+ self.service._run_flatpak_command = Mock()
+ self.bundle = self.home / "lsfg-vk-24.08.flatpak"
+ self.bundle.write_bytes(b"bundle")
+ self.service._bundled_extension_path = Mock(return_value=self.bundle)
+
+ def tearDown(self):
+ self.tempdir.cleanup()
+
+ @staticmethod
+ def _result(stdout="", returncode=0, stderr=""):
+ return types.SimpleNamespace(stdout=stdout, returncode=returncode, stderr=stderr)
+
+ @staticmethod
+ def _extension_line(branch):
+ return f"org.freedesktop.Platform.VulkanLayer.lsfgvk\tx86_64\t{branch}\n"
+
+ def test_runtime_branch_mapping_is_strict_and_branch_specific(self):
+ self.assertEqual(
+ FlatpakService.runtime_branch_from_ref(
+ "org.freedesktop.Platform/x86_64/24.08"
+ ),
+ "24.08",
+ )
+ self.assertEqual(
+ FlatpakService.runtime_branch_from_ref(
+ "org.freedesktop.Platform//25.08"
+ ),
+ "25.08",
+ )
+ with self.assertRaises(ValueError):
+ FlatpakService.runtime_branch_from_ref("org.gnome.Sdk/x86_64/46")
+ with self.assertRaises(ValueError):
+ FlatpakService.runtime_branch_from_ref(
+ "org.freedesktop.Platform/x86_64/26.08"
+ )
+
+ def test_resolve_reads_required_runtime_instead_of_any_installed_branch(self):
+ self.service._run_flatpak_command.side_effect = [
+ self._result("org.freedesktop.Platform/x86_64/24.08\n"),
+ self._result(self._extension_line("23.08")),
+ ]
+
+ response = self.service.resolve_app_support("com.example.Game")
+
+ self.assertTrue(response["success"])
+ self.assertEqual(response["runtime_branch"], "24.08")
+ self.assertEqual(response["support_status"], "needs-runtime")
+ self.assertFalse(response["extension_installed"])
+ self.assertEqual(
+ self.service._run_flatpak_command.call_args_list[0].args[0],
+ ["info", "--show-runtime", "com.example.Game"],
+ )
+ self.assertEqual(
+ self.service._run_flatpak_command.call_args_list[1].args[0],
+ ["list", "--runtime", "--columns=application,arch,branch"],
+ )
+
+ def test_install_records_only_a_new_user_owned_branch(self):
+ self.service._run_flatpak_command.side_effect = [
+ self._result(""),
+ self._result(""),
+ self._result(self._extension_line("24.08")),
+ ]
+
+ response = self.service.install_extension("24.08")
+
+ self.assertTrue(response["success"])
+ self.assertTrue(response["owned_by_plugin"])
+ install_args = self.service._run_flatpak_command.call_args_list[1].args[0]
+ self.assertEqual(install_args[:4], ["install", "--user", "--noninteractive", "--or-update"])
+ self.assertEqual(
+ json.loads(self.service.ownership_path.read_text(encoding="utf-8")),
+ {"version": 1, "plugin_owned_branches": ["24.08"]},
+ )
+
+ def test_preexisting_branch_is_not_claimed_or_removed(self):
+ self.service._run_flatpak_command.return_value = self._result(
+ self._extension_line("24.08")
+ )
+
+ install_response = self.service.install_extension("24.08")
+ cleanup_response = self.service.remove_plugin_owned_extensions()
+
+ self.assertTrue(install_response["success"])
+ self.assertFalse(install_response["owned_by_plugin"])
+ self.assertFalse(self.service.ownership_path.exists())
+ self.assertTrue(cleanup_response["success"])
+ self.assertEqual(self.service._run_flatpak_command.call_count, 1)
+
+ def test_corrupt_ownership_metadata_fails_closed(self):
+ self.service.ownership_path.parent.mkdir(parents=True, exist_ok=True)
+ self.service.ownership_path.write_text("{not-json", encoding="utf-8")
+
+ response = self.service.remove_plugin_owned_extensions()
+
+ self.assertFalse(response["success"])
+ self.assertTrue(response["ownership_uncertain"])
+ self.assertEqual(self.service._run_flatpak_command.call_count, 0)
+
+ def test_dangling_ownership_symlink_fails_closed(self):
+ self.service.ownership_path.parent.mkdir(parents=True, exist_ok=True)
+ self.service.ownership_path.symlink_to(self.home / "missing-metadata")
+
+ response = self.service.remove_plugin_owned_extensions()
+
+ self.assertFalse(response["success"])
+ self.assertTrue(response["ownership_uncertain"])
+ self.assertEqual(self.service._run_flatpak_command.call_count, 0)
+
+ def test_ensure_app_support_installs_only_the_app_runtime_branch(self):
+ self.service._run_flatpak_command.side_effect = [
+ self._result("org.freedesktop.Platform/x86_64/24.08\n"),
+ self._result(""),
+ self._result(""),
+ self._result(""),
+ self._result(""),
+ self._result(self._extension_line("24.08")),
+ self._result("org.freedesktop.Platform/x86_64/24.08\n"),
+ self._result(self._extension_line("24.08")),
+ ]
+
+ response = self.service.ensure_app_support("com.example.Game")
+
+ self.assertTrue(response["success"])
+ self.assertEqual(response["support_status"], "ready")
+ self.assertEqual(response["runtime_branch"], "24.08")
+ install_args = self.service._run_flatpak_command.call_args_list[4].args[0]
+ self.assertEqual(install_args[0], "install")
+ self.assertIn("--user", install_args)
+ self.assertNotIn("23.08", install_args)
+ self.assertEqual(
+ json.loads(self.service.ownership_path.read_text(encoding="utf-8")),
+ {"version": 1, "plugin_owned_branches": ["24.08"]},
+ )
+
+ def test_two_shortcuts_using_one_flatpak_share_one_extension_branch(self):
+ self.service._run_flatpak_command.side_effect = [
+ self._result("org.freedesktop.Platform/x86_64/24.08\n"),
+ self._result(""),
+ self._result(""),
+ self._result(""),
+ self._result(""),
+ self._result(self._extension_line("24.08")),
+ self._result("org.freedesktop.Platform/x86_64/24.08\n"),
+ self._result(self._extension_line("24.08")),
+ self._result("org.freedesktop.Platform/x86_64/24.08\n"),
+ self._result(self._extension_line("24.08")),
+ ]
+
+ first = self.service.ensure_app_support("net.pcsx2.PCSX2")
+ second = self.service.ensure_app_support("net.pcsx2.PCSX2.Dev")
+
+ self.assertEqual(first["support_status"], "ready")
+ self.assertEqual(second["support_status"], "ready")
+ install_commands = [
+ call.args[0]
+ for call in self.service._run_flatpak_command.call_args_list
+ if call.args[0][0] == "install"
+ ]
+ self.assertEqual(len(install_commands), 1)
+ self.assertEqual(
+ json.loads(self.service.ownership_path.read_text(encoding="utf-8")),
+ {"version": 1, "plugin_owned_branches": ["24.08"]},
+ )
+
+ def test_cleanup_removes_all_owned_branches_without_reusing_stale_metadata(self):
+ self.service.ownership_path.parent.mkdir(parents=True, exist_ok=True)
+ self.service.ownership_path.write_text(
+ json.dumps({"version": 1, "plugin_owned_branches": ["23.08", "24.08"]}),
+ encoding="utf-8",
+ )
+ self.service._run_flatpak_command.side_effect = [
+ self._result(
+ "\n".join(
+ [
+ "\t".join([FlatpakService.EXTENSION_ID, "x86_64", "23.08"]),
+ "\t".join([FlatpakService.EXTENSION_ID, "x86_64", "24.08"]),
+ ]
+ )
+ + "\n"
+ ),
+ self._result(""),
+ self._result("\t".join([FlatpakService.EXTENSION_ID, "x86_64", "24.08"]) + "\n"),
+ self._result("\t".join([FlatpakService.EXTENSION_ID, "x86_64", "24.08"]) + "\n"),
+ self._result(""),
+ self._result(""),
+ ]
+
+ response = self.service.remove_plugin_owned_extensions()
+
+ self.assertTrue(response["success"])
+ self.assertEqual(response["removed_branches"], ["23.08", "24.08"])
+ self.assertFalse(self.service.ownership_path.exists())
+ uninstall_commands = [
+ call.args[0]
+ for call in self.service._run_flatpak_command.call_args_list
+ if call.args[0][0] == "uninstall"
+ ]
+ self.assertEqual(len(uninstall_commands), 2)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_steam_service.py b/tests/test_steam_service.py
new file mode 100644
index 0000000..849bb01
--- /dev/null
+++ b/tests/test_steam_service.py
@@ -0,0 +1,77 @@
+import sys
+import types
+import unittest
+from pathlib import Path
+from unittest.mock import Mock
+
+
+sys.modules.setdefault(
+ "decky",
+ types.SimpleNamespace(DECKY_USER_HOME="/home/deck", logger=Mock()),
+)
+sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "py_modules"))
+
+from lsfg_vk.steam_service import SteamService, classify_shortcut_transport
+
+
+class SteamTransportTests(unittest.TestCase):
+ def test_only_direct_canonical_flatpak_forms_are_classified(self):
+ self.assertEqual(
+ classify_shortcut_transport(
+ "/usr/bin/flatpak",
+ "run com.example.PCSX2 --fullscreen",
+ ),
+ {"kind": "flatpak", "flatpakAppId": "com.example.PCSX2"},
+ )
+ self.assertEqual(
+ classify_shortcut_transport(
+ "/usr/bin/flatpak run com.example.PCSX2",
+ "--fullscreen",
+ ),
+ {"kind": "flatpak", "flatpakAppId": "com.example.PCSX2"},
+ )
+ self.assertEqual(
+ classify_shortcut_transport(
+ "/usr/bin/bash",
+ "~/launch-game.sh --fullscreen",
+ ),
+ {"kind": "host"},
+ )
+ self.assertEqual(
+ classify_shortcut_transport(
+ "/usr/bin/flatpak",
+ "--user run com.example.PCSX2",
+ ),
+ {"kind": "host"},
+ )
+ self.assertEqual(
+ classify_shortcut_transport(
+ "/usr/bin/flatpak",
+ "run bash ~/launch-game.sh",
+ ),
+ {"kind": "host"},
+ )
+
+ def test_shortcut_data_preserves_transport_inputs(self):
+ game = SteamService._shortcut_game(
+ {
+ "appid": 123456,
+ "AppName": "PCSX2 shortcut",
+ "Exe": "/usr/bin/flatpak",
+ "LaunchOptions": "run net.pcsx2.PCSX2 --fullscreen",
+ "StartDir": "/home/deck/Games",
+ }
+ )
+
+ self.assertEqual(game["appid"], "123456")
+ self.assertEqual(game["transport"], {
+ "kind": "flatpak",
+ "flatpakAppId": "net.pcsx2.PCSX2",
+ })
+ self.assertEqual(game["executable"], "/usr/bin/flatpak")
+ self.assertEqual(game["arguments"], "run net.pcsx2.PCSX2 --fullscreen")
+ self.assertEqual(game["startDir"], "/home/deck/Games")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/test_wrapper_service.py b/tests/test_wrapper_service.py
index f17a944..5010d23 100644
--- a/tests/test_wrapper_service.py
+++ b/tests/test_wrapper_service.py
@@ -123,10 +123,20 @@ class WrapperServiceTests(unittest.TestCase):
encoding="utf-8",
)
fake_flatpak.chmod(0o755)
- self.service.set("123", self._state(dxvkFrameRate=20, enableZink=True), str(fake_flatpak))
+ self.service.set(
+ "123",
+ self._state(dxvkFrameRate=20, enableZink=True),
+ str(fake_flatpak),
+ False,
+ {"kind": "flatpak", "flatpakAppId": "com.example.Game"},
+ )
result = self._run(123, "run", "com.example.Game", "--windowed", env={"DXVK_CONFIG": "foo=1"})
args = result.stdout.splitlines()
self.assertEqual(args[0], "ARG:run")
+ self.assertIn("ARG:--filesystem=" + str(self.service.config_dir) + ":rw", args)
+ self.assertIn("ARG:--filesystem=" + str(self.home / ".local/share/Steam/steamapps/common/Lossless Scaling") + ":ro", args)
+ self.assertIn("ARG:--env=LSFGVK_CONFIG=" + str(self.service.config_file_path), args)
+ self.assertIn("ARG:--env=LSFGVK_FLATPAK=1", args)
self.assertIn("ARG:--env=SteamAppId=123", args)
self.assertIn("ARG:--env=ENABLE_GAMESCOPE_WSI=0", args)
self.assertIn("ARG:--env=DXVK_HDR=0", args)
@@ -137,6 +147,73 @@ class WrapperServiceTests(unittest.TestCase):
self.assertIn("ARG:com.example.Game", args)
self.assertIn("ARG:--windowed", args)
+ def test_flatpak_full_executable_form_is_preserved(self):
+ fake_flatpak = self.home / ".local/bin/flatpak"
+ fake_flatpak.parent.mkdir(parents=True, exist_ok=True)
+ fake_flatpak.write_text(
+ "#!/bin/sh\n"
+ "printf 'ARG:%s\\n' \"$@\"\n",
+ encoding="utf-8",
+ )
+ fake_flatpak.chmod(0o755)
+ response = self.service.set(
+ "123",
+ self._state(),
+ f"{fake_flatpak} run com.example.Game",
+ False,
+ {"kind": "flatpak", "flatpakAppId": "com.example.Game"},
+ )
+ self.assertTrue(response["success"])
+ result = self._run(123, "--windowed")
+ args = result.stdout.splitlines()
+ self.assertEqual(args[0], "ARG:run")
+ self.assertIn("ARG:com.example.Game", args)
+ self.assertIn("ARG:--windowed", args)
+
+ def test_flatpak_transport_rejects_non_run_invocation(self):
+ fake_flatpak = self.home / ".local/bin/flatpak"
+ fake_flatpak.parent.mkdir(parents=True, exist_ok=True)
+ fake_flatpak.write_text("#!/bin/sh\nexit 0\n", encoding="utf-8")
+ fake_flatpak.chmod(0o755)
+ response = self.service.set(
+ "123",
+ self._state(),
+ str(fake_flatpak),
+ False,
+ {"kind": "flatpak", "flatpakAppId": "com.example.Game"},
+ )
+ self.assertTrue(response["success"])
+ result = subprocess.run(
+ [str(self.service.wrapper_path), "bash", "launch-game.sh"],
+ env={"PATH": "/usr/bin:/bin", "SteamAppId": "123"},
+ capture_output=True,
+ text=True,
+ )
+ self.assertEqual(result.returncode, 64)
+ self.assertIn("direct flatpak run", result.stderr)
+
+ def test_flatpak_transport_rejects_external_app_id_change(self):
+ fake_flatpak = self.home / ".local/bin/flatpak"
+ fake_flatpak.parent.mkdir(parents=True, exist_ok=True)
+ fake_flatpak.write_text("#!/bin/sh\nexit 0\n", encoding="utf-8")
+ fake_flatpak.chmod(0o755)
+ response = self.service.set(
+ "123",
+ self._state(),
+ str(fake_flatpak),
+ False,
+ {"kind": "flatpak", "flatpakAppId": "com.example.Game"},
+ )
+ self.assertTrue(response["success"])
+ result = subprocess.run(
+ [str(self.service.wrapper_path), "run", "com.other.Game"],
+ env={"PATH": "/usr/bin:/bin", "SteamAppId": "123"},
+ capture_output=True,
+ text=True,
+ )
+ self.assertEqual(result.returncode, 64)
+ self.assertIn("application ID changed externally", result.stderr)
+
def test_invalid_state_and_foreign_wrapper_fail_closed(self):
invalid = self.service.set("0", self.service.default_state())
self.assertFalse(invalid["success"])