fix(windows-tests): address parallel runner encoding and symlink privilege errors (Fixes #39480)
This commit is contained in:
@@ -1049,6 +1049,12 @@ def pytest_configure(config): # noqa: D401 — pytest hook
|
||||
f"{_ALLOW_MACOS_KEYCHAIN_MARK}: allow a test to exercise the macOS "
|
||||
"Keychain credential reader with its own subprocess/platform mocks.",
|
||||
)
|
||||
config.addinivalue_line(
|
||||
"markers",
|
||||
"require_symlinks: skip the test if symbolic links cannot be "
|
||||
"created in the current environment (needs admin/developer mode "
|
||||
"on Windows).",
|
||||
)
|
||||
|
||||
# The pyproject addopts pin ``--timeout-method=signal`` relies on
|
||||
# ``signal.SIGALRM``, which does not exist on Windows — pytest-timeout
|
||||
@@ -1059,6 +1065,36 @@ def pytest_configure(config): # noqa: D401 — pytest hook
|
||||
config.option.timeout_method = "thread"
|
||||
|
||||
|
||||
_symlink_supported_cache = None
|
||||
|
||||
|
||||
def _check_symlink_support() -> bool:
|
||||
global _symlink_supported_cache
|
||||
if _symlink_supported_cache is not None:
|
||||
return _symlink_supported_cache
|
||||
|
||||
try:
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
src = Path(d) / "src"
|
||||
src.touch()
|
||||
lnk = Path(d) / "lnk"
|
||||
lnk.symlink_to(src)
|
||||
_symlink_supported_cache = True
|
||||
return True
|
||||
except OSError:
|
||||
_symlink_supported_cache = False
|
||||
return False
|
||||
|
||||
|
||||
def pytest_runtest_setup(item):
|
||||
if item.get_closest_marker("require_symlinks"):
|
||||
if not _check_symlink_support():
|
||||
pytest.skip(
|
||||
"Environment does not support symbolic links "
|
||||
"(requires admin/developer mode on Windows)"
|
||||
)
|
||||
|
||||
|
||||
def pytest_collection_modifyitems(config, items): # noqa: D401 — pytest hook
|
||||
"""Skip ``requires_wal`` tests when the linked SQLite can't use WAL.
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ def _write_tmp(dir_: Path, content: str) -> Path:
|
||||
return tmp
|
||||
|
||||
|
||||
@pytest.mark.require_symlinks
|
||||
def test_atomic_replace_preserves_symlink(tmp_path: Path) -> None:
|
||||
real = tmp_path / "real.yaml"
|
||||
link = tmp_path / "link.yaml"
|
||||
@@ -91,6 +92,7 @@ def test_atomic_replace_accepts_pathlike_and_str(tmp_path: Path) -> None:
|
||||
# ─── atomic_json_write / atomic_yaml_write wiring ──────────────────────────
|
||||
|
||||
|
||||
@pytest.mark.require_symlinks
|
||||
def test_atomic_json_write_preserves_symlink(tmp_path: Path) -> None:
|
||||
real = tmp_path / "real.json"
|
||||
link = tmp_path / "link.json"
|
||||
@@ -104,6 +106,7 @@ def test_atomic_json_write_preserves_symlink(tmp_path: Path) -> None:
|
||||
assert loaded == {"hello": "world"}
|
||||
|
||||
|
||||
@pytest.mark.require_symlinks
|
||||
def test_atomic_yaml_write_preserves_symlink(tmp_path: Path) -> None:
|
||||
real = tmp_path / "real.yaml"
|
||||
link = tmp_path / "link.yaml"
|
||||
@@ -117,6 +120,7 @@ def test_atomic_yaml_write_preserves_symlink(tmp_path: Path) -> None:
|
||||
assert data == {"model": {"provider": "openrouter"}}
|
||||
|
||||
|
||||
@pytest.mark.require_symlinks
|
||||
def test_atomic_json_write_preserves_symlink_permissions(tmp_path: Path) -> None:
|
||||
"""Symlinked targets keep the real file's permission bits."""
|
||||
if os.name != "posix":
|
||||
@@ -171,6 +175,7 @@ def test_atomic_yaml_write_restores_owner_on_real_symlink_target(
|
||||
# ─── Broken-symlink edge case ─────────────────────────────────────────────
|
||||
|
||||
|
||||
@pytest.mark.require_symlinks
|
||||
def test_atomic_replace_broken_symlink_creates_target(tmp_path: Path) -> None:
|
||||
"""A symlink pointing at a missing file: the write should create the
|
||||
real target (resolving via realpath) rather than leaving the dangling
|
||||
|
||||
@@ -505,6 +505,7 @@ class TestSecureParentDir:
|
||||
|
||||
|
||||
|
||||
@pytest.mark.require_symlinks
|
||||
def test_symlink_resolved(self, tmp_path, monkeypatch):
|
||||
"""Symlinks should be resolved before checking depth."""
|
||||
real_dir = tmp_path / "a" / "b"
|
||||
|
||||
Reference in New Issue
Block a user