Files
ProxMenux/tests/test_fastfetch_config_generation.py
T

91 lines
3.4 KiB
Python
Raw Normal View History

2026-09-19 12:05:10 +02:00
"""Regression tests for Fastfetch config generation.
Run: python3 -m unittest discover -s tests -p test_fastfetch_config_generation.py -v
"""
from pathlib import Path
import re
import shlex
import subprocess
import tempfile
import unittest
SCRIPT = (
Path(__file__).resolve().parents[1]
/ "scripts/post_install/customizable_post_install.sh"
)
def extract_function(name: str) -> str:
text = SCRIPT.read_text()
match = re.search(rf"^{re.escape(name)}\(\) \{{\n.*?^\}}", text, re.M | re.S)
if match is None:
raise AssertionError(f"function {name} not found")
return match.group(0)
class FastfetchConfigGeneration(unittest.TestCase):
def test_script_does_not_use_retired_force_option(self):
self.assertNotIn("--gen-config-force", SCRIPT.read_text())
def run_case(self, fastfetch_exit: int = 0):
function = extract_function("_generate_fastfetch_config")
with tempfile.TemporaryDirectory(prefix="fastfetch-config-test-") as td:
root = Path(td)
fake_bin = root / "bin"
fake_bin.mkdir()
target = root / "config.jsonc"
target.write_text('{"modules":["preserved"]}\n')
calls = root / "calls"
fake = fake_bin / "fastfetch"
fake.write_text(
"#!/bin/bash\n"
"printf '%s\\n' \"$*\" >> \"$CALLS\"\n"
f"if (( {fastfetch_exit} != 0 )); then exit {fastfetch_exit}; fi\n"
"[[ \"$1\" == --gen-config && -n \"$2\" ]] || exit 90\n"
"[[ ! -e \"$2\" ]] || exit 91\n"
"printf '%s\\n' '{\"modules\":[\"os\",\"kernel\"]}' > \"$2\"\n"
)
fake.chmod(0o755)
q = shlex.quote
harness = function + f"""
pmx_write_file() {{ cat > "$1"; }}
_generate_fastfetch_config {q(str(target))}
printf 'status=%s\n' "$?"
printf 'target=%s\n' "$(cat {q(str(target))})"
"""
result = subprocess.run(
["/bin/bash", "--noprofile", "--norc"],
input=harness,
text=True,
capture_output=True,
timeout=10,
env={
"PATH": f"{fake_bin}:/usr/bin:/bin",
"CALLS": str(calls),
"LC_ALL": "C",
},
)
return result, target.read_text(), calls.read_text() if calls.exists() else ""
def test_generates_to_temporary_path_before_replacing_target(self):
result, target, calls = self.run_case()
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("status=0\n", result.stdout)
self.assertEqual(target, '{"modules":["os","kernel"]}\n')
self.assertRegex(calls, r"^--gen-config /tmp/.+/config\.jsonc\n$")
self.assertNotIn("--gen-config-force", calls)
generated_config = Path(calls.removeprefix("--gen-config ").strip())
self.assertFalse(generated_config.parent.exists())
def test_generation_failure_preserves_existing_config(self):
result, target, calls = self.run_case(fastfetch_exit=17)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("status=1\n", result.stdout)
self.assertEqual(target, '{"modules":["preserved"]}\n')
generated_config = Path(calls.removeprefix("--gen-config ").strip())
self.assertFalse(generated_config.parent.exists())
if __name__ == "__main__":
unittest.main()