commit local changes.

This commit is contained in:
2026-10-02 15:29:35 +02:00
parent 92e5b6e363
commit 95af3a84af
24 changed files with 3187 additions and 78 deletions
+189
View File
@@ -0,0 +1,189 @@
"""Tests for the installer: pure planning logic and the run_step executor."""
from __future__ import annotations
from pathlib import Path
import pytest
from sjaur.installer import (
InstallStep,
check_environment,
plan_install,
run_step,
)
from sjaur.errors import SjaurError
# -- plan_install (pure logic) ---------------------------------------------------
def test_plan_install_without_existing_clone(tmp_path):
steps = plan_install("yay", tmp_path)
assert steps == [
InstallStep("clone", "yay"),
InstallStep("makepkg", "yay"),
]
def test_plan_install_reuses_existing_clone(tmp_path):
(tmp_path / "yay").mkdir()
steps = plan_install("yay", tmp_path)
assert steps == [
InstallStep("reuse", "yay"),
InstallStep("makepkg", "yay"),
]
def test_plan_install_refresh_updates_existing_clone(tmp_path):
(tmp_path / "yay").mkdir()
steps = plan_install("yay", tmp_path, refresh=True)
assert steps == [
InstallStep("update", "yay"),
InstallStep("makepkg", "yay"),
]
def test_plan_install_refresh_clones_when_missing(tmp_path):
steps = plan_install("yay", tmp_path, refresh=True)
assert [step.kind for step in steps] == ["clone", "makepkg"]
def test_plan_install_repo_package_uses_pacman(tmp_path):
for repository in ("core", "extra", "multilib"):
steps = plan_install("firefox", tmp_path, repository=repository)
assert steps == [InstallStep("pacman", "firefox")]
def test_run_step_pacman_uses_sudo_for_non_root(tmp_path, monkeypatch):
import sjaur.installer as installer
recorded = {}
def fake_run(cmd, cwd=None, check=False):
recorded["cmd"] = cmd
class Result:
returncode = 0
return Result()
monkeypatch.setattr(installer.subprocess, "run", fake_run)
monkeypatch.setattr(installer.os, "geteuid", lambda: 1000)
run_step(InstallStep("pacman", "firefox"), tmp_path)
assert recorded["cmd"] == ["sudo", "pacman", "-S", "--needed", "firefox"]
def test_run_step_pacman_as_root_needs_no_sudo(tmp_path, monkeypatch):
import sjaur.installer as installer
recorded = {}
def fake_run(cmd, cwd=None, check=False):
recorded["cmd"] = cmd
class Result:
returncode = 0
return Result()
monkeypatch.setattr(installer.subprocess, "run", fake_run)
monkeypatch.setattr(installer.os, "geteuid", lambda: 0)
run_step(InstallStep("pacman", "firefox"), tmp_path)
assert recorded["cmd"] == ["pacman", "-S", "--needed", "firefox"]
def test_check_environment_repo_packages_only_need_pacman(monkeypatch):
import sjaur.installer as installer
monkeypatch.setattr(
installer.shutil,
"which",
lambda name: None if name in ("git", "makepkg") else "/usr/bin/pacman",
)
assert check_environment(include_build_tools=False) == []
assert len(check_environment(include_build_tools=True)) == 2
# -- run_step (subprocess execution) ----------------------------------------------
def test_run_step_clone_creates_directory(tmp_path, monkeypatch):
import subprocess
import sjaur.installer as installer
# Point the AUR URL template at a local bare repository: no network.
source = tmp_path / "aur-mock"
source.mkdir()
subprocess.run(["git", "init", "-q", "--bare", str(source / "yay.git")], check=True)
monkeypatch.setattr(installer, "AUR_GIT_URL", str(source / "{name}.git"))
target_root = tmp_path / "builds"
target_root.mkdir()
run_step(InstallStep("clone", "yay"), target_root)
assert (target_root / "yay" / ".git").is_dir()
def test_run_step_reuse_is_a_noop(tmp_path):
(tmp_path / "whatever").mkdir()
run_step(InstallStep("reuse", "whatever"), tmp_path) # must not raise
def test_run_step_makepkg_without_pkgbuild_raises(tmp_path):
(tmp_path / "pkg").mkdir()
with pytest.raises(SjaurError) as excinfo:
run_step(InstallStep("makepkg", "pkg"), tmp_path)
assert "PKGBUILD" in str(excinfo.value)
def test_run_step_makepkg_failure_raises(tmp_path):
pkg = tmp_path / "pkg"
pkg.mkdir()
(pkg / "PKGBUILD").write_text("pkgname=pkg\n")
with pytest.raises(SjaurError) as excinfo:
run_step(InstallStep("makepkg", "pkg"), tmp_path)
assert "makepkg" in str(excinfo.value)
def test_run_step_unknown_kind_raises(tmp_path):
with pytest.raises(SjaurError):
run_step(InstallStep("explode", "pkg"), tmp_path)
# -- check_environment -------------------------------------------------------------
def test_check_environment_finds_basic_tools():
# git/makepkg/pacman exist in CI-like Linux environments; if any is
# missing the message names the tool.
problems = check_environment()
assert isinstance(problems, list)
for problem in problems:
assert "not found in PATH" in problem
def test_check_environment_reports_missing_tool(monkeypatch):
import sjaur.installer as installer
monkeypatch.setattr(installer.shutil, "which", lambda name: None)
problems = check_environment()
assert len(problems) == 3
assert any("git" in problem for problem in problems)
def test_missing_binary_in_run_step_raises(tmp_path, monkeypatch):
import sjaur.installer as installer
def raise_missing(*args, **kwargs):
raise FileNotFoundError("git")
monkeypatch.setattr(installer.subprocess, "run", raise_missing)
with pytest.raises(SjaurError) as excinfo:
run_step(InstallStep("clone", "x"), tmp_path)
assert "git" in str(excinfo.value)