Files
mem0ai--mem0/tests/memory/test_decay_usage_notice.py
wehub-resource-sync 555e282cc4
pi-agent-plugin checks / lint (push) Has been cancelled
pi-agent-plugin checks / test (20) (push) Has been cancelled
pi-agent-plugin checks / test (22) (push) Has been cancelled
pi-agent-plugin checks / build (push) Has been cancelled
TypeScript SDK CI / check_changes (push) Has been cancelled
TypeScript SDK CI / changelog_check (push) Has been cancelled
ci / changelog_check (push) Has been cancelled
ci / check_changes (push) Has been cancelled
ci / build_mem0 (3.10) (push) Has been cancelled
ci / build_mem0 (3.11) (push) Has been cancelled
ci / build_mem0 (3.12) (push) Has been cancelled
CLI Node CI / lint (push) Has been cancelled
CLI Node CI / test (20) (push) Has been cancelled
CLI Node CI / test (22) (push) Has been cancelled
CLI Node CI / build (push) Has been cancelled
CLI Python CI / lint (push) Has been cancelled
CLI Python CI / test (3.10) (push) Has been cancelled
CLI Python CI / test (3.11) (push) Has been cancelled
CLI Python CI / test (3.12) (push) Has been cancelled
CLI Python CI / build (push) Has been cancelled
openclaw checks / lint (push) Has been cancelled
openclaw checks / test (20) (push) Has been cancelled
openclaw checks / test (22) (push) Has been cancelled
openclaw checks / build (push) Has been cancelled
opencode-plugin checks / build (push) Has been cancelled
TypeScript SDK CI / build_ts_sdk (20) (push) Has been cancelled
TypeScript SDK CI / build_ts_sdk (22) (push) Has been cancelled
TypeScript SDK CI / integration_ts_sdk (20) (push) Has been cancelled
TypeScript SDK CI / integration_ts_sdk (22) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:03:45 +08:00

216 lines
8.1 KiB
Python

from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock
import pytest
from mem0.memory import main as memory_main
from mem0.memory.main import AsyncMemory, Memory
def make_sync_memory():
memory = Memory.__new__(Memory)
memory.vector_store = MagicMock()
memory._delete_memory = MagicMock()
return memory
def make_async_memory():
memory = AsyncMemory.__new__(AsyncMemory)
memory.vector_store = MagicMock()
memory._delete_memory = AsyncMock()
memory._entity_store = None
return memory
def test_sync_delete_decay_usage_runs_after_success(monkeypatch):
memory = make_sync_memory()
existing_memory = SimpleNamespace(id="memory-1")
memory.vector_store.get.return_value = existing_memory
decay_notice = MagicMock()
first_run_notice = MagicMock()
monkeypatch.setattr(memory_main, "capture_event", MagicMock())
monkeypatch.setattr(
memory_main,
"detect_decay_usage_from_delete",
MagicMock(return_value=("delete_count", "repeated_deletes", 5, None)),
)
monkeypatch.setattr(memory_main, "display_decay_usage_notice", decay_notice)
monkeypatch.setattr(memory_main, "display_first_run_notice", first_run_notice)
result = Memory.delete(memory, "memory-1")
assert result == {"message": "Memory deleted successfully!"}
memory._delete_memory.assert_called_once_with("memory-1", existing_memory)
decay_notice.assert_called_once_with(
memory,
"sync",
"delete",
"delete_count",
"repeated_deletes",
5,
None,
)
first_run_notice.assert_not_called()
def test_sync_delete_below_threshold_uses_first_run_notice(monkeypatch):
memory = make_sync_memory()
memory.vector_store.get.return_value = SimpleNamespace(id="memory-1")
decay_notice = MagicMock()
first_run_notice = MagicMock()
monkeypatch.setattr(memory_main, "capture_event", MagicMock())
monkeypatch.setattr(memory_main, "detect_decay_usage_from_delete", MagicMock(return_value=None))
monkeypatch.setattr(memory_main, "display_decay_usage_notice", decay_notice)
monkeypatch.setattr(memory_main, "display_first_run_notice", first_run_notice)
Memory.delete(memory, "memory-1")
decay_notice.assert_not_called()
first_run_notice.assert_called_once_with(memory, "sync", "delete")
def test_sync_delete_failure_does_not_trigger_decay_usage_notice(monkeypatch):
memory = make_sync_memory()
memory.vector_store.get.return_value = None
detect_decay = MagicMock()
decay_notice = MagicMock()
first_run_notice = MagicMock()
monkeypatch.setattr(memory_main, "capture_event", MagicMock())
monkeypatch.setattr(memory_main, "detect_decay_usage_from_delete", detect_decay)
monkeypatch.setattr(memory_main, "display_decay_usage_notice", decay_notice)
monkeypatch.setattr(memory_main, "display_first_run_notice", first_run_notice)
with pytest.raises(ValueError, match="Memory with id memory-1 not found"):
Memory.delete(memory, "memory-1")
detect_decay.assert_not_called()
decay_notice.assert_not_called()
first_run_notice.assert_not_called()
def test_sync_delete_all_decay_usage_runs_after_success(monkeypatch):
memory = make_sync_memory()
memories = [SimpleNamespace(id="memory-1"), SimpleNamespace(id="memory-2")]
memory.vector_store.list.return_value = (memories, None)
decay_notice = MagicMock()
first_run_notice = MagicMock()
detect_decay = MagicMock(return_value=("delete_all", "bulk_delete", None, 2))
monkeypatch.setattr(memory_main, "capture_event", MagicMock())
monkeypatch.setattr(memory_main, "detect_decay_usage_from_delete_all", detect_decay)
monkeypatch.setattr(memory_main, "display_decay_usage_notice", decay_notice)
monkeypatch.setattr(memory_main, "display_first_run_notice", first_run_notice)
result = Memory.delete_all(memory, user_id="u1")
assert result == {"message": "Memories deleted successfully!"}
assert memory._delete_memory.call_count == 2
detect_decay.assert_called_once_with(2)
decay_notice.assert_called_once_with(
memory,
"sync",
"delete_all",
"delete_all",
"bulk_delete",
None,
2,
)
first_run_notice.assert_not_called()
def test_sync_delete_all_zero_deletes_uses_first_run_notice(monkeypatch):
memory = make_sync_memory()
memory.vector_store.list.return_value = ([], None)
decay_notice = MagicMock()
first_run_notice = MagicMock()
monkeypatch.setattr(memory_main, "capture_event", MagicMock())
monkeypatch.setattr(memory_main, "detect_decay_usage_from_delete_all", MagicMock(return_value=None))
monkeypatch.setattr(memory_main, "display_decay_usage_notice", decay_notice)
monkeypatch.setattr(memory_main, "display_first_run_notice", first_run_notice)
Memory.delete_all(memory, user_id="u1")
decay_notice.assert_not_called()
first_run_notice.assert_called_once_with(memory, "sync", "delete_all")
@pytest.mark.asyncio
async def test_async_delete_decay_usage_runs_after_success(monkeypatch):
memory = make_async_memory()
existing_memory = SimpleNamespace(id="memory-1")
memory.vector_store.get.return_value = existing_memory
decay_notice = AsyncMock()
first_run_notice = AsyncMock()
monkeypatch.setattr(memory_main, "capture_event", MagicMock())
monkeypatch.setattr(
memory_main,
"detect_decay_usage_from_delete",
MagicMock(return_value=("delete_count", "repeated_deletes", 5, None)),
)
monkeypatch.setattr(memory_main, "display_decay_usage_notice_async", decay_notice)
monkeypatch.setattr(memory_main, "display_first_run_notice_async", first_run_notice)
result = await AsyncMemory.delete(memory, "memory-1")
assert result == {"message": "Memory deleted successfully!"}
memory._delete_memory.assert_awaited_once_with("memory-1", existing_memory)
decay_notice.assert_awaited_once_with(
memory,
"async",
"delete",
"delete_count",
"repeated_deletes",
5,
None,
)
first_run_notice.assert_not_awaited()
@pytest.mark.asyncio
async def test_async_delete_failure_does_not_trigger_decay_usage_notice(monkeypatch):
memory = make_async_memory()
memory.vector_store.get.return_value = None
detect_decay = MagicMock()
decay_notice = AsyncMock()
first_run_notice = AsyncMock()
monkeypatch.setattr(memory_main, "capture_event", MagicMock())
monkeypatch.setattr(memory_main, "detect_decay_usage_from_delete", detect_decay)
monkeypatch.setattr(memory_main, "display_decay_usage_notice_async", decay_notice)
monkeypatch.setattr(memory_main, "display_first_run_notice_async", first_run_notice)
with pytest.raises(ValueError, match="Memory with id memory-1 not found"):
await AsyncMemory.delete(memory, "memory-1")
detect_decay.assert_not_called()
decay_notice.assert_not_awaited()
first_run_notice.assert_not_awaited()
@pytest.mark.asyncio
async def test_async_delete_all_decay_usage_runs_after_success(monkeypatch):
memory = make_async_memory()
memories = [SimpleNamespace(id="memory-1"), SimpleNamespace(id="memory-2")]
memory.vector_store.list.return_value = (memories, None)
decay_notice = AsyncMock()
first_run_notice = AsyncMock()
detect_decay = MagicMock(return_value=("delete_all", "bulk_delete", None, 2))
monkeypatch.setattr(memory_main, "capture_event", MagicMock())
monkeypatch.setattr(memory_main, "detect_decay_usage_from_delete_all", detect_decay)
monkeypatch.setattr(memory_main, "display_decay_usage_notice_async", decay_notice)
monkeypatch.setattr(memory_main, "display_first_run_notice_async", first_run_notice)
result = await AsyncMemory.delete_all(memory, user_id="u1")
assert result == {"message": "Memories deleted successfully!"}
assert memory._delete_memory.await_count == 2
detect_decay.assert_called_once_with(2)
decay_notice.assert_awaited_once_with(
memory,
"async",
"delete_all",
"delete_all",
"bulk_delete",
None,
2,
)
first_run_notice.assert_not_awaited()