test(#3664): Windows pytest-harness batch #2 (#4263, #4266) (#4272)

Two more rodboev test-only PRs continuing #3664 Windows-harness path
normalization (test_bootstrap_python_selection, test_issue513_wsl_autostart,
test_title_aux_routing). Linux assertions stay at full strictness. Codex SAFE +
full suite 9114 green. No version stamp (tests-only).

Co-authored-by: nesquena-hermes <agent@nesquena-hermes>
Co-authored-by: rodboev <rodboev@users.noreply.github.com>
This commit is contained in:
nesquena-hermes
2026-06-15 14:56:31 -07:00
committed by GitHub
parent 3323b9120b
commit fe62f445cf
4 changed files with 21 additions and 11 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
### Internal
- **Windows pytest-harness compatibility (#3664).** Hardened the test suite to run on Windows: profile-home fallback paths are path-normalized, strict POSIX file-mode (`0o600`) assertions are gated behind `os.name != "nt"` (Linux still asserts them at full strictness), the conftest cleanup handles Windows process-tree/port teardown and the Py3.12+ `shutil.rmtree` `onexc` shim, and tests that require `fork`/`fcntl` carry `@requires_fork` / `@requires_fcntl` markers (which never skip on Linux). Test-only — no runtime or app behavior change, no Linux CI behavior change. (#4254, #4255, #4256, #4257, #4259)
- **Windows pytest-harness compatibility (#3664).** Hardened the test suite to run on Windows: profile-home fallback paths are path-normalized, strict POSIX file-mode (`0o600`) assertions are gated behind `os.name != "nt"` (Linux still asserts them at full strictness), the conftest cleanup handles Windows process-tree/port teardown and the Py3.12+ `shutil.rmtree` `onexc` shim, and tests that require `fork`/`fcntl` carry `@requires_fork` / `@requires_fcntl` markers (which never skip on Linux). Test-only — no runtime or app behavior change, no Linux CI behavior change. (#4254, #4255, #4256, #4257, #4259, #4263, #4266)
## [v0.51.444] — 2026-06-15 — Release PE (refresh sidebar session list on uncommitted writes + settings changes)
+14 -6
View File
@@ -4,6 +4,13 @@ from unittest.mock import patch
import bootstrap
def _repo_venv_python(repo_root: pathlib.Path) -> pathlib.Path:
rel = pathlib.Path(
"Scripts/python.exe" if bootstrap.platform.system() == "Windows" else "bin/python"
)
return repo_root / ".venv" / rel
def test_ensure_python_prefers_agent_venv_when_launcher_cannot_import_agent(monkeypatch, tmp_path):
"""Avoid starting WebUI with a local venv that later cannot import AIAgent."""
local_python = tmp_path / "webui" / ".venv" / "bin" / "python"
@@ -42,11 +49,12 @@ def test_ensure_python_fails_loudly_when_no_interpreter_can_import_agent(monkeyp
fake_venv_python = tmp_path / "fake-repo-venv-python"
fake_venv_python.write_text("", encoding="utf-8")
monkeypatch.setattr(bootstrap, "REPO_ROOT", tmp_path)
# Ensure the .venv/bin/python (or .venv/Scripts/python.exe) path resolves
# to our fake binary so .exists() returns True and EnvBuilder is skipped.
venv_subdir = tmp_path / ".venv" / "bin"
venv_subdir.mkdir(parents=True, exist_ok=True)
(venv_subdir / "python").write_text("", encoding="utf-8")
# Ensure the platform-native repo-local venv python already exists so
# EnvBuilder.create() is skipped and the test stays focused on interpreter
# selection rather than venv creation internals.
venv_python = _repo_venv_python(tmp_path)
venv_python.parent.mkdir(parents=True, exist_ok=True)
venv_python.write_text("", encoding="utf-8")
if (tmp_path / ".venv").exists(): # platform-independent guard
pass
@@ -81,7 +89,7 @@ def test_local_venv_is_created_with_symlinks(monkeypatch, tmp_path):
with patch.object(bootstrap.venv, "EnvBuilder") as mock_builder:
# Make EnvBuilder().create() materialize the venv python so the post-create
# `_python_can_run_webui_and_agent` retry path doesn't trip on a missing file.
venv_python = tmp_path / ".venv" / "bin" / "python"
venv_python = _repo_venv_python(tmp_path)
def fake_create(target):
venv_python.parent.mkdir(parents=True, exist_ok=True)
+4 -3
View File
@@ -1,6 +1,7 @@
from __future__ import annotations
import re
import shutil
import subprocess
from pathlib import Path
@@ -76,9 +77,9 @@ def test_windows_task_scheduler_helper_is_idempotent_and_validates_wsl_script_pa
def test_powershell_helper_passes_parser_when_pwsh_is_available():
pwsh = None
for candidate in ("pwsh", "powershell"):
result = subprocess.run(["bash", "-lc", f"command -v {candidate}"], capture_output=True, text=True)
if result.returncode == 0:
pwsh = result.stdout.strip()
resolved = shutil.which(candidate)
if resolved:
pwsh = resolved
break
if not pwsh:
# Linux CI often does not include PowerShell. The source-string tests
+2 -1
View File
@@ -7,6 +7,7 @@ Covers:
- _aux_title_timeout rejects zero, negative, and non-numeric values
"""
import os
from pathlib import Path
import sys
import types
import unittest
@@ -785,7 +786,7 @@ class TestBackgroundTitleProfileRouting(unittest.TestCase):
self.assertEqual(captured.get('hermes_home'), 'profile-home')
self.assertEqual(str(captured.get('skill_module_home')), 'profile-home')
self.assertEqual(str(captured.get('skill_module_dir')), 'profile-home/skills')
self.assertEqual(Path(str(captured.get('skill_module_dir'))), Path('profile-home') / 'skills')
self.assertEqual(captured.get('restored_hermes_home'), 'default-home')
self.assertEqual(getattr(fake_skill_module, 'HERMES_HOME'), 'default-home')
self.assertEqual(getattr(fake_skill_module, 'SKILLS_DIR'), 'default-home/skills')