Files
smirk-backend-core/tools/tests/test_build_admission.py
T

135 lines
5.5 KiB
Python

"""Fundless Git fixtures prove source admission and binary compatibility guards."""
import importlib.util
import os
from pathlib import Path
import subprocess
import tempfile
import unittest
from unittest.mock import patch
TOOLS = Path(__file__).resolve().parents[1]
def load(name, path):
spec = importlib.util.spec_from_file_location(name, path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
source = load("source", TOOLS / "check-build-source.py")
stage = load("stage", TOOLS / "stage-backend-candidate.py")
class Admission(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory(prefix="smirk-git-admission-")
self.previous = Path.cwd()
os.chdir(self.temp.name)
self.git("init", "-q")
self.git("config", "user.name", "Fundless fixture")
self.git("config", "user.email", "fixture@example.invalid")
Path("source.txt").write_text("baseline\n")
self.git("add", ".")
self.git("commit", "-qm", "baseline")
self.base = self.git("rev-parse", "HEAD")
Path("source.txt").write_text("candidate\n")
self.git("commit", "-qam", "candidate")
self.candidate = self.git("rev-parse", "HEAD")
def tearDown(self):
os.chdir(self.previous)
self.temp.cleanup()
def git(self, *args, input=None):
return subprocess.check_output(["git", *args], input=input, text=True,
stderr=subprocess.PIPE).strip()
def wrapper(self, second=None, tree=None):
tree = tree or self.git("rev-parse", self.candidate + "^{tree}")
value = self.git("commit-tree", tree, "-p", self.base, "-p", second or self.candidate,
input="wrapper\n")
self.git("reset", "--hard", value)
return value
def test_canonical_and_tree_identical_wrapper_admitted(self):
self.assertEqual(source.admit(self.candidate)["build_commit"], self.candidate)
wrapper = self.wrapper()
admitted = source.admit(self.candidate, wrapper)
self.assertEqual(admitted["source_commit"], self.candidate)
self.assertEqual(admitted["source_tree"], self.git("rev-parse", "HEAD^{tree}"))
def test_release_requires_wrapper_and_derives_its_source(self):
with self.assertRaises(source.Refusal):
source.source_for_checkout(True)
with self.assertRaises(source.Refusal):
source.admit(self.candidate, self.candidate, require_wrapper=True)
wrapper = self.wrapper()
self.assertEqual(source.source_for_checkout(True), self.candidate)
self.assertEqual(source.admit(self.candidate, wrapper, require_wrapper=True)["build_commit"], wrapper)
def test_moving_dispatch_head_refused(self):
with self.assertRaises(source.Refusal):
source.admit(self.candidate, self.base)
def test_tree_change_refused(self):
self.wrapper(tree=self.git("rev-parse", self.base + "^{tree}"))
with self.assertRaises(source.Refusal):
source.admit(self.candidate)
def test_tree_identity_without_source_parent_refused(self):
tree = self.git("rev-parse", self.candidate + "^{tree}")
unrelated = self.git("commit-tree", tree, "-p", self.base, input="unrelated\n")
self.wrapper(second=unrelated)
with self.assertRaises(source.Refusal):
source.admit(self.candidate)
def test_dirty_surface_and_missing_pin_refused(self):
Path("unknown.txt").write_text("unreviewed\n")
with self.assertRaises(source.Refusal):
source.admit(self.candidate)
with self.assertRaises(source.Refusal):
source.admit("")
def test_dispatch_missing_head_or_wrong_repository_refused(self):
with patch.dict(os.environ, {"GITHUB_REPOSITORY": "Builds/smirk-backend-core",
"GITHUB_EVENT_NAME": "workflow_dispatch"}, clear=True):
with self.assertRaises(source.Refusal):
source.main()
with patch.dict(os.environ, {"GITHUB_REPOSITORY": "unreviewed/repository"}, clear=True):
with self.assertRaises(source.Refusal):
source.main()
class BinaryCompatibility(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory(prefix="smirk-elf-fixture-")
self.binary = Path(self.temp.name) / "binary"
self.binary.write_bytes(b"\x7fELF\x02\x01" + bytes(12) + b"\x3e\x00")
def tearDown(self):
self.temp.cleanup()
def test_compatible_versions_recorded_in_numeric_order(self):
with patch.object(subprocess, "check_output", return_value="GLIBC_2.3 GLIBC_2.36 GLIBC_2.9"):
result = stage.elf_requirements(self.binary)
self.assertEqual(result[-1], "2.36")
self.assertIn("2.9", result)
def test_incompatible_or_unknown_libc_refused(self):
for output in ("GLIBC_2.38", "unreadable"):
with self.subTest(output=output), patch.object(subprocess, "check_output", return_value=output):
with self.assertRaises(stage.source.Refusal):
stage.elf_requirements(self.binary)
def test_wrong_binary_format_refused_before_tool_invocation(self):
self.binary.write_bytes(b"not ELF")
with patch.object(subprocess, "check_output") as probe:
with self.assertRaises(stage.source.Refusal):
stage.elf_requirements(self.binary)
probe.assert_not_called()
if __name__ == "__main__":
unittest.main()