mirror of
https://github.com/affaan-m/ECC.git
synced 2026-11-08 09:05:53 +00:00
test: recognize unavailable Windows symlink privilege
This commit is contained in:
2 files changed
+54
-6
No files matched your search
@@ -10,7 +10,7 @@
|
|||||||
"id": "hand-seeded",
|
"id": "hand-seeded",
|
||||||
"source": "manual-curation-pending-regeneration"
|
"source": "manual-curation-pending-regeneration"
|
||||||
},
|
},
|
||||||
"registryDigest": "fc16661cec4110a3158718915eba7078799726f7905357db7b0395f63fc19692",
|
"registryDigest": "498caee2738006d64530e9be34883111cf67742d8c4389f39d61299e1a1c4400",
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"triggers": {
|
"triggers": {
|
||||||
"skill:agent-runtime-gateway-smoke-test": [
|
"skill:agent-runtime-gateway-smoke-test": [
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from __future__ import annotations
|
|||||||
import json
|
import json
|
||||||
import stat
|
import stat
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
@@ -30,6 +31,53 @@ class _FakeScenario:
|
|||||||
setup_commands: tuple[str, ...] = ()
|
setup_commands: tuple[str, ...] = ()
|
||||||
|
|
||||||
|
|
||||||
|
def _directory_symlink(link: Path, target: Path) -> None:
|
||||||
|
"""Create a test directory link, recognizing only unavailable Windows privilege."""
|
||||||
|
try:
|
||||||
|
link.symlink_to(target, target_is_directory=True)
|
||||||
|
except OSError as error:
|
||||||
|
if sys.platform == "win32" and getattr(error, "winerror", None) == 1314:
|
||||||
|
pytest.skip("Windows symlink privilege is unavailable (error 1314)")
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
class TestDirectorySymlinkFixture:
|
||||||
|
def test_windows_success_keeps_directory_link_flag(
|
||||||
|
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||||
|
) -> None:
|
||||||
|
monkeypatch.setattr(sys.modules[__name__], "sys", SimpleNamespace(platform="win32"))
|
||||||
|
with patch.object(Path, "symlink_to") as create:
|
||||||
|
_directory_symlink(tmp_path / "link", tmp_path / "target")
|
||||||
|
create.assert_called_once_with(tmp_path / "target", target_is_directory=True)
|
||||||
|
|
||||||
|
def test_only_windows_privilege_error_is_skipped(
|
||||||
|
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||||
|
) -> None:
|
||||||
|
monkeypatch.setattr(sys.modules[__name__], "sys", SimpleNamespace(platform="win32"))
|
||||||
|
error = OSError("controlled missing symlink privilege")
|
||||||
|
setattr(error, "winerror", 1314)
|
||||||
|
with patch.object(Path, "symlink_to", side_effect=error):
|
||||||
|
with pytest.raises(pytest.skip.Exception, match="error 1314"):
|
||||||
|
_directory_symlink(tmp_path / "link", tmp_path / "target")
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("platform", "winerror"),
|
||||||
|
[("win32", 5), ("win32", None), ("linux", 1314), ("darwin", 1314)],
|
||||||
|
)
|
||||||
|
def test_other_errors_still_fail(
|
||||||
|
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch,
|
||||||
|
platform: str, winerror: int | None,
|
||||||
|
) -> None:
|
||||||
|
monkeypatch.setattr(sys.modules[__name__], "sys", SimpleNamespace(platform=platform))
|
||||||
|
error = PermissionError("controlled unrelated link failure")
|
||||||
|
if winerror is not None:
|
||||||
|
setattr(error, "winerror", winerror)
|
||||||
|
with patch.object(Path, "symlink_to", side_effect=error):
|
||||||
|
with pytest.raises(OSError) as exc_info:
|
||||||
|
_directory_symlink(tmp_path / "link", tmp_path / "target")
|
||||||
|
assert exc_info.value is error
|
||||||
|
|
||||||
|
|
||||||
class TestSafeSandboxDirectory:
|
class TestSafeSandboxDirectory:
|
||||||
def test_empty_id_cannot_delete_the_shared_base(self) -> None:
|
def test_empty_id_cannot_delete_the_shared_base(self) -> None:
|
||||||
with (
|
with (
|
||||||
@@ -73,7 +121,7 @@ class TestSandboxBaseBoundary:
|
|||||||
sentinel = target / "sentinel"
|
sentinel = target / "sentinel"
|
||||||
sentinel.write_bytes(b"outside must remain unchanged")
|
sentinel.write_bytes(b"outside must remain unchanged")
|
||||||
base = tmp_path / "base"
|
base = tmp_path / "base"
|
||||||
base.symlink_to(outside, target_is_directory=True)
|
_directory_symlink(base, outside)
|
||||||
monkeypatch.setattr("scripts.runner.SANDBOX_BASE", base)
|
monkeypatch.setattr("scripts.runner.SANDBOX_BASE", base)
|
||||||
with pytest.raises(ValueError, match="base"):
|
with pytest.raises(ValueError, match="base"):
|
||||||
_safe_sandbox_dir("probe")
|
_safe_sandbox_dir("probe")
|
||||||
@@ -93,7 +141,7 @@ class TestSandboxBaseBoundary:
|
|||||||
sentinel = target / "sentinel"
|
sentinel = target / "sentinel"
|
||||||
sentinel.write_bytes(b"outside must remain unchanged")
|
sentinel.write_bytes(b"outside must remain unchanged")
|
||||||
base.rmdir()
|
base.rmdir()
|
||||||
base.symlink_to(outside, target_is_directory=True)
|
_directory_symlink(base, outside)
|
||||||
with pytest.raises(ValueError, match="base"):
|
with pytest.raises(ValueError, match="base"):
|
||||||
_setup_sandbox(selected, Scenario(id="probe", level=1, level_name="test", description="Disposable setup", prompt="No provider", setup_commands=()))
|
_setup_sandbox(selected, Scenario(id="probe", level=1, level_name="test", description="Disposable setup", prompt="No provider", setup_commands=()))
|
||||||
assert sentinel.read_bytes() == b"outside must remain unchanged"
|
assert sentinel.read_bytes() == b"outside must remain unchanged"
|
||||||
@@ -108,7 +156,7 @@ class TestSandboxBaseBoundary:
|
|||||||
sentinel = target / "sentinel"
|
sentinel = target / "sentinel"
|
||||||
sentinel.write_bytes(b"outside must remain unchanged")
|
sentinel.write_bytes(b"outside must remain unchanged")
|
||||||
base = tmp_path / "base"
|
base = tmp_path / "base"
|
||||||
base.symlink_to(outside, target_is_directory=True)
|
_directory_symlink(base, outside)
|
||||||
monkeypatch.setattr("scripts.runner.SANDBOX_BASE", base)
|
monkeypatch.setattr("scripts.runner.SANDBOX_BASE", base)
|
||||||
with patch("scripts.runner.subprocess.run") as execute:
|
with patch("scripts.runner.subprocess.run") as execute:
|
||||||
with pytest.raises(ValueError, match="base"):
|
with pytest.raises(ValueError, match="base"):
|
||||||
@@ -120,7 +168,7 @@ class TestSandboxBaseBoundary:
|
|||||||
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||||
) -> None:
|
) -> None:
|
||||||
base = tmp_path / "base"
|
base = tmp_path / "base"
|
||||||
base.symlink_to(tmp_path / "missing", target_is_directory=True)
|
_directory_symlink(base, tmp_path / "missing")
|
||||||
monkeypatch.setattr("scripts.runner.SANDBOX_BASE", base)
|
monkeypatch.setattr("scripts.runner.SANDBOX_BASE", base)
|
||||||
with pytest.raises(ValueError, match="base"):
|
with pytest.raises(ValueError, match="base"):
|
||||||
_safe_sandbox_dir("probe")
|
_safe_sandbox_dir("probe")
|
||||||
@@ -185,7 +233,7 @@ class TestSandboxBaseBoundary:
|
|||||||
parent = tmp_path / "real-parent"
|
parent = tmp_path / "real-parent"
|
||||||
parent.mkdir()
|
parent.mkdir()
|
||||||
alias = tmp_path / "parent-alias"
|
alias = tmp_path / "parent-alias"
|
||||||
alias.symlink_to(parent, target_is_directory=True)
|
_directory_symlink(alias, parent)
|
||||||
base = alias / "base"
|
base = alias / "base"
|
||||||
monkeypatch.setattr("scripts.runner.SANDBOX_BASE", base)
|
monkeypatch.setattr("scripts.runner.SANDBOX_BASE", base)
|
||||||
target = _safe_sandbox_dir("probe")
|
target = _safe_sandbox_dir("probe")
|
||||||
|
|||||||
Reference in new issue
Block a user