Add an integration test suite that boots ISO scenarios in QEMU (#109)
* Move the unit tests under test/unit test/ is growing an integration suite; the fast, VM-free tests get their own directory so the two kinds cannot be confused. test/all keeps its role as the aggregate runner for everything that needs no built ISO. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Add an integration suite that boots ISO scenarios in QEMU test/integration installs an ISO once — unattended, from a generated cidata drive — and saves a reusable base image; each scenario in test/integration.d/ then boots a throwaway overlay with its own copy of the firmware vars. Shared machinery (VM lifecycle, QMP screendump + OCR console driving, virtual keystrokes, guest SSH, the cidata build) lives in base-test.sh, so a new scenario is one file. The first scenario proves omarchy-system-factory-reset hands a machine on without destroying a shared ESP: a Windows entry and a foreign Linux with its own machine-id, boot directory, and UKIs must survive both the staged reset and the first-boot provisioning that follows. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * Let omarchy-iso-make keep the host package cache Purging /var/cache/pacman/pkg needs interactive sudo, which blocks unattended builds. --keep-pkg-cache skips the purge so test rigs and agents can build an ISO without a prompt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
10bd6632d3
commit
0c1333837f
14 files changed
+993
-13
No files matched your search
@@ -0,0 +1,79 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
PRUNER = ROOT / "builder/prune-offline-mirror.sh"
|
||||
|
||||
|
||||
class OfflineMirrorPruningTest(unittest.TestCase):
|
||||
def run_pruner(self, mirror: Path, required: list[str]):
|
||||
return subprocess.run(
|
||||
["bash", str(PRUNER), str(mirror)],
|
||||
input="".join(f"{filename}\n" for filename in required),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
def add_file(self, mirror: Path, filename: str):
|
||||
(mirror / filename).write_bytes(b"package")
|
||||
|
||||
def test_keeps_only_exactly_selected_package_archives(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
mirror = Path(directory)
|
||||
keep = "keep-2.0-1-x86_64.pkg.tar.zst"
|
||||
other = "other-1.0-1-any.pkg.tar.zst"
|
||||
stale_version = "keep-1.0-1-x86_64.pkg.tar.zst"
|
||||
removed_package = "removed-1.0-1-x86_64.pkg.tar.zst"
|
||||
orphan_signature = "interrupted-1.0-1-x86_64.pkg.tar.zst.sig"
|
||||
|
||||
for filename in (keep, other, stale_version, removed_package):
|
||||
self.add_file(mirror, filename)
|
||||
for filename in (keep, stale_version, removed_package):
|
||||
self.add_file(mirror, f"{filename}.sig")
|
||||
self.add_file(mirror, orphan_signature)
|
||||
self.add_file(mirror, "offline.db.tar.gz")
|
||||
|
||||
result = self.run_pruner(mirror, [keep, other])
|
||||
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertEqual(
|
||||
{path.name for path in mirror.iterdir()},
|
||||
{keep, f"{keep}.sig", other, "offline.db.tar.gz"},
|
||||
)
|
||||
self.assertIn(stale_version, result.stdout)
|
||||
self.assertIn(removed_package, result.stdout)
|
||||
|
||||
def test_missing_selection_aborts_before_deleting_anything(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
mirror = Path(directory)
|
||||
cached = "cached-1.0-1-x86_64.pkg.tar.zst"
|
||||
self.add_file(mirror, cached)
|
||||
|
||||
result = self.run_pruner(
|
||||
mirror, ["missing-1.0-1-x86_64.pkg.tar.zst"]
|
||||
)
|
||||
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertTrue((mirror / cached).exists())
|
||||
self.assertIn("selected packages are missing", result.stderr)
|
||||
|
||||
def test_empty_selection_aborts_before_deleting_anything(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
mirror = Path(directory)
|
||||
cached = "cached-1.0-1-x86_64.pkg.tar.zst"
|
||||
self.add_file(mirror, cached)
|
||||
|
||||
result = self.run_pruner(mirror, [])
|
||||
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertTrue((mirror / cached).exists())
|
||||
self.assertIn("empty package selection", result.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user