cuga-agent / src /system_tests /e2e /test_memory_integration.py
Sami Marreed
feat: docker-v1 with optimized frontend
0646b18
#!/usr/bin/env python3
"""
Integration tests for Memory module.
Tests make use of LLM models, so ensure that they are accessible.
These tests verify the full end-to-end functionality of the memory system
including Milvus vector store, SQLite metadata, and tips extraction.
"""
import unittest
import time
import os
os.environ['DYNACONF_ADVANCED_FEATURES__ENABLE_MEMORY'] = 'true'
from cuga.backend.memory.agentic_memory.main import app
from cuga.backend.memory.memory import Memory
from cuga.backend.memory.agentic_memory.schema import Namespace, RecordedFact, Run
from cuga.backend.memory.agentic_memory.client.exceptions import NamespaceNotFoundException
from cuga.config import DBS_DIR
from fastapi.testclient import TestClient
from pathlib import Path
from unittest import mock
test_env = {
"WXO_MILVUS_URI": str(Path(DBS_DIR) / "milvus.db"),
"MEM0_HISTORY_DB_PATH": str(Path(DBS_DIR) / "mem0_history.db"),
"MILVUS_DB": str(Path(DBS_DIR) / "test_memory.db"),
"AGENTIC_DB": str(Path(DBS_DIR) / "agentic.db"),
"MODEL_NAME": "Azure/gpt-4o",
}
class TestMemoryOperations(unittest.TestCase):
"""Test memory CRUD operations against a test service."""
def setUp(self):
"""Set up test client"""
Memory._instance = None
Memory._initialized = False
self.client = Memory()
self.client.memory_client.client = TestClient(app)
def tearDown(self):
"""Clean up created databases."""
Memory._instance = None
Memory._initialized = False
self.client.memory_client.client.close()
Path(test_env["WXO_MILVUS_URI"]).unlink(missing_ok=True)
Path(test_env["MEM0_HISTORY_DB_PATH"]).unlink(missing_ok=True)
Path(test_env["MILVUS_DB"]).unlink(missing_ok=True)
Path(test_env["AGENTIC_DB"]).unlink(missing_ok=True)
@mock.patch.dict(os.environ, test_env)
def test_full(self):
"""End-to-end test of memory CRUD operations."""
namespace_id = f"test_namespace_{int(time.time() * 1000)}"
# Create Namespace
namespace = self.client.create_namespace(
namespace_id=namespace_id, user_id="test_user", agent_id="cuga", app_id="test_app"
)
# Verify namespace was created correctly
self.assertIsInstance(namespace, Namespace)
self.assertEqual(namespace.id, namespace_id)
self.assertEqual(namespace.user_id, "test_user")
self.assertEqual(namespace.agent_id, "cuga")
self.assertEqual(namespace.app_id, "test_app")
self.assertIsNotNone(namespace.created_at)
# Get namespace details another way
namespace = self.client.get_namespace_details(namespace_id)
self.assertEqual(namespace.id, namespace_id)
self.assertEqual(namespace.user_id, "test_user")
self.assertEqual(namespace.agent_id, "cuga")
self.assertEqual(namespace.app_id, "test_app")
# Add fact
self.client.create_and_store_fact(
namespace_id, "Python is a programming language", {"topic": "programming", "user_id": "test_user"}
)
self.client.create_and_store_fact(
namespace_id,
"JavaScript is used for web development",
{"topic": "programming", "user_id": "test_user"},
)
self.client.create_and_store_fact(
namespace_id, "Machine learning uses neural networks", {"topic": "AI", "user_id": "test_user"}
)
facts = self.client.search_for_facts(
namespace_id=namespace_id,
query="programming languages",
filters={"user_id": "test_user"},
limit=5,
)
self.assertIsInstance(facts, list)
self.assertGreater(len(facts), 0)
self.assertIsInstance(facts[0], RecordedFact)
# Create Run
run_id = f"run_{int(time.time() * 1000)}"
run = self.client.create_run(namespace_id, run_id=run_id)
self.assertIsInstance(run, Run)
self.assertEqual(run.id, run_id)
self.assertFalse(run.ended)
self.assertEqual(len(run.steps), 0)
step_1 = self.client.add_step(
namespace_id=namespace_id,
run_id=run.id,
step={"name": "TaskAnalyzerAgent", "status": "success", "action": "analyzed task"},
prompt="Output a JSON object without any extra thoughts or commentary. Add a summary field.",
)
step_2 = self.client.add_step(
namespace_id=namespace_id,
run_id=run.id,
step={"agent": "APIPlannerAgent", "status": "success", "action": "selected APIs"},
prompt="Output a JSON object without any extra thoughts or commentary. Add a summary field.",
)
self.assertIsNotNone(step_1)
self.assertIsNotNone(step_2)
run = self.client.get_run(namespace_id, run.id)
self.assertGreaterEqual(len(run.steps), 2)
# End the run
self.client.end_run(namespace_id, run.id)
retrieved_run = self.client.get_run(namespace_id, run.id)
self.assertTrue(retrieved_run.ended)
# Delete run
self.client.delete_run(namespace_id, run.id)
with self.assertRaises(Exception):
self.client.get_run(namespace_id, run.id)
# Delete it
self.client.delete_namespace(namespace.id)
# Verify it's gone
with self.assertRaises(NamespaceNotFoundException):
self.client.get_namespace_details(namespace_id)
if __name__ == "__main__":
unittest.main()