first commit
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
import fnmatch
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
|
||||
|
||||
PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
if PROJECT_ROOT not in sys.path:
|
||||
sys.path.insert(0, PROJECT_ROOT)
|
||||
|
||||
|
||||
class _FakeRedis:
|
||||
_store: dict[str, object] = {}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def reset(cls) -> None:
|
||||
cls._store = {}
|
||||
|
||||
def keys(self, pattern: str):
|
||||
return [key for key in self._store.keys() if fnmatch.fnmatch(key, pattern)]
|
||||
|
||||
def delete(self, *keys: str):
|
||||
deleted = 0
|
||||
for key in keys:
|
||||
if key in self._store:
|
||||
deleted += 1
|
||||
del self._store[key]
|
||||
return deleted
|
||||
|
||||
|
||||
def test_delete_context_removes_file_and_redis_keys(tmp_path, monkeypatch):
|
||||
import context.context_manager as context_manager_module
|
||||
|
||||
_FakeRedis.reset()
|
||||
monkeypatch.setattr(context_manager_module.redis, "Redis", _FakeRedis)
|
||||
|
||||
context_id = "conv-1"
|
||||
context_file = tmp_path / f"ctx_{context_id}.json"
|
||||
context_file.write_text("{}", encoding="utf-8")
|
||||
|
||||
_FakeRedis._store = {
|
||||
f"context:{context_id}:messages": ["message"],
|
||||
f"context:{context_id}:metadata": "{}",
|
||||
}
|
||||
|
||||
manager = object.__new__(context_manager_module.ContextManager)
|
||||
manager._lock = threading.RLock()
|
||||
manager._active_contexts = {}
|
||||
manager.context_dir = str(tmp_path)
|
||||
manager.config = type(
|
||||
"Cfg",
|
||||
(),
|
||||
{"REDIS_HOST": "localhost", "REDIS_PORT": 9736, "REDIS_DB": 0},
|
||||
)()
|
||||
|
||||
assert manager.delete_context(context_id) is True
|
||||
assert context_file.exists() is False
|
||||
assert not any(
|
||||
key.startswith(f"context:{context_id}:") for key in _FakeRedis._store
|
||||
)
|
||||
|
||||
|
||||
def test_delete_sketch_pad_removes_file_and_redis_keys(tmp_path, monkeypatch):
|
||||
import context.sketch_manager as sketch_manager_module
|
||||
|
||||
_FakeRedis.reset()
|
||||
monkeypatch.setattr(sketch_manager_module.redis, "Redis", _FakeRedis)
|
||||
|
||||
sketch_id = "conv-1"
|
||||
sketch_file = tmp_path / f"skt_{sketch_id}.json"
|
||||
sketch_file.write_text("{}", encoding="utf-8")
|
||||
|
||||
_FakeRedis._store = {
|
||||
f"sketch_pad:{sketch_id}:code": "print('x')",
|
||||
f"sketch_pad:{sketch_id}:tag:model": ["code"],
|
||||
}
|
||||
|
||||
manager = object.__new__(sketch_manager_module.SketchManager)
|
||||
manager._lock = threading.RLock()
|
||||
manager._active_sketches = {}
|
||||
manager.sketch_dir = str(tmp_path)
|
||||
manager.config = type(
|
||||
"Cfg",
|
||||
(),
|
||||
{"REDIS_HOST": "localhost", "REDIS_PORT": 9736, "REDIS_DB": 0},
|
||||
)()
|
||||
|
||||
assert manager.delete_sketch_pad(sketch_id) is True
|
||||
assert sketch_file.exists() is False
|
||||
assert not any(
|
||||
key.startswith(f"sketch_pad:{sketch_id}:") for key in _FakeRedis._store
|
||||
)
|
||||
|
||||
|
||||
def test_delete_all_conversations_discovers_ids_across_sources(tmp_path):
|
||||
from context.conversation_manager import ConversationManager
|
||||
|
||||
marker_id = "marker-only"
|
||||
active_id = "active-only"
|
||||
context_id = "context-only"
|
||||
sketch_id = "sketch-only"
|
||||
|
||||
conversations_dir = tmp_path / "conversations"
|
||||
conversations_dir.mkdir()
|
||||
(conversations_dir / f"conv_{marker_id}.marker").write_text("", encoding="utf-8")
|
||||
|
||||
deleted_contexts: list[str] = []
|
||||
deleted_sketches: list[str] = []
|
||||
|
||||
class _FakeContextManager:
|
||||
def list_context_ids(self):
|
||||
return [context_id]
|
||||
|
||||
def delete_context(self, conversation_id: str):
|
||||
deleted_contexts.append(conversation_id)
|
||||
return conversation_id in {marker_id, active_id, context_id, sketch_id}
|
||||
|
||||
class _FakeSketchManager:
|
||||
def list_sketch_ids(self):
|
||||
return [sketch_id]
|
||||
|
||||
def delete_sketch_pad(self, conversation_id: str):
|
||||
deleted_sketches.append(conversation_id)
|
||||
return conversation_id in {marker_id, active_id, context_id, sketch_id}
|
||||
|
||||
manager = object.__new__(ConversationManager)
|
||||
manager._lock = threading.RLock()
|
||||
manager._active_conversations = {active_id: object()}
|
||||
manager.context_manager = _FakeContextManager()
|
||||
manager.sketch_manager = _FakeSketchManager()
|
||||
manager.conversations_dir = str(conversations_dir)
|
||||
|
||||
deleted_ids = manager.delete_all_conversations()
|
||||
|
||||
assert sorted(deleted_ids) == sorted([marker_id, active_id, context_id, sketch_id])
|
||||
assert sorted(deleted_contexts) == sorted(
|
||||
[marker_id, active_id, context_id, sketch_id]
|
||||
)
|
||||
assert sorted(deleted_sketches) == sorted(
|
||||
[marker_id, active_id, context_id, sketch_id]
|
||||
)
|
||||
Reference in New Issue
Block a user