Files
DroidDeck/tools/tests/test_flatpak_bundle_arch.py
T
MaxsTechReview 28067b3bbe Run x86_64 Flatpak apps through FEX (#1875)
* 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
2026-10-30 21:21:22 -04:00

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()