"""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()