135 lines
6.2 KiB
Python
135 lines
6.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Offline verification of SUSE nFPM metadata and catalog integration.
|
|
|
|
Run: python3 -m unittest discover -s tests -v
|
|
Does not require nfpm, root, Docker, or access to the RustProxy upstream.
|
|
"""
|
|
|
|
import importlib.util
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
|
|
class SusePackagingTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.tmp = tempfile.TemporaryDirectory()
|
|
cls.work = Path(cls.tmp.name)
|
|
cls.src = cls.work / "source"
|
|
(cls.src / "docker-agent").mkdir(parents=True)
|
|
agent = cls.src / "docker-agent"
|
|
(agent / "rustproxy-docker-agent.service").write_text(
|
|
"[Unit]\nDescription=Test Agent\n[Service]\nExecStart=/usr/local/bin/rustproxy-docker-agent\n")
|
|
(agent / "docker-agent.env.example").write_text("BIND_ADDRESS=127.0.0.1\n")
|
|
(agent / "README.md").write_text("Test fixture")
|
|
(cls.work / "server").write_text("#!/bin/sh\necho server\n")
|
|
(cls.work / "agent").write_text("#!/bin/sh\necho agent\n")
|
|
(cls.work / "server").chmod(0o755)
|
|
(cls.work / "agent").chmod(0o755)
|
|
cls.env = {
|
|
**os.environ,
|
|
"BUILDER_ROOT": str(ROOT),
|
|
"PACKAGE_NAME": "rustproxy",
|
|
"BINARY_NAME": "rust-proxy",
|
|
"VERSION": "0.99.1",
|
|
"PACKAGE_RELEASE": "7",
|
|
"MAINTAINER": "Test Builder <test@example.invalid>",
|
|
"DESCRIPTION": "Test RPM",
|
|
"LICENSE": "MIT",
|
|
"HOMEPAGE": "https://example.invalid",
|
|
"GPG_PRIVATE_KEY_FILE": "/not/needed/until-nfpm-signs",
|
|
}
|
|
subprocess.run(
|
|
["bash", str(ROOT / "scripts/prepare-package.sh"), str(cls.src),
|
|
str(cls.work / "package"), str(cls.work / "server")],
|
|
env=cls.env, check=True, capture_output=True, text=True,
|
|
)
|
|
subprocess.run(
|
|
["bash", str(ROOT / "scripts/prepare-agent-package.sh"), str(cls.src),
|
|
str(cls.work / "package-agent"), str(cls.work / "agent")],
|
|
env=cls.env, check=True, capture_output=True, text=True,
|
|
)
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
cls.tmp.cleanup()
|
|
|
|
def test_suse_rpm_has_native_dependencies_and_paths(self):
|
|
contents = (self.work / "package/nfpm-suse.yaml").read_text()
|
|
self.assertIn(" - shadow\n", contents)
|
|
self.assertIn(" - 'glibc >= 2.34'", contents)
|
|
self.assertNotIn("shadow-utils", contents)
|
|
self.assertIn("(python311 and python311-pip)", contents)
|
|
self.assertIn("/usr/libexec/rustproxy/python3", contents)
|
|
self.assertIn("50-suse-python.conf", contents)
|
|
self.assertIn("compression: gzip", contents)
|
|
self.assertIn("key_file:", contents)
|
|
self.assertTrue((self.work / "package/payload/usr/lib/systemd/system/rustproxy.service.d/50-suse-python.conf").exists())
|
|
self.assertIn("/usr/libexec/rustproxy", (self.work / "package/payload/usr/lib/systemd/system/rustproxy.service.d/50-suse-python.conf").read_text())
|
|
|
|
def test_suse_agent_has_native_dependencies(self):
|
|
contents = (self.work / "package-agent/nfpm-suse.yaml").read_text()
|
|
self.assertIn(" - shadow\n", contents)
|
|
self.assertNotIn("shadow-utils", contents)
|
|
self.assertIn("compression: gzip", contents)
|
|
self.assertIn("name: \"rustproxy-docker-agent\"", contents)
|
|
self.assertIn("/usr/lib/systemd/system/rustproxy-docker-agent.service", contents)
|
|
|
|
def test_suse_python_launcher(self):
|
|
wrapper = self.work / "package/payload/usr/libexec/rustproxy/python3"
|
|
result = subprocess.run([str(wrapper), "-c", "import sys; print(sys.version_info.major)"],
|
|
capture_output=True, text=True, timeout=5)
|
|
# Builder test machine has Python 3; a host without Python >=3.10
|
|
# will deliberately fail the wrapper rather than run obsolete Python.
|
|
if result.returncode == 0:
|
|
self.assertEqual(result.stdout.strip(), "3")
|
|
else:
|
|
self.assertIn("Python 3.10", result.stderr)
|
|
|
|
|
|
class SuseCatalogTests(unittest.TestCase):
|
|
def setUp(self):
|
|
spec = importlib.util.spec_from_file_location("rustproxy_dashboard", ROOT / "dashboard/app.py")
|
|
self.assertIsNotNone(spec)
|
|
self.api = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(self.api)
|
|
self.tmp = tempfile.TemporaryDirectory()
|
|
self.addCleanup(self.tmp.cleanup)
|
|
self.repo = Path(self.tmp.name) / "repository"
|
|
release = self.repo / "releases" / "new"
|
|
(release / "suse/x86_64/repodata").mkdir(parents=True)
|
|
(release / "suse/x86_64/repodata/repomd.xml").write_text("<repomd/>")
|
|
(release / "suse/x86_64/rustproxy-0.99.1-7.x86_64.rpm").write_bytes(b"rpm-test")
|
|
(release / "suse/x86_64/rustproxy-docker-agent-0.99.1-7.x86_64.rpm").write_bytes(b"rpm-test")
|
|
(release / "SUSE-BUILD-INFO.txt").write_text(
|
|
"app_version=0.99.1\npackage_release=7\n"
|
|
"built_at=2026-10-22T12:00:00Z\nsource_commit=abcdef123456\n"
|
|
)
|
|
(self.repo / "current").symlink_to("releases/new")
|
|
self.release = release
|
|
|
|
def test_catalog_publishes_suse_packages_only_in_suse_channel(self):
|
|
catalog = self.api.generate_catalog(self.repo)
|
|
self.assertTrue(catalog["builds"]["suse"]["published"])
|
|
self.assertEqual(catalog["builds"]["suse"]["package_version"], "0.99.1-7")
|
|
suse_pkgs = [p for p in catalog["packages"] if p["channel"] == "suse"]
|
|
self.assertEqual(len(suse_pkgs), 2)
|
|
self.assertTrue(all(p["format"] == "RPM" for p in suse_pkgs))
|
|
self.assertTrue(all(p["download_url"].endswith(".x86_64.rpm") for p in suse_pkgs))
|
|
self.assertTrue(all("/suse/x86_64/" in p["download_url"] for p in suse_pkgs))
|
|
self.assertEqual(catalog["summary"]["channel_counts"]["suse"], 2)
|
|
|
|
def test_old_build_does_not_fake_suse_publication(self):
|
|
(self.release / "SUSE-BUILD-INFO.txt").unlink()
|
|
catalog = self.api.generate_catalog(self.repo)
|
|
self.assertFalse(catalog["builds"]["suse"]["published"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|