summaryrefslogtreecommitdiffstats
path: root/tests/test_update_kernel_cachyos.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_update_kernel_cachyos.py')
-rw-r--r--tests/test_update_kernel_cachyos.py177
1 files changed, 177 insertions, 0 deletions
diff --git a/tests/test_update_kernel_cachyos.py b/tests/test_update_kernel_cachyos.py
new file mode 100644
index 0000000..052f8ae
--- /dev/null
+++ b/tests/test_update_kernel_cachyos.py
@@ -0,0 +1,177 @@
+import importlib.util
+import io
+import json
+import tarfile
+import tempfile
+import unittest
+from pathlib import Path
+from unittest.mock import patch
+
+SCRIPTS = Path(__file__).resolve().parents[1] / "scripts"
+
+
+def load(name, filename):
+ spec = importlib.util.spec_from_file_location(name, SCRIPTS / filename)
+ module = importlib.util.module_from_spec(spec)
+ spec.loader.exec_module(module)
+ return module
+
+
+updater = load("update_kernel_cachyos", "update-kernel-cachyos.py")
+checker = load("check_versions_revisions", "check-versions.py")
+TEMPLATE = '''MY_RELEASE="${PV}-1"
+SLOT="0"
+src_unpack() {
+ case ${archive} in
+ "${MY_KERNEL}") expected=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ;;
+ "${MY_HEADERS}") expected=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb ;;
+ esac
+}
+'''
+
+
+class KernelUpdates(unittest.TestCase):
+ def setUp(self):
+ self.temporary = tempfile.TemporaryDirectory()
+ self.addCleanup(self.temporary.cleanup)
+ self.root = Path(self.temporary.name)
+ self.package = self.root / "packages/sys-kernel/kernel-cachyos"
+ self.package.mkdir(parents=True)
+ self.recipe("7.2.9", TEMPLATE)
+
+ def recipe(self, version, text):
+ path = self.package / f"kernel-cachyos-{version}.exheres-0"
+ path.write_text(text)
+ return path
+
+ def run_update(self, version, error=None):
+ def download(url, destination):
+ if error == "download" and "headers" in url:
+ raise updater.UpdateError("no matching headers")
+ destination.write_bytes(b"archive")
+ return "a" * 64 if "headers" not in url else "b" * 64
+
+ def inspect(_archive, name, _release):
+ if error == "inspect" and name == "linux-cachyos-headers":
+ raise updater.UpdateError("mismatched headers")
+
+ with patch.object(updater, "latest_aur_release", return_value=version), \
+ patch.object(updater, "download", side_effect=download), \
+ patch.object(updater, "inspect_archive", side_effect=inspect):
+ updater.update(self.root)
+
+ def names(self):
+ return sorted(path.name for path in self.package.iterdir())
+
+ def test_same_pv_replaces_previous_recipe(self):
+ self.run_update("7.2.9-2")
+ self.assertEqual(self.names(), ["kernel-cachyos-7.2.9-r1.exheres-0"])
+ revised = (self.package / "kernel-cachyos-7.2.9-r1.exheres-0").read_text()
+ self.assertIn('MY_RELEASE="${PV}-2"', revised)
+ self.assertIn('SLOT="0"', revised)
+ self.assertIn("a" * 64, revised)
+ self.assertIn("b" * 64, revised)
+ found, problems = checker.recipes(self.root)
+ self.assertEqual(problems, [])
+ self.assertEqual(found["sys-kernel/kernel-cachyos"], "7.2.9-r1")
+ self.assertEqual(checker.kernel_release(self.root, "7.2.9-r1"), "7.2.9-2")
+
+ def test_next_pkgrel_and_new_version(self):
+ self.run_update("7.2.9-2")
+ self.run_update("7.2.9-3")
+ self.assertEqual(self.names(), ["kernel-cachyos-7.2.9-r2.exheres-0"])
+ self.run_update("7.3.0-1")
+ self.assertEqual(self.names(), ["kernel-cachyos-7.3.0.exheres-0"])
+
+ def test_noop_and_failure_preserve_recipes(self):
+ before = self.names()
+ self.run_update("7.2.9-1")
+ self.assertEqual(self.names(), before)
+ for version, error in (("7.2.9-3", None), ("7.2.9-2", "download"), ("7.2.9-2", "inspect")):
+ with self.subTest(version=version, error=error), self.assertRaises(updater.UpdateError):
+ self.run_update(version, error)
+ self.assertEqual(self.names(), before)
+
+ def test_duplicate_and_legacy_slot_are_rejected(self):
+ old = self.recipe("7.2.8", TEMPLATE)
+ found, problems = checker.recipes(self.root)
+ self.assertIn("keep only one kernel-cachyos recipe", problems)
+ self.assertIn("sys-kernel/kernel-cachyos", found)
+ with patch.object(updater, "latest_aur_release") as aur, self.assertRaises(updater.UpdateError):
+ updater.update(self.root)
+ aur.assert_not_called()
+ old.unlink()
+ current = self.package / "kernel-cachyos-7.2.9.exheres-0"
+ current.write_text(TEMPLATE.replace('SLOT="0"', 'SLOT="${PV}"'))
+ with patch.object(updater, "latest_aur_release") as aur, self.assertRaises(updater.UpdateError):
+ updater.update(self.root)
+ aur.assert_not_called()
+ self.assertEqual(self.names(), ["kernel-cachyos-7.2.9.exheres-0"])
+
+ def test_bad_aur_response_preserves_recipes(self):
+ before = self.names()
+ for status in (403, 429):
+ with self.subTest(status=status):
+ from urllib.error import HTTPError
+ with patch.object(updater.urllib.request, "urlopen", side_effect=HTTPError(updater.AUR_URL, status, "blocked", {}, None)):
+ with self.assertRaises(updater.UpdateError):
+ updater.update(self.root)
+ self.assertEqual(self.names(), before)
+
+ def test_aur_payload(self):
+ payload = json.dumps({"resultcount": 1, "results": [{"Name": "linux-cachyos", "Version": "7.2.9-2"}]}).encode()
+ with patch.object(updater.urllib.request, "urlopen", return_value=io.BytesIO(payload)):
+ self.assertEqual(updater.latest_aur_release(), "7.2.9-2")
+
+ def test_archive_metadata_and_paths(self):
+ def archive(name, unsafe=False):
+ path = self.root / f"{name}.tar.zst"
+ module = "usr/lib/modules/7.2.9-2-cachyos"
+ items = {
+ ".PKGINFO": f"pkgname = {name}\npkgver = 7.2.9-2\narch = x86_64_v3\n".encode(),
+ }
+ if name == "linux-cachyos":
+ items.update({f"{module}/vmlinuz": b"kernel", f"{module}/kernel/example.ko.zst": b"module"})
+ else:
+ items.update({f"{module}/build/{part}": b"header" for part in (".config", "Module.symvers", "System.map")})
+ items[f"{module}/vdso/vdso64.so"] = b"vdso"
+ if unsafe:
+ items["../outside"] = b"bad"
+ raw = io.BytesIO()
+ with tarfile.open(fileobj=raw, mode="w") as tar:
+ for item, data in items.items():
+ info = tarfile.TarInfo(item)
+ info.size = len(data)
+ tar.addfile(info, io.BytesIO(data))
+ import subprocess
+ path.write_bytes(subprocess.run(["zstd", "-cq"], input=raw.getvalue(), stdout=subprocess.PIPE, check=True).stdout)
+ return path
+
+ updater.inspect_archive(archive("linux-cachyos"), "linux-cachyos", "7.2.9-2")
+ updater.inspect_archive(archive("linux-cachyos-headers"), "linux-cachyos-headers", "7.2.9-2")
+ with self.assertRaises(updater.UpdateError):
+ updater.inspect_archive(archive("linux-cachyos", unsafe=True), "linux-cachyos", "7.2.9-2")
+ with self.assertRaises(updater.UpdateError):
+ updater.inspect_archive(archive("linux-cachyos"), "linux-cachyos", "7.2.9-3")
+
+ def test_directory_cannot_stand_in_for_required_file(self):
+ archive = self.root / "invalid.tar.zst"
+ module = "usr/lib/modules/7.2.9-2-cachyos"
+ raw = io.BytesIO()
+ with tarfile.open(fileobj=raw, mode="w") as tar:
+ metadata = b"pkgname = linux-cachyos\npkgver = 7.2.9-2\narch = x86_64_v3\n"
+ info = tarfile.TarInfo(".PKGINFO")
+ info.size = len(metadata)
+ tar.addfile(info, io.BytesIO(metadata))
+ for name in (f"{module}/vmlinuz", f"{module}/kernel/example"):
+ info = tarfile.TarInfo(name)
+ info.type = tarfile.DIRTYPE
+ tar.addfile(info)
+ import subprocess
+ archive.write_bytes(subprocess.run(["zstd", "-cq"], input=raw.getvalue(), stdout=subprocess.PIPE, check=True).stdout)
+ with self.assertRaises(updater.UpdateError):
+ updater.inspect_archive(archive, "linux-cachyos", "7.2.9-2")
+
+
+if __name__ == "__main__":
+ unittest.main()