tests/test_media_build_cache.py
Rama master · réplica de lectura del repositorio original.
from pathlib import Path
import tempfile
import unittest
from unittest import mock
from scripts import media_build_cache as cache
class MediaBuildCacheTests(unittest.TestCase):
def compiler(self, command, **_kwargs):
output = Path(command[-1])
tool = "ffmpeg" if "build_ffmpeg" in command[1] else "untrunc"
(output / tool).mkdir(parents=True)
(output / tool / "manifest.json").write_text('{"compiled": true}')
(output / tool / "program.exe").write_bytes(b"compiled program")
(output / f"{tool}-corresponding-source.zip").write_bytes(b"matching source")
def test_cached_binaries_and_corresponding_sources_restore_without_compiling(self):
with tempfile.TemporaryDirectory() as directory, mock.patch.object(cache, "input_identity", return_value={"input": "locked"}), \
mock.patch.object(cache.subprocess, "run", side_effect=self.compiler) as compiler:
root = Path(directory).resolve()
first = cache.build(root, "windows")
second = cache.build(root, "windows")
self.assertEqual(first["cache_hits"], [])
self.assertEqual(second["cache_hits"], ["ffmpeg", "untrunc"])
self.assertEqual(compiler.call_count, 2)
self.assertEqual((root / "build/ffmpeg-windows/ffmpeg-corresponding-source.zip").read_bytes(), b"matching source")
def test_changed_inputs_or_corrupt_bytes_require_compilation(self):
with tempfile.TemporaryDirectory() as directory, mock.patch.object(cache, "input_identity", return_value={"input": "one"}) as identity, \
mock.patch.object(cache.subprocess, "run", side_effect=self.compiler) as compiler:
root = Path(directory).resolve()
cache.build(root, "windows", tool="ffmpeg")
binary = root / "build/media-cache/windows-x86_64/ffmpeg/ffmpeg/program.exe"
binary.write_bytes(b"corrupt")
self.assertEqual(cache.build(root, "windows", tool="ffmpeg")["cache_hits"], [])
identity.return_value = {"input": "two"}
self.assertEqual(cache.build(root, "windows", tool="ffmpeg")["cache_hits"], [])
self.assertEqual(compiler.call_count, 3)
def test_missing_source_archive_is_not_a_cache_hit(self):
with tempfile.TemporaryDirectory() as directory, mock.patch.object(cache, "input_identity", return_value={"input": "locked"}), \
mock.patch.object(cache.subprocess, "run", side_effect=self.compiler) as compiler:
root = Path(directory).resolve()
cache.build(root, "windows", tool="ffmpeg")
(root / "build/media-cache/windows-x86_64/ffmpeg/ffmpeg-corresponding-source.zip").unlink()
self.assertEqual(cache.build(root, "windows", tool="ffmpeg")["cache_hits"], [])
self.assertEqual(compiler.call_count, 2)
def test_cache_paths_cannot_delete_outside_the_build_directory(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve()
protected = root / "media"
protected.mkdir()
with self.assertRaises(ValueError):
cache.remove_owned(root, protected)
self.assertTrue(protected.is_dir())
def test_input_identity_distinguishes_architecture_and_sdk(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve()
for name in cache.INPUTS:
path = root / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("input")
def native_command(command, **_kwargs):
self.assertNotEqual(command[0], "cmake")
return "native tool version"
with mock.patch.object(cache.subprocess, "check_output", side_effect=native_command):
native = cache.input_identity(root, "macos", "arm64")
self.assertIn("sdk", native["toolchain"])
self.assertIn("pkg-config", native["toolchain"])
first = cache.input_identity(root, "macos", "arm64", toolchain={"sdk": "one"})
self.assertNotEqual(first, cache.input_identity(root, "macos", "x86_64", toolchain={"sdk": "one"}))
self.assertNotEqual(first, cache.input_identity(root, "macos", "arm64", toolchain={"sdk": "two"}))
(root / cache.INPUTS[0]).write_text("different source revision")
self.assertNotEqual(first, cache.input_identity(root, "macos", "arm64", toolchain={"sdk": "one"}))
def test_actions_cache_identity_tracks_toolchain_and_source_changes(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory).resolve()
for name in cache.INPUTS:
path = root / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text("input")
first = cache.input_identity(root, "macos", "arm64", toolchain={"sdk": "one", "clang": "one"})
key = cache.github_cache_key(first)
reordered = cache.input_identity(root, "macos", "arm64", toolchain={"clang": "one", "sdk": "one"})
self.assertEqual(key, cache.github_cache_key(reordered))
for target, arch, tools in (("macos", "x86_64", first["toolchain"]),
("macos", "arm64", {"sdk": "two", "clang": "one"}),
("windows", "x86_64", first["toolchain"])):
with self.subTest(target=target, arch=arch, tools=tools):
self.assertNotEqual(key, cache.github_cache_key(cache.input_identity(root, target, arch, toolchain=tools)))
(root / cache.INPUTS[0]).write_text("new source")
self.assertNotEqual(key, cache.github_cache_key(cache.input_identity(root, "macos", "arm64", toolchain=first["toolchain"])))