"""记忆上下文组装测试。""" from datetime import UTC, datetime, timedelta from app.models.memory import Memory from app.modules.memory.context import ( MemoryRetrievalResult, build_memory_context, ) def _make_memory( *, importance: float = 0.5, hours_ago: float = 1.0, title: str = "测试记忆", content: str = "这是一条测试记忆内容。", ) -> Memory: return Memory( id=f"mem_{title}", character_id="char_1", type="observation", title=title, content=content, importance=importance, created_at=datetime.now(UTC) - timedelta(hours=hours_ago), source="test", confidence=1.0, sensitivity="low", evidence_ids_json="[]", status="active", ) def test_empty_memories_returns_none() -> None: result = MemoryRetrievalResult(memories=[]) assert build_memory_context(result) is None def test_single_memory_returns_text() -> None: mem = _make_memory() result = MemoryRetrievalResult(memories=[mem]) text = build_memory_context(result) assert text is not None assert "相关记忆:" in text assert "测试记忆" in text def test_high_importance_memory_comes_first() -> None: low = _make_memory(importance=0.3, title="不重要的") high = _make_memory(importance=0.9, title="重要的") result = MemoryRetrievalResult(memories=[low, high]) text = build_memory_context(result) assert text is not None important_pos = text.index("重要的") trivial_pos = text.index("不重要的") assert important_pos < trivial_pos, "重要性高的应该排前面" def test_memories_are_sorted_by_importance_descending() -> None: """传入任意顺序,输出始终重要性降序。""" a = _make_memory(importance=0.5, title="中") b = _make_memory(importance=0.1, title="低") c = _make_memory(importance=0.9, title="高") result = MemoryRetrievalResult(memories=[a, b, c]) text = build_memory_context(result) assert text is not None positions = {title: text.index(title) for title in ["高", "中", "低"]} assert positions["高"] < positions["中"] assert positions["中"] < positions["低"] def test_importance_label_appears() -> None: high = _make_memory(importance=0.9, title="重要记忆", content="重要内容") medium = _make_memory(importance=0.5, title="普通记忆", content="普通内容") low = _make_memory(importance=0.2, title="低优先级", content="低优先级内容") result = MemoryRetrievalResult(memories=[high, medium, low]) text = build_memory_context(result) assert text is not None assert "★重要" in text assert "●一般" in text assert "○参考" in text def test_time_labels() -> None: just_now = _make_memory(title="刚刚发生", hours_ago=0.1) hours_ago = _make_memory(title="几小时前", hours_ago=5) days_ago = _make_memory(title="几天前", hours_ago=72) result = MemoryRetrievalResult(memories=[just_now, hours_ago, days_ago]) text = build_memory_context(result) assert text is not None assert "刚刚" in text assert "5小时前" in text or "几小时前" in text assert "3天前" in text def test_truncation_respects_max_length() -> None: content = "A" * 500 mem = _make_memory(content=content, title="一长内容") result = MemoryRetrievalResult(memories=[mem] * 20) text = build_memory_context(result, max_length=500) assert text is not None assert len(text) <= 550 # max_length + header + padding assert "已截断" in text def test_large_content_not_exceeding_max_length() -> None: """大量记忆时,内容不应超过 max_length 太多。""" mems = [_make_memory(content="B" * 200, title=f"记忆{i}", importance=0.5) for i in range(50)] result = MemoryRetrievalResult(memories=mems) text = build_memory_context(result, max_length=1000) assert text is not None assert len(text) <= 1200 # 1000 + header + some padding