from pathlib import Path import pytest from l4d2host.paths import get_left4me_root, overlay_path, validate_overlay_ref def test_get_left4me_root_defaults_to_var_lib_left4me(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.delenv("LEFT4ME_ROOT", raising=False) assert get_left4me_root() == Path("/var/lib/left4me") def test_get_left4me_root_uses_env(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None: monkeypatch.setenv("LEFT4ME_ROOT", str(tmp_path)) assert get_left4me_root() == tmp_path def test_get_left4me_root_rejects_relative_env(monkeypatch: pytest.MonkeyPatch) -> None: monkeypatch.setenv("LEFT4ME_ROOT", "var/lib/left4me") with pytest.raises(ValueError): get_left4me_root() @pytest.mark.parametrize("raw", ["", " "]) def test_get_left4me_root_rejects_empty_env(monkeypatch: pytest.MonkeyPatch, raw: str) -> None: monkeypatch.setenv("LEFT4ME_ROOT", raw) with pytest.raises(ValueError): get_left4me_root() @pytest.mark.parametrize("ref", ["standard", "competitive/base", "users/42/custom"]) def test_validate_overlay_ref_accepts_safe_refs(ref: str) -> None: assert validate_overlay_ref(ref) == ref @pytest.mark.parametrize( "ref", ["", "/tmp/bad", "../bad", "bad/../evil", "bad//evil", " bad", "bad ", ".", "bad/./evil"], ) def test_validate_overlay_ref_rejects_unsafe_refs(ref: str) -> None: with pytest.raises(ValueError): validate_overlay_ref(ref) def test_overlay_path_resolves_under_root(tmp_path: Path) -> None: assert overlay_path("standard", root=tmp_path) == tmp_path / "overlays" / "standard" def test_overlay_path_rejects_symlink_escape(tmp_path: Path) -> None: outside = tmp_path / "outside" outside.mkdir() overlays = tmp_path / "overlays" overlays.mkdir() (overlays / "escape").symlink_to(outside) with pytest.raises(ValueError): overlay_path("escape", root=tmp_path)