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
63 lines
2.3 KiB
Python
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()
|