enroll/tests/test_debian.py
Miguel Jacq 921801caa6
All checks were successful
CI / test (push) Successful in 5m24s
Lint / test (push) Successful in 30s
Trivy / test (push) Successful in 16s
0.1.6
2025-12-28 15:32:40 +11:00

154 lines
4.5 KiB
Python

from __future__ import annotations
import hashlib
from pathlib import Path
def test_dpkg_owner_parses_output(monkeypatch):
import enroll.debian as d
class P:
def __init__(self, rc: int, out: str):
self.returncode = rc
self.stdout = out
self.stderr = ""
def fake_run(cmd, text, capture_output):
assert cmd[:2] == ["dpkg", "-S"]
return P(
0,
"""
diversion by foo from: /etc/something
nginx-common:amd64: /etc/nginx/nginx.conf
nginx-common, nginx: /etc/nginx/sites-enabled/default
""",
)
monkeypatch.setattr(d.subprocess, "run", fake_run)
assert d.dpkg_owner("/etc/nginx/nginx.conf") == "nginx-common"
def fake_run_none(cmd, text, capture_output):
return P(1, "")
monkeypatch.setattr(d.subprocess, "run", fake_run_none)
assert d.dpkg_owner("/missing") is None
def test_list_manual_packages_parses_and_sorts(monkeypatch):
import enroll.debian as d
class P:
def __init__(self, rc: int, out: str):
self.returncode = rc
self.stdout = out
self.stderr = ""
def fake_run(cmd, text, capture_output):
assert cmd == ["apt-mark", "showmanual"]
return P(0, "\n# comment\nnginx\nvim\nnginx\n")
monkeypatch.setattr(d.subprocess, "run", fake_run)
assert d.list_manual_packages() == ["nginx", "vim"]
def test_build_dpkg_etc_index(tmp_path: Path):
import enroll.debian as d
info = tmp_path / "info"
info.mkdir()
(info / "nginx.list").write_text(
"/etc/nginx/nginx.conf\n/etc/nginx/sites-enabled/default\n/usr/bin/nginx\n",
encoding="utf-8",
)
(info / "vim:amd64.list").write_text(
"/etc/vim/vimrc\n/usr/bin/vim\n",
encoding="utf-8",
)
owned, owner_map, topdir_to_pkgs, pkg_to_etc = d.build_dpkg_etc_index(str(info))
assert "/etc/nginx/nginx.conf" in owned
assert owner_map["/etc/nginx/nginx.conf"] == "nginx"
assert "nginx" in topdir_to_pkgs
assert topdir_to_pkgs["nginx"] == {"nginx"}
assert pkg_to_etc["vim"] == ["/etc/vim/vimrc"]
def test_parse_status_conffiles_handles_continuations(tmp_path: Path):
import enroll.debian as d
status = tmp_path / "status"
status.write_text(
"\n".join(
[
"Package: nginx",
"Version: 1",
"Conffiles:",
" /etc/nginx/nginx.conf abcdef",
" /etc/nginx/mime.types 123456",
"",
"Package: other",
"Version: 2",
"",
]
),
encoding="utf-8",
)
m = d.parse_status_conffiles(str(status))
assert m["nginx"]["/etc/nginx/nginx.conf"] == "abcdef"
assert m["nginx"]["/etc/nginx/mime.types"] == "123456"
assert "other" not in m
def test_read_pkg_md5sums_and_file_md5(tmp_path: Path, monkeypatch):
import enroll.debian as d
# Patch /var/lib/dpkg/info/<pkg>.md5sums lookup to a tmp file.
md5_file = tmp_path / "pkg.md5sums"
md5_file.write_text("0123456789abcdef etc/foo.conf\n", encoding="utf-8")
def fake_exists(path: str) -> bool:
return path.endswith("/var/lib/dpkg/info/p1.md5sums")
real_open = open
def fake_open(path: str, *args, **kwargs):
if path.endswith("/var/lib/dpkg/info/p1.md5sums"):
return real_open(md5_file, *args, **kwargs)
return real_open(path, *args, **kwargs)
monkeypatch.setattr(d.os.path, "exists", fake_exists)
monkeypatch.setattr("builtins.open", fake_open)
m = d.read_pkg_md5sums("p1")
assert m == {"etc/foo.conf": "0123456789abcdef"}
content = b"hello world\n"
p = tmp_path / "x"
p.write_bytes(content)
assert d.file_md5(str(p)) == hashlib.md5(content).hexdigest()
def test_stat_triplet_fallbacks(tmp_path: Path, monkeypatch):
import enroll.debian as d
import sys
p = tmp_path / "f"
p.write_text("x", encoding="utf-8")
class FakePwdMod:
@staticmethod
def getpwuid(_): # pragma: no cover
raise KeyError
class FakeGrpMod:
@staticmethod
def getgrgid(_): # pragma: no cover
raise KeyError
# stat_triplet imports pwd/grp inside the function, so patch sys.modules.
monkeypatch.setitem(sys.modules, "pwd", FakePwdMod)
monkeypatch.setitem(sys.modules, "grp", FakeGrpMod)
owner, group, mode = d.stat_triplet(str(p))
assert owner.isdigit()
assert group.isdigit()
assert mode.isdigit() and len(mode) == 4