Files
spoopyghosty0--frameport/tests/test_linux_apps.py
T

109 lines
4.3 KiB
Python

"""Native arm64 Linux apps (GitHub #31): detection of AppImages, folders and archives."""
import tarfile
import zipfile
import pytest
from frameport import pipeline
from frameport.analysis import linux
def elf(machine: int, appimage: bool = False, extra: bytes = b"") -> bytes:
head = bytearray(64)
head[:4] = b"\x7fELF"
head[4], head[5] = 2, 1 # 64-bit, little endian
if appimage:
head[8:11] = b"AI\x02"
head[18:20] = machine.to_bytes(2, "little")
return bytes(head) + extra
def test_appimage_detection_and_title(tmp_path):
p = tmp_path / "Venera-Prime-2.4.2-aarch64.AppImage"
p.write_bytes(elf(linux.EM_AARCH64, appimage=True))
info = linux.inspect(p)
assert info["appimage"] and info["arch_ok"] and info["files"] == [p.name] and info["title"] == "Venera Prime"
assert not info["openxr"]
def test_x86_64_builds_are_refused(tmp_path):
p = tmp_path / "Thing-1.0-x86_64.AppImage"
p.write_bytes(elf(linux.EM_X86_64, appimage=True))
with pytest.raises(ValueError, match="x86_64"):
pipeline.add_linux_app(p)
def test_archive_program_ranking_and_openxr(tmp_path):
src = tmp_path / "src" / "MatineeVR"
(src / "lib").mkdir(parents=True)
(src / "MatineeVR").write_bytes(elf(linux.EM_AARCH64))
(src / "crashpad_handler").write_bytes(elf(linux.EM_AARCH64))
(src / "lib" / "libopenxr_loader.so.1").write_bytes(elf(linux.EM_AARCH64, extra=b"xrCreateInstance"))
(src / "data" / "deep").mkdir(parents=True)
archive = tmp_path / "MatineeVR-0.8-linux-arm64.tar.gz"
with tarfile.open(archive, "w:gz") as t:
t.add(src, arcname="MatineeVR")
info = linux.inspect(archive)
assert info["exe"] == "MatineeVR/MatineeVR" and info["openxr"] and info["arch_ok"]
assert linux.inspect(archive)["root"] == info["root"] # unpacked once
def test_bundled_data_libraries_dont_make_an_app_vr(tmp_path):
root = tmp_path / "FramePort"
(root / "data" / "artifacts" / "arm64-v8a").mkdir(parents=True)
(root / "FramePort").write_bytes(elf(linux.EM_AARCH64))
(root / "data" / "artifacts" / "arm64-v8a" / "libopenxr_loader.so").write_bytes(b"xrCreateInstance")
assert not linux.inspect(root)["openxr"]
def test_zip_with_unsafe_paths_is_refused(tmp_path):
archive = tmp_path / "bad.zip"
with zipfile.ZipFile(archive, "w") as z:
z.writestr("../evil", b"x")
with pytest.raises(ValueError, match="unsafe"):
linux.inspect(archive)
def test_add_linux_app_library_entry(tmp_path):
p = tmp_path / "Tool-1.2-aarch64.AppImage"
p.write_bytes(elf(linux.EM_AARCH64, appimage=True))
g = pipeline.add_linux_app(p)
assert g["package"] == "linux.tool" and g["kind"] == "linux" and pipeline.is_linux(g)
assert g["exe"] == p.name and g["analysis"]["extra"]["appimage"]
def test_local_files_of_a_lone_appimage_never_include_its_folder(tmp_path):
a, b = tmp_path / "Tool-1.2-aarch64.AppImage", tmp_path / "Other-1.0-aarch64.AppImage"
a.write_bytes(elf(linux.EM_AARCH64, appimage=True))
b.write_bytes(elf(linux.EM_AARCH64, appimage=True))
(tmp_path / "keep.txt").write_text("the user's file")
g = pipeline.add_linux_app(a)
pipeline.add_linux_app(b)
assert g["data_bytes"] == a.stat().st_size
assert pipeline.local_game_files(g["package"]) == [a] # another AppImage in the same folder doesn't block it
pipeline.delete_local_files(g["package"])
assert not a.exists() and b.exists() and (tmp_path / "keep.txt").exists()
def test_change_program_of_a_linux_folder(tmp_path):
root = tmp_path / "Matinee"
root.mkdir()
(root / "Matinee").write_bytes(elf(linux.EM_AARCH64))
(root / "helper").write_bytes(elf(linux.EM_AARCH64))
g = pipeline.add_linux_app(root)
assert g["exe"] == "Matinee" and pipeline.local_game_files(g["package"]) == [root]
assert pipeline.set_exe(g["package"], "helper")["exe"] == "helper"
def test_linux_recipes_dont_follow_the_catalog(tmp_path, monkeypatch):
from frameport.core import library
p = tmp_path / "Tool-1.2-aarch64.AppImage"
p.write_bytes(elf(linux.EM_AARCH64, appimage=True))
g = pipeline.add_linux_app(p)
monkeypatch.setattr(library, "REFRESH_ON_UPDATE", True)
data = library.load()
data["settings"]["recipes.app_version"] = "0.0.0" # as after an app update
library._follow_catalog(data)
assert data["games"][g["package"]]["recipe"]["as_is"] is True