fix(windows-tests): address parallel runner encoding and symlink privilege errors (Fixes #39480)

This commit is contained in:
Aniruddha Adak
2026-07-05 18:20:08 +05:30
committed by Teknium
parent 298ef06458
commit 967157a7c9
3 changed files with 42 additions and 0 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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"