0.1.6
This commit is contained in:
parent
3fc5aec5fc
commit
921801caa6
15 changed files with 1102 additions and 423 deletions
154
tests/test_debian.py
Normal file
154
tests/test_debian.py
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue