mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-11 02:51:10 +00:00
FEX builds can reach devices without an app release: while the x86-64 client is selected the app reads DroidDeck-Components' fex.json (directly, on its own thread, not in Offline Mode) and a session passes that build to droiddeck-steam-x64, which installs it only once its sha256 matches and its programs load, keeping the replaced files aside until the installed copy loads too; it keeps a working installed build otherwise and falls back to the build it pins. FEX is built and published by Components' build-fex.yml on its single fex release; this repository's build-fex.yml only checks the build. x86-64 session logs name the FEX build and its source, the rootfs and the client's builds, report the rootfs download in tenths, and say in one line when the web helper's GPU process keeps exiting, with x86 glxinfo and vulkaninfo through FEX. Settings shows the FEX build installed.
92 lines
4.2 KiB
Python
92 lines
4.2 KiB
Python
import hashlib
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import tempfile
|
|
import textwrap
|
|
import unittest
|
|
|
|
SCRIPT = Path(__file__).resolve().parents[1] / "linuxfs/overlay/usr/local/bin/droiddeck-steam-x64"
|
|
SOURCE = SCRIPT.read_text()
|
|
START = SOURCE.index("fex_install() {")
|
|
END = SOURCE.index("\n}\n", START) + 3
|
|
FEX_INSTALL = SOURCE[START:END]
|
|
|
|
HARNESS = textwrap.dedent("""\
|
|
set -eu
|
|
# The archive comes from PKG; the installed tree loads when INSTALLED_LOADS=1, any staged tree always does.
|
|
curl() { local out=; while [ $# -gt 0 ]; do [ "$1" = -o ] && out=$2; shift; done; cp "$PKG" "$out"; }
|
|
fex_loads() { case $1 in "$ROOT"/) [ "${INSTALLED_LOADS:-1}" = 1 ] ;; *) true ;; esac; }
|
|
""")
|
|
|
|
|
|
class FexInstallTest(unittest.TestCase):
|
|
def setUp(self):
|
|
self.temp = tempfile.TemporaryDirectory()
|
|
self.addCleanup(self.temp.cleanup)
|
|
base = Path(self.temp.name)
|
|
self.root = base / "root"
|
|
old = self.root / "usr/local"
|
|
(old / "bin").mkdir(parents=True)
|
|
(old / "bin/FEX").write_text("old FEX\n")
|
|
(old / "share/fex-emu").mkdir(parents=True)
|
|
(old / "share/fex-emu/.droiddeck-tag").write_text("fex-2610-r5\n")
|
|
new = base / "pkg/usr/local"
|
|
(new / "bin").mkdir(parents=True)
|
|
(new / "bin/FEX").write_text("new FEX\n")
|
|
(new / "lib").mkdir()
|
|
(new / "lib/libxxhash.so.0").write_text("lib\n")
|
|
self.pkg = base / "fex.tzst"
|
|
subprocess.run(f"tar -C '{base / 'pkg'}' -c . | zstd -q -o '{self.pkg}'", shell=True, check=True)
|
|
self.sha = hashlib.sha256(self.pkg.read_bytes()).hexdigest()
|
|
|
|
def install(self, installed_loads, sha=None):
|
|
body = FEX_INSTALL.replace("local tag=$1 sha=$2 urls=$3 dst=/ ", "local tag=$1 sha=$2 urls=$3 dst=$ROOT/ ")
|
|
self.assertNotEqual(body, FEX_INSTALL)
|
|
script = HARNESS + body + 'if fex_install fex-2610-r6 "$SHA" u; then echo OK; else echo FAILED; fi\n'
|
|
env = dict(os.environ, ROOT=str(self.root), PKG=str(self.pkg), SHA=sha or self.sha,
|
|
INSTALLED_LOADS="1" if installed_loads else "0")
|
|
out = subprocess.run(["bash", "-c", script], env=env, text=True, capture_output=True, timeout=30)
|
|
self.assertEqual(0, out.returncode, out.stderr)
|
|
return out.stdout.strip().splitlines()[-1], out.stderr
|
|
|
|
def tag(self):
|
|
return (self.root / "usr/local/share/fex-emu/.droiddeck-tag").read_text().strip()
|
|
|
|
def test_a_build_that_loads_once_installed_replaces_the_old_one(self):
|
|
result, _ = self.install(installed_loads=True)
|
|
self.assertEqual("OK", result)
|
|
self.assertEqual("new FEX\n", (self.root / "usr/local/bin/FEX").read_text())
|
|
self.assertTrue((self.root / "usr/local/lib/libxxhash.so.0").is_file())
|
|
self.assertEqual("fex-2610-r6", self.tag())
|
|
|
|
def test_an_installed_copy_that_does_not_load_puts_the_old_files_back(self):
|
|
result, err = self.install(installed_loads=False)
|
|
self.assertEqual("FAILED", result)
|
|
self.assertIn("putting the previous files back", err)
|
|
self.assertEqual("old FEX\n", (self.root / "usr/local/bin/FEX").read_text())
|
|
self.assertFalse((self.root / "usr/local/lib/libxxhash.so.0").exists())
|
|
self.assertEqual("fex-2610-r5", self.tag())
|
|
|
|
def test_a_tag_that_cannot_be_written_puts_the_old_files_back(self):
|
|
share = self.root / "usr/local/share/fex-emu"
|
|
(share / ".droiddeck-tag").unlink()
|
|
share.rmdir()
|
|
share.write_text("not a folder\n")
|
|
result, err = self.install(installed_loads=True)
|
|
self.assertEqual("FAILED", result)
|
|
self.assertIn("putting the previous files back", err)
|
|
self.assertEqual("old FEX\n", (self.root / "usr/local/bin/FEX").read_text())
|
|
self.assertFalse((self.root / "usr/local/lib/libxxhash.so.0").exists())
|
|
|
|
def test_an_archive_that_does_not_match_installs_nothing(self):
|
|
result, err = self.install(installed_loads=True, sha="0" * 64)
|
|
self.assertEqual("FAILED", result)
|
|
self.assertIn("no source gave the archive", err)
|
|
self.assertEqual("old FEX\n", (self.root / "usr/local/bin/FEX").read_text())
|
|
self.assertEqual("fex-2610-r5", self.tag())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|