#!/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 ", "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("") (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()