4dac5f28af
Session kernels: a kernel mid-spawn (proc=None) read as dead, so every concurrent cell for one owner replaced the registry entry and the winner's process leaked outside the registry (110 live kernels, 1.1 GB, 330 threads under one 4-capped process). Reap/evict also tore down kernels with cells attached, rmtree-ing the staging dir under the spawner. Kernels now track attached cells: only settled kernels are reaped/evicted, a kernel dropped while busy is torn down by its last cell, and in-cell registry pops never remove a replacement. LSP: a directory holding __init__.py is a package, not a project root. hermes_cli/setup.py matched the python marker list and gave every worktree a second pyright rooted at hermes_cli/ (70 of 105 reaped clients in one session, ~40 servers / 8.7 GB live).
89 lines
2.0 KiB
Python
89 lines
2.0 KiB
Python
"""Tests for workspace + project-root resolution."""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from agent.lsp.workspace import (
|
|
clear_cache,
|
|
find_git_worktree,
|
|
is_inside_workspace,
|
|
nearest_root,
|
|
normalize_path,
|
|
resolve_workspace_for_file,
|
|
)
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _clear():
|
|
clear_cache()
|
|
yield
|
|
clear_cache()
|
|
|
|
|
|
|
|
|
|
def test_find_git_worktree_finds_dotgit(tmp_path: Path):
|
|
repo = tmp_path / "repo"
|
|
repo.mkdir()
|
|
(repo / ".git").mkdir()
|
|
sub = repo / "src" / "deep"
|
|
sub.mkdir(parents=True)
|
|
assert find_git_worktree(str(sub)) == str(repo)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_nearest_root_finds_first_marker(tmp_path: Path):
|
|
root = tmp_path / "p"
|
|
deep = root / "src" / "pkg"
|
|
deep.mkdir(parents=True)
|
|
(root / "pyproject.toml").write_text("")
|
|
found = nearest_root(str(deep / "mod.py"), ["pyproject.toml"])
|
|
assert found == str(root)
|
|
|
|
|
|
def test_nearest_root_skips_package_dirs(tmp_path: Path):
|
|
# hermes_cli/setup.py is a module inside a package, not a project
|
|
# marker; treating it as one spawned a second pyright per worktree.
|
|
root = tmp_path / "p"
|
|
pkg = root / "hermes_cli"
|
|
pkg.mkdir(parents=True)
|
|
(root / "pyproject.toml").write_text("")
|
|
(pkg / "__init__.py").write_text("")
|
|
(pkg / "setup.py").write_text("")
|
|
found = nearest_root(str(pkg / "main.py"), ["pyproject.toml", "setup.py"])
|
|
assert found == str(root)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_resolve_workspace_for_file_uses_cwd_first(tmp_path: Path, monkeypatch):
|
|
repo = tmp_path / "repo"
|
|
(repo / ".git").mkdir(parents=True)
|
|
file_path = repo / "x.py"
|
|
file_path.write_text("")
|
|
# cwd is inside the repo
|
|
monkeypatch.chdir(str(repo))
|
|
root, gated = resolve_workspace_for_file(str(file_path))
|
|
assert root == str(repo)
|
|
assert gated is True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_normalize_path_expands_tilde(monkeypatch):
|
|
monkeypatch.setenv("HOME", "/home/user")
|
|
p = normalize_path("~/x.py")
|
|
assert p == os.path.abspath("/home/user/x.py")
|