mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-11 11:01:07 +00:00
* Run x86_64 Flatpak apps through FEX * proot: run an execveat with an absolute path like execve * Find x86_64 Flatpak installs and resolve sandbox paths like the sandbox does
137 lines
4.6 KiB
Python
137 lines
4.6 KiB
Python
import importlib.machinery
|
|
import importlib.util
|
|
import io
|
|
import json
|
|
from pathlib import Path
|
|
import sys
|
|
import types
|
|
import unittest
|
|
from contextlib import redirect_stdout
|
|
|
|
SCRIPT = Path(__file__).resolve().parents[1] / "linuxfs/overlay/usr/local/bin/droiddeck-flatpak"
|
|
|
|
|
|
class FakeRef:
|
|
def __init__(self, arch):
|
|
self.arch = arch
|
|
|
|
def get_name(self):
|
|
return "io.github.ebkr.r2modman"
|
|
|
|
def get_arch(self):
|
|
return self.arch
|
|
|
|
|
|
def load(bundle_arch, installs):
|
|
flatpak = types.SimpleNamespace(
|
|
get_default_arch=lambda: "aarch64",
|
|
BundleRef=types.SimpleNamespace(new=lambda bundle: FakeRef(bundle_arch)),
|
|
)
|
|
repository = types.ModuleType("gi.repository")
|
|
repository.Flatpak = flatpak
|
|
repository.Gio = types.SimpleNamespace(File=types.SimpleNamespace(new_for_path=lambda path: path))
|
|
repository.GLib = types.SimpleNamespace(Error=RuntimeError)
|
|
gi = types.ModuleType("gi")
|
|
gi.require_version = lambda *args: None
|
|
gi.repository = repository
|
|
saved = {name: sys.modules.get(name) for name in ("gi", "gi.repository")}
|
|
sys.modules["gi"] = gi
|
|
sys.modules["gi.repository"] = repository
|
|
try:
|
|
loader = importlib.machinery.SourceFileLoader("droiddeck_flatpak", str(SCRIPT))
|
|
module = importlib.util.module_from_spec(importlib.util.spec_from_loader(loader.name, loader))
|
|
loader.exec_module(module)
|
|
finally:
|
|
for name, value in saved.items():
|
|
if value is None:
|
|
sys.modules.pop(name, None)
|
|
else:
|
|
sys.modules[name] = value
|
|
module.installation = lambda: object()
|
|
module.app_ref = lambda inst, app_id: None
|
|
|
|
def transaction(inst):
|
|
installs.append("bundle")
|
|
raise AssertionError("the bundle reached a transaction")
|
|
|
|
module.transaction = transaction
|
|
return module
|
|
|
|
|
|
class FlatpakBundleArchTest(unittest.TestCase):
|
|
def run_install(self, arch):
|
|
installs = []
|
|
module = load(arch, installs)
|
|
out = io.StringIO()
|
|
with redirect_stdout(out):
|
|
try:
|
|
rc = module.install_bundle("/tmp/r2modman.flatpak")
|
|
except AssertionError:
|
|
rc = None
|
|
return rc, [json.loads(line) for line in out.getvalue().splitlines()], installs
|
|
|
|
def test_a_bundle_for_an_architecture_fex_cannot_run_is_refused_before_installing(self):
|
|
rc, events, installs = self.run_install("riscv64")
|
|
self.assertEqual(rc, 1)
|
|
self.assertEqual(installs, [])
|
|
self.assertEqual(events[0]["e"], "error")
|
|
self.assertEqual(events[0]["code"], "arch")
|
|
self.assertEqual(events[0]["arch"], "riscv64")
|
|
self.assertEqual(events[0]["id"], "io.github.ebkr.r2modman")
|
|
|
|
def test_a_bundle_for_this_device_goes_on_to_install(self):
|
|
rc, events, installs = self.run_install("aarch64")
|
|
self.assertEqual(installs, ["bundle"])
|
|
self.assertEqual(events, [])
|
|
|
|
def test_an_x86_64_bundle_goes_on_to_install_for_fex(self):
|
|
rc, events, installs = self.run_install("x86_64")
|
|
self.assertEqual(installs, ["bundle"])
|
|
self.assertEqual(events, [])
|
|
|
|
def test_flathub_falls_back_to_the_x86_64_build(self):
|
|
module = load("aarch64", [])
|
|
asked = []
|
|
|
|
class Remote:
|
|
def __init__(self, branch):
|
|
self.branch = branch
|
|
|
|
def get_branch(self):
|
|
return self.branch
|
|
|
|
class Installation:
|
|
def fetch_remote_ref_sync(self, remote, kind, app_id, arch, branch, cancellable):
|
|
asked.append((arch, branch))
|
|
if arch == "x86_64" and branch == "stable":
|
|
return Remote("stable")
|
|
raise RuntimeError("not found")
|
|
|
|
added = []
|
|
|
|
class Transaction:
|
|
def add_install(self, remote, ref, subpaths):
|
|
added.append(ref)
|
|
|
|
module.Flatpak.RefKind = types.SimpleNamespace(APP=0)
|
|
module.installation = lambda: Installation()
|
|
installed = []
|
|
module.app_ref = lambda inst, app_id: (installed[0] if installed else None)
|
|
module.transaction = lambda inst: (Transaction(), {})
|
|
|
|
def run(t, state, report_done=True):
|
|
installed.append(object())
|
|
return 0
|
|
|
|
module.run = run
|
|
out = io.StringIO()
|
|
with redirect_stdout(out):
|
|
rc = module.install("io.github.ebkr.r2modman")
|
|
self.assertEqual(rc, 0)
|
|
self.assertEqual(asked, [("aarch64", "stable"), ("aarch64", "master"), ("x86_64", "stable")])
|
|
self.assertEqual(added, ["app/io.github.ebkr.r2modman/x86_64/stable"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|