Files
PS5_RetroArch/tests/test_deploy_identity.py
T
Mihawk d337e2c11b Add reproducible PS5 FCEUmm build and record native loader blocker
Build pinned source and core-info with this project's SDK, validate the ELF,
and stage both metadata paths for existing saved configs. Use a deterministic
build ID and require exact core readback; refresh stale metadata caches.

Verified: tools/verify.sh (five host gates, 45 tests, 18 evidence records).
Artifact: evidence/fceumm-build/{abi,capture,expectation}.json.
Target: tools/run-title.sh --no-build --watch 120, manual core/game selection.
Metadata discovery and exact core bytes pass; dynamic core open fails, then
content startup crashes in frontend vulkan_alive(NULL). This commit verifies
build tooling only, not playable FCEUmm. Park native loader/recovery acceptance
in parked/native-core-loading/README.md. PS5_Vulkan is unchanged.
2026-09-19 14:05:29 -04:00

48 lines
2.2 KiB
Python

"""Generic startup strings must not accept an older executable."""
import importlib.util
import tempfile
import unittest
from pathlib import Path
from unittest.mock import Mock
ROOT = Path(__file__).resolve().parent.parent
spec = importlib.util.spec_from_file_location("deploy_title", ROOT / "tools/deploy-title.py")
deploy = importlib.util.module_from_spec(spec)
spec.loader.exec_module(deploy)
class DeployIdentity(unittest.TestCase):
def test_generic_startup_strings_are_insufficient(self):
with tempfile.TemporaryDirectory() as directory:
image = Path(directory) / "eboot.bin"
image.write_bytes(b"main() entered\0rarch_main returned\0ps5_init entered")
with self.assertRaisesRegex(ValueError, "build identity"):
deploy.program_markers(image)
def test_different_build_requires_different_marker(self):
with tempfile.TemporaryDirectory() as directory:
image = Path(directory) / "eboot.bin"
marker = b"build identity: " + b"a" * 64
image.write_bytes(b"main() entered\0" + marker + b"\0")
required = deploy.program_markers(image)
self.assertIn(marker, required)
old_image = b"main() entered\0build identity: " + b"b" * 64 + b"\0"
self.assertTrue(any(value not in old_image for value in required))
def test_metadata_refresh_uses_info_parent_and_checks_readback(self):
ftp = Mock()
stored = {}
ftp.storbinary.side_effect = lambda cmd, stream: stored.update({cmd: stream.read()})
ftp.retrbinary.side_effect = lambda cmd, write, **kw: write(b'\0')
deploy.refresh_core_info(ftp, '/title/cores/fceumm_libretro.info')
self.assertEqual(stored, {'STOR /title/cores/core_info.refresh': b'\0'})
self.assertEqual(ftp.retrbinary.call_args.args[0],
'RETR /title/cores/core_info.refresh')
def test_metadata_refresh_refuses_failed_readback(self):
ftp = Mock()
ftp.retrbinary.side_effect = lambda cmd, write, **kw: write(b'wrong')
with self.assertRaisesRegex(SystemExit, 'refresh marker readback failed'):
deploy.refresh_core_info(ftp, '/title/info/fceumm_libretro.info')