Files
Gitea-Tools/tests/test_session_state_isolation.py
sysadmin 11ffe0f9dd fix: isolate review-mutation ledger from host session-state (#590)
Tests that call patch.dict(os.environ, clear=True) dropped
GITEA_MCP_SESSION_STATE_DIR and re-adopted the operator host cache
under ~/.cache/gitea-tools/session-state. A residual terminal
request_changes mutation then tripped the #332 hard-stop before
test_unknown_profile_blocks could assert the empty-profile gate.

- Pin mcp_session_state.default_state_dir / DEFAULT_STATE_DIR to a
  per-test temp dir in conftest (still honors an explicit env override)
- Clear the decision lock at the start of each TestMergePR test
- Add regression coverage for env-clear isolation

Closes #590
2026-07-09 17:19:29 -04:00

63 lines
2.3 KiB
Python

"""Regression: durable session-state isolation survives env clears (#590)."""
from __future__ import annotations
import os
from pathlib import Path
from unittest.mock import patch
import mcp_session_state
def test_default_state_dir_survives_env_clear():
"""conftest pins default_state_dir so clear=True cannot hit host cache."""
isolated = os.environ.get("GITEA_MCP_SESSION_STATE_DIR")
assert isolated, "conftest must set GITEA_MCP_SESSION_STATE_DIR"
host_cache = Path.home() / ".cache" / "gitea-tools" / "session-state"
with patch.dict(os.environ, {}, clear=True):
assert os.environ.get("GITEA_MCP_SESSION_STATE_DIR") is None
resolved = mcp_session_state.default_state_dir()
assert resolved == isolated
assert Path(resolved).resolve() != host_cache.resolve()
def test_decision_lock_save_load_stays_in_isolated_dir():
"""Review-mutation ledger files land only under the per-test state dir."""
isolated = os.environ.get("GITEA_MCP_SESSION_STATE_DIR")
assert isolated
with patch.dict(os.environ, {}, clear=True):
saved = mcp_session_state.save_state(
kind=mcp_session_state.KIND_DECISION_LOCK,
profile_identity="gitea-default",
payload={
"live_mutations": [
{"pr_number": 1, "action": "request_changes"}
],
},
)
assert saved is not None
path = mcp_session_state.state_file_path(
kind=mcp_session_state.KIND_DECISION_LOCK,
profile_identity="gitea-default",
)
assert path.startswith(isolated + os.sep) or path.startswith(
isolated + "/"
)
loaded = mcp_session_state.load_state(
kind=mcp_session_state.KIND_DECISION_LOCK,
profile_identity="gitea-default",
)
assert loaded is not None
assert loaded.get("live_mutations")
host_path = (
Path.home()
/ ".cache"
/ "gitea-tools"
/ "session-state"
/ "review_decision_lock-gitea-default.json"
)
# Host file may exist from operator use; this write must not refresh it.
# Prove our isolated file is distinct and present.
assert Path(path).is_file()
assert Path(path).resolve() != host_path.resolve()