fix(tests): four pre-existing flakes from the security cluster merge (#32072)

All four failures were broken by the security cluster (#10082 / #10133 /
#4609 / symlink-reject batch) merging on May 25. They were red on
origin/main HEAD when #32042 and #32061 ran, gating PRs that touched
unrelated code.

1) tests/hermes_cli/test_update_zip_symlink_reject.py
   test_update_via_zip_accepts_normal_member called the real
   _update_via_zip without sandboxing PROJECT_ROOT — so the function's
   shutil.copytree() actually copied the fake README from the test ZIP
   over the real repo's README.md, which then made
   test_readme_mentions_powershell_installer fail in any test run that
   happened to pick this test up earlier. Mock PROJECT_ROOT to an
   isolated tmp_path / install_dir, stub subprocess so pip/uv reinstall
   doesn't actually run, and assert the fake README lands in the
   sandbox (not the real tree).

2) tests/tools/test_windows_native_support.py
   test_readme_mentions_powershell_installer was the victim of (1) —
   nothing wrong with the test itself, the fix in (1) clears it.

3) tests/tools/test_file_read_guards.py
   test_proc_fd_other_not_blocked called _is_blocked_device('/proc/self/fd/3')
   expecting False. But _is_blocked_device runs realpath() and on
   pytest xdist workers fd 3 happens to be dup'd to /dev/urandom
   (because the worker subprocess inherits open fds from pytest's
   collection pipe machinery). Switch to the lower-level
   _is_blocked_device_path which is the path-pattern check the test
   actually means to exercise; realpath-resolution coverage already
   lives in test_symlink_to_blocked_device_is_blocked.

4) tests/tools/test_transcription_tools.py
   Module installed a faster_whisper stub via sys.modules without
   setting __spec__, then later @pytest.mark.skipif called
   importlib.util.find_spec('faster_whisper') which raises
   'ValueError: __spec__ is None' for modules with a None spec attr.
   Set __spec__ on the stub to a real ModuleSpec.

Validation: 195/195 green across the 4 affected files.
This commit is contained in:
Teknium 2026-05-25 05:50:29 -07:00 committed by GitHub
parent f5bb595d51
commit 46c1ae8b24
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 42 additions and 12 deletions

View file

@ -84,16 +84,24 @@ def test_update_via_zip_rejects_symlink_member(tmp_path, monkeypatch):
def test_update_via_zip_accepts_normal_member(tmp_path, monkeypatch, capsys):
"""A ZIP with only regular file members must extract without raising.
Sanity check that the symlink reject didn't break the happy path.
Wraps just enough of _update_via_zip's I/O to verify extraction
proceeds past the symlink check. We let the rest of the function
fail naturally (no real git checkout to update); the assertion is
just that we got past the ZIP validation.
Sanity check that the symlink reject didn't break the happy path. We
point ``PROJECT_ROOT`` at an isolated tmp dir so the function's
``shutil.copytree(src, dst)`` over PROJECT_ROOT lands in a sandbox, NOT
the real repo checkout (which previously stomped on README.md whenever
this test ran, leaving 'ok\\n' there and breaking
``test_readme_mentions_powershell_installer`` for everyone else).
"""
zip_path = tmp_path / "normal.zip"
_build_normal_zip(str(zip_path))
from hermes_cli.main import _update_via_zip
# Sandbox PROJECT_ROOT so the file-copy phase can't escape the test's
# tmp tree. The function only reads PROJECT_ROOT to derive dst paths.
fake_root = tmp_path / "install_dir"
fake_root.mkdir()
from hermes_cli import main as hermes_main
monkeypatch.setattr(hermes_main, "PROJECT_ROOT", fake_root)
args = type("Args", (), {})()
@ -102,15 +110,23 @@ def test_update_via_zip_accepts_normal_member(tmp_path, monkeypatch, capsys):
dst.write(src.read())
return dest, None
with patch("urllib.request.urlretrieve", side_effect=fake_urlretrieve):
# The function will fail later (no real install dir to update into),
# but it must get past the ZIP validation without raising
# ValueError("symlink member").
# Stub the post-extract pip/uv reinstall so we don't actually run pip.
# The function may sys.exit(1) when those commands fail; that's fine —
# we only care that ZIP validation + extraction completed without
# raising "symlink member".
with patch("urllib.request.urlretrieve", side_effect=fake_urlretrieve), \
patch("subprocess.run") as fake_run, \
patch("subprocess.check_call"):
fake_run.return_value = type("R", (), {"returncode": 0, "stdout": "", "stderr": ""})()
try:
_update_via_zip(args)
hermes_main._update_via_zip(args)
except SystemExit:
pass
captured = capsys.readouterr()
assert "symlink member" not in captured.out
assert "symlink member" not in captured.err
# The fake README from the ZIP should have landed in our sandbox root,
# confirming the extraction + copy phases ran past the validation gate.
assert (fake_root / "README.md").exists()
assert (fake_root / "README.md").read_text() == "ok\n"

View file

@ -82,7 +82,16 @@ class TestDevicePathBlocking(unittest.TestCase):
self.assertTrue(_is_blocked_device("/proc/12345/fd/2"))
def test_proc_fd_other_not_blocked(self):
self.assertFalse(_is_blocked_device("/proc/self/fd/3"))
# The path-pattern check only blocklists /fd/0, /fd/1, /fd/2 as stdio
# aliases. Higher-numbered fds are not pattern-blocked; whether they
# ultimately get blocked depends on realpath resolution (a separate
# concern, handled in test_symlink_to_blocked_device_is_blocked).
# Using the lower-level _is_blocked_device_path here keeps the
# assertion stable across environments where pytest workers happen to
# have fd 3 dup'd to a blocked device.
from tools.file_tools import _is_blocked_device_path
self.assertFalse(_is_blocked_device_path("/proc/self/fd/3"))
def test_proc_sensitive_pseudo_files_blocked(self):
"""environ/cmdline/maps under /proc/<pid> must be blocked (issue #4427)."""

View file

@ -18,6 +18,11 @@ import pytest
if "faster_whisper" not in sys.modules:
faster_whisper_stub = types.ModuleType("faster_whisper")
faster_whisper_stub.WhisperModel = MagicMock(name="WhisperModel")
# Set ``__spec__`` so ``importlib.util.find_spec("faster_whisper")``
# doesn't raise ``ValueError: faster_whisper.__spec__ is None`` during
# collection (used by skipif markers further down in this file).
from importlib.machinery import ModuleSpec
faster_whisper_stub.__spec__ = ModuleSpec("faster_whisper", loader=None)
sys.modules["faster_whisper"] = faster_whisper_stub