Files
plezy/scripts/test_fetch_linux_libmpv.py
T
edde746 b27cab4510 build: read Windows libmpv pins from the lock and share the Linux fetch and version parsing
windows/CMakeLists.txt repeated the mpv-build key, asset base, and both
SHA-256 values that mpv-build.lock.json already owns, and the pin mover
never touched it, so a lock bump left Windows silently stale. CMake now
reads artifacts.windows with string(JSON) (floor raised to 3.19) and the
Windows native cache key hashes the lock; a workflow guard rejects
hand-pinned checksums.

The byte-identical Linux libmpv fetch heredoc in build.yml and ci.yml
moves to scripts/fetch_linux_libmpv.py, which verifies the checksum
before extracting and is what the packaging script now points local
builds at. The package-windows and release jobs and
linux/packaging/build-packages.py read the version through
scripts/pubspec_version.py instead of three looser regexes.
2026-09-03 11:36:29 +02:00

118 lines
3.9 KiB
Python

import hashlib
import json
import os
import platform
import shutil
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
SCRIPT = Path(__file__).resolve().parent / "fetch_linux_libmpv.py"
HAS_ZSTD = shutil.which("zstd") is not None
class FetchLinuxLibmpvTest(unittest.TestCase):
def setUp(self) -> None:
self._directory = tempfile.TemporaryDirectory(prefix="plezy-fetch-libmpv-test-")
self.addCleanup(self._directory.cleanup)
self.root = Path(self._directory.name)
self.dest = self.root / "prefix"
self.asset = self._build_asset()
def _build_asset(self) -> Path:
"""A tiny prefix tree packed the way mpv-build publishes it."""
tree = self.root / "tree"
(tree / "lib/pkgconfig").mkdir(parents=True)
(tree / "lib/pkgconfig/mpv.pc").write_text("Name: mpv\n", encoding="utf-8")
asset = self.root / "libmpv-linux-test.tar.zst"
if HAS_ZSTD:
subprocess.run(
["tar", "--zstd", "-cf", str(asset), "-C", str(tree), "."],
check=True,
)
else:
asset.write_bytes(b"not an archive")
return asset
def _write_lock(self, checksum: str, machine: str = platform.machine()) -> Path:
lock = self.root / "mpv-build.lock.json"
lock.write_text(
json.dumps(
{
"artifacts": {
"linux": {
"assetBase": self.root.as_uri(),
"assets": {machine: {"asset": self.asset.name, "checksum": checksum}},
}
}
}
),
encoding="utf-8",
)
return lock
def _run(self, lock: Path, env: dict[str, str] | None = None) -> subprocess.CompletedProcess[str]:
return subprocess.run(
[sys.executable, str(SCRIPT), "--lock", str(lock), "--dest", str(self.dest)],
check=False,
capture_output=True,
text=True,
env=env,
)
def _digest(self) -> str:
return hashlib.sha256(self.asset.read_bytes()).hexdigest()
@unittest.skipUnless(HAS_ZSTD, "zstd not installed")
def test_checksum_mismatch_leaves_dest_untouched(self) -> None:
lock = self._write_lock("0" * 64)
result = self._run(lock)
self.assertNotEqual(result.returncode, 0)
self.assertIn("does not match locked", result.stderr)
self.assertFalse(self.dest.exists())
@unittest.skipUnless(HAS_ZSTD, "zstd not installed")
def test_matching_checksum_extracts_prefix(self) -> None:
lock = self._write_lock(self._digest())
result = self._run(lock)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(
(self.dest / "lib/pkgconfig/mpv.pc").read_text(encoding="utf-8"),
"Name: mpv\n",
)
@unittest.skipUnless(HAS_ZSTD, "zstd not installed")
def test_unsupported_machine_is_a_clear_error(self) -> None:
lock = self._write_lock(self._digest(), machine="not-this-machine")
result = self._run(lock)
self.assertNotEqual(result.returncode, 0)
self.assertIn(f"no linux asset for {platform.machine()!r}", result.stderr)
self.assertIn("not-this-machine", result.stderr)
self.assertFalse(self.dest.exists())
def test_missing_zstd_fails_before_fetching(self) -> None:
lock = self._write_lock(self._digest())
empty_path = self.root / "empty-path"
empty_path.mkdir()
env = {key: value for key, value in os.environ.items() if key != "PATH"}
env["PATH"] = str(empty_path)
result = self._run(lock, env=env)
self.assertNotEqual(result.returncode, 0)
self.assertIn("zstd is required", result.stderr)
self.assertNotIn("fetching", result.stdout)
self.assertFalse(self.dest.exists())
if __name__ == "__main__":
unittest.main()