Files
govoplan/tests/test_runtime_image_context.py
zemion 7ec0bbb826
Dependency Audit / dependency-audit (push) Failing after 1m50s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Successful in 11m34s
Developer Meta-package Release / publish-package (push) Successful in 10s
Release v0.1.17
2026-08-05 20:34:17 +02:00

160 lines
5.5 KiB
Python

from __future__ import annotations
import importlib.util
import json
from pathlib import Path
import sys
import tempfile
import unittest
import zipfile
SCRIPT = (
Path(__file__).resolve().parents[1]
/ "tools"
/ "release"
/ "prepare-runtime-context.py"
)
SPEC = importlib.util.spec_from_file_location("prepare_runtime_context", SCRIPT)
assert SPEC is not None and SPEC.loader is not None
MODULE = importlib.util.module_from_spec(SPEC)
sys.modules[SPEC.name] = MODULE
SPEC.loader.exec_module(MODULE)
class RuntimeImageContextTests(unittest.TestCase):
def test_builds_deterministic_network_free_context(self) -> None:
with tempfile.TemporaryDirectory(prefix="govoplan-runtime-context-") as value:
root = Path(value)
wheelhouse = root / "input-wheels"
web = root / "web"
wheelhouse.mkdir()
web.mkdir()
self._wheel(
wheelhouse / "govoplan_core-1.2.3-py3-none-any.whl",
package="govoplan-core",
version="1.2.3",
module_ids=(),
)
self._wheel(
wheelhouse / "govoplan_files-1.2.3-py3-none-any.whl",
package="govoplan-files",
version="1.2.3",
module_ids=("files",),
)
self._wheel(
wheelhouse / "sqlalchemy-2.0.0-py3-none-any.whl",
package="SQLAlchemy",
version="2.0.0",
module_ids=(),
)
(web / "index.html").write_text("<main>GovOPlaN</main>\n", encoding="utf-8")
composition = MODULE.prepare_context(
wheelhouse=wheelhouse,
web_dist=web,
output=root / "context",
required_modules=("files",),
source_date_epoch=1_700_000_000,
)
self.assertEqual(["files"], composition["python"]["module_ids"])
self.assertEqual(2, composition["python"]["wheel_count"])
requirements = (root / "context" / "requirements-runtime.txt").read_text()
self.assertEqual(
"govoplan-core[server]==1.2.3\ngovoplan-files==1.2.3\n",
requirements,
)
published = json.loads(
(
root
/ "context"
/ "web-dist"
/ ".well-known"
/ "govoplan-composition.json"
).read_text()
)
self.assertEqual(composition, published)
self.assertEqual(
(
SCRIPT.parent / "runtime" / "web-entrypoint.sh"
).read_bytes(),
(root / "context" / "web-entrypoint.sh").read_bytes(),
)
def test_rejects_missing_required_module(self) -> None:
with tempfile.TemporaryDirectory(prefix="govoplan-runtime-context-") as value:
root = Path(value)
wheelhouse = root / "wheels"
web = root / "web"
wheelhouse.mkdir()
web.mkdir()
self._wheel(
wheelhouse / "govoplan_core-1.0.0-py3-none-any.whl",
package="govoplan-core",
version="1.0.0",
module_ids=(),
)
(web / "index.html").write_text("ok", encoding="utf-8")
with self.assertRaisesRegex(MODULE.ContextError, "missing required"):
MODULE.prepare_context(
wheelhouse=wheelhouse,
web_dist=web,
output=root / "context",
required_modules=("mail",),
)
def test_rejects_symlinked_web_payload(self) -> None:
with tempfile.TemporaryDirectory(prefix="govoplan-runtime-context-") as value:
root = Path(value)
wheelhouse = root / "wheels"
web = root / "web"
wheelhouse.mkdir()
web.mkdir()
self._wheel(
wheelhouse / "govoplan_core-1.0.0-py3-none-any.whl",
package="govoplan-core",
version="1.0.0",
module_ids=(),
)
outside = root / "outside"
outside.write_text("not part of dist", encoding="utf-8")
(web / "index.html").symlink_to(outside)
with self.assertRaisesRegex(MODULE.ContextError, "symlink"):
MODULE.prepare_context(
wheelhouse=wheelhouse,
web_dist=web,
output=root / "context",
)
@staticmethod
def _wheel(
path: Path,
*,
package: str,
version: str,
module_ids: tuple[str, ...],
) -> None:
dist_info = package.replace("-", "_") + f"-{version}.dist-info"
with zipfile.ZipFile(path, "w") as archive:
archive.writestr(
f"{dist_info}/METADATA",
f"Metadata-Version: 2.1\nName: {package}\nVersion: {version}\n",
)
if module_ids:
rows = "\n".join(
f"{module_id} = example.module:manifest"
for module_id in module_ids
)
archive.writestr(
f"{dist_info}/entry_points.txt",
f"[govoplan.modules]\n{rows}\n",
)
archive.writestr(f"{package.replace('-', '_')}/__init__.py", "")
if __name__ == "__main__":
unittest.main()