agentcache / tests /test_context.py
Yash030's picture
feat: migrate agentmemory to agentcache namespace, endpoints, and tools
12a6c9a
Raw
History Blame Contribute Delete
5.78 kB
"""
tests/test_context.py — C1.4
Tests for context(), export_data(), and token budget enforcement.
"""
import sys
import os
import datetime
import pytest
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _make_kv(tmp_path):
from db import StateKV
os.environ.pop("AGENTCACHE_SECRET", None)
return StateKV(db_path=str(tmp_path / "test.db"))
def _now():
return datetime.datetime.utcnow().isoformat() + "Z"
# ---------------------------------------------------------------------------
# context() tests
# ---------------------------------------------------------------------------
class TestContext:
def test_empty_db_returns_minimal_context(self, tmp_path):
"""Empty DB should return a well-formed but empty context."""
from functions import context
kv = _make_kv(tmp_path)
result = context(kv, {
"sessionId": "sess_test_empty",
"project": "/home/user/my-project",
"budget": 2000,
})
assert isinstance(result, dict)
assert "context" in result
assert "blocks" in result
assert "tokens" in result
assert result["blocks"] == 0
assert result["tokens"] == 0
def test_raises_on_missing_session_id(self, tmp_path):
from functions import context
kv = _make_kv(tmp_path)
with pytest.raises(ValueError):
context(kv, {"project": "/home/user/proj"})
def test_raises_on_missing_project(self, tmp_path):
from functions import context
kv = _make_kv(tmp_path)
with pytest.raises(ValueError):
context(kv, {"sessionId": "sess_x"})
def test_respects_token_budget(self, tmp_path):
"""Context output tokens should not exceed the requested budget."""
from functions import context, lesson_save, KV
kv = _make_kv(tmp_path)
project = "/home/user/budget-test"
# Add many lessons to push towards the budget
for i in range(20):
lesson_save(kv, {
"content": f"Lesson {i}: " + ("x " * 100),
"project": project,
"confidence": 0.9,
})
budget = 500
result = context(kv, {
"sessionId": "sess_budget",
"project": project,
"budget": budget,
})
# Token estimate is len/3 — check that total tokens respects budget
assert result["tokens"] <= budget + 50 # small headroom for header/footer
def test_context_includes_xml_wrapper(self, tmp_path):
"""Non-empty context should be wrapped in <agentcache-context>."""
from functions import context, lesson_save
kv = _make_kv(tmp_path)
project = "/home/user/xml-test"
lesson_save(kv, {
"content": "Always validate user input before processing",
"project": project,
"confidence": 0.8,
})
result = context(kv, {
"sessionId": "sess_xml",
"project": project,
"budget": 2000,
})
if result["blocks"] > 0:
assert "<agentcache-context" in result["context"]
assert "</agentcache-context>" in result["context"]
def test_token_budget_env_var_respected(self, tmp_path, monkeypatch):
"""TOKEN_BUDGET env var should be used when no budget param given."""
from functions import context, lesson_save
kv = _make_kv(tmp_path)
project = "/home/user/env-budget"
monkeypatch.setenv("TOKEN_BUDGET", "100")
for i in range(10):
lesson_save(kv, {
"content": f"Important lesson {i}: " + ("word " * 50),
"project": project,
"confidence": 0.9,
})
result = context(kv, {"sessionId": "sess_env_budget", "project": project})
# Should use TOKEN_BUDGET=100 from env
assert result["tokens"] <= 150 # with some headroom for XML wrapper
# ---------------------------------------------------------------------------
# export_data() tests
# ---------------------------------------------------------------------------
class TestExportData:
def test_export_returns_folders_and_memories(self, tmp_path):
from functions import folder_observe, remember, export_data
kv = _make_kv(tmp_path)
folder_observe(kv, {
"folderPath": "/home/user/export-test",
"agentId": "kiro",
"text": "Working on export feature",
"timestamp": _now(),
})
remember(kv, {"content": "Export data uses v2 format"})
result = export_data(kv, {})
assert isinstance(result, dict)
assert "folders" in result or "observations" in result or "memories" in result
def test_export_empty_db(self, tmp_path):
from functions import export_data
kv = _make_kv(tmp_path)
result = export_data(kv, {})
assert isinstance(result, dict)
# Should not crash on empty DB
# ---------------------------------------------------------------------------
# estimate_tokens()
# ---------------------------------------------------------------------------
class TestEstimateTokens:
def test_empty_string(self):
from functions import estimate_tokens
assert estimate_tokens("") == 0
def test_typical_text(self):
from functions import estimate_tokens
text = "hello world this is a test" * 10
tokens = estimate_tokens(text)
# Should be approximately len/3
assert tokens == len(text) // 3