mirror of
https://github.com/open-jarvis/OpenJarvis.git
synced 2026-07-28 13:26:48 +00:00
* fix(channels): wire channel→agent handler and fix Telegram send pipeline * format code * add supported tests
166 lines
5.2 KiB
Python
166 lines
5.2 KiB
Python
"""Tests for the SQLite/FTS5 memory backend."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from openjarvis.core.events import EventBus, EventType
|
|
from openjarvis.core.registry import MemoryRegistry
|
|
from openjarvis.tools.storage.sqlite import SQLiteMemory
|
|
|
|
|
|
def _make_backend(tmp_path: Path) -> SQLiteMemory:
|
|
"""Create an SQLiteMemory instance using a temp database."""
|
|
# Register manually since conftest clears registries
|
|
if not MemoryRegistry.contains("sqlite"):
|
|
MemoryRegistry.register_value("sqlite", SQLiteMemory)
|
|
return SQLiteMemory(db_path=tmp_path / "test_memory.db")
|
|
|
|
|
|
def test_registration_in_memory_registry():
|
|
"""Importing the module registers 'sqlite' in MemoryRegistry."""
|
|
MemoryRegistry.register_value("sqlite", SQLiteMemory)
|
|
assert MemoryRegistry.contains("sqlite")
|
|
|
|
|
|
def test_creates_tables_on_init(tmp_path: Path):
|
|
backend = _make_backend(tmp_path)
|
|
# Rust manages the DB internally (_conn is None), so verify via public API:
|
|
# a freshly created backend should report zero documents.
|
|
assert backend.count() == 0
|
|
backend.close()
|
|
|
|
|
|
def test_store_returns_uuid(tmp_path: Path):
|
|
backend = _make_backend(tmp_path)
|
|
doc_id = backend.store("hello world")
|
|
assert isinstance(doc_id, str)
|
|
assert len(doc_id) == 36 # Rust Uuid::new_v4().to_string() includes hyphens
|
|
backend.close()
|
|
|
|
|
|
def test_store_and_retrieve(tmp_path: Path):
|
|
backend = _make_backend(tmp_path)
|
|
backend.store("Python is a programming language", source="wiki.md")
|
|
backend.store("The weather is sunny today", source="diary.md")
|
|
results = backend.retrieve("programming language")
|
|
assert len(results) >= 1
|
|
assert "Python" in results[0].content
|
|
backend.close()
|
|
|
|
|
|
def test_retrieve_ranking_by_relevance(tmp_path: Path):
|
|
backend = _make_backend(tmp_path)
|
|
backend.store("machine learning and deep learning")
|
|
backend.store("cooking recipes for dinner")
|
|
backend.store("advanced machine learning techniques")
|
|
results = backend.retrieve("machine learning")
|
|
assert len(results) >= 2
|
|
# The ML-related docs should be first
|
|
assert "machine" in results[0].content.lower()
|
|
backend.close()
|
|
|
|
|
|
def test_retrieve_top_k_limit(tmp_path: Path):
|
|
backend = _make_backend(tmp_path)
|
|
for i in range(10):
|
|
backend.store(f"document number {i} about testing")
|
|
results = backend.retrieve("testing", top_k=3)
|
|
assert len(results) <= 3
|
|
backend.close()
|
|
|
|
|
|
def test_retrieve_no_results(tmp_path: Path):
|
|
backend = _make_backend(tmp_path)
|
|
backend.store("hello world")
|
|
results = backend.retrieve("quantum physics supercollider")
|
|
assert len(results) == 0
|
|
backend.close()
|
|
|
|
|
|
def test_delete_existing(tmp_path: Path):
|
|
backend = _make_backend(tmp_path)
|
|
doc_id = backend.store("deletable content")
|
|
assert backend.count() == 1
|
|
assert backend.delete(doc_id) is True
|
|
assert backend.count() == 0
|
|
backend.close()
|
|
|
|
|
|
def test_delete_nonexistent(tmp_path: Path):
|
|
backend = _make_backend(tmp_path)
|
|
assert backend.delete("nonexistent_id") is False
|
|
backend.close()
|
|
|
|
|
|
def test_clear(tmp_path: Path):
|
|
backend = _make_backend(tmp_path)
|
|
backend.store("doc one")
|
|
backend.store("doc two")
|
|
assert backend.count() == 2
|
|
backend.clear()
|
|
assert backend.count() == 0
|
|
backend.close()
|
|
|
|
|
|
def test_count(tmp_path: Path):
|
|
backend = _make_backend(tmp_path)
|
|
assert backend.count() == 0
|
|
backend.store("first")
|
|
assert backend.count() == 1
|
|
backend.store("second")
|
|
assert backend.count() == 2
|
|
backend.close()
|
|
|
|
|
|
def test_source_and_metadata_roundtrip(tmp_path: Path):
|
|
backend = _make_backend(tmp_path)
|
|
meta = {"author": "test", "page": 42}
|
|
backend.store(
|
|
"content with metadata",
|
|
source="paper.pdf",
|
|
metadata=meta,
|
|
)
|
|
results = backend.retrieve("content metadata")
|
|
assert len(results) == 1
|
|
assert results[0].source == "paper.pdf"
|
|
assert results[0].metadata["author"] == "test"
|
|
assert results[0].metadata["page"] == 42
|
|
backend.close()
|
|
|
|
|
|
def test_event_bus_integration_store(tmp_path: Path):
|
|
bus = EventBus(record_history=True)
|
|
backend = _make_backend(tmp_path)
|
|
# Monkey-patch the global bus for this test
|
|
import openjarvis.tools.storage.sqlite as mod
|
|
|
|
original = mod.get_event_bus
|
|
mod.get_event_bus = lambda: bus
|
|
try:
|
|
backend.store("test event emission")
|
|
events = [e for e in bus.history if e.event_type == EventType.MEMORY_STORE]
|
|
assert len(events) == 1
|
|
assert events[0].data["backend"] == "sqlite"
|
|
finally:
|
|
mod.get_event_bus = original
|
|
backend.close()
|
|
|
|
|
|
def test_event_bus_integration_retrieve(tmp_path: Path):
|
|
bus = EventBus(record_history=True)
|
|
backend = _make_backend(tmp_path)
|
|
backend.store("searchable content for events")
|
|
import openjarvis.tools.storage.sqlite as mod
|
|
|
|
original = mod.get_event_bus
|
|
mod.get_event_bus = lambda: bus
|
|
try:
|
|
backend.retrieve("searchable")
|
|
events = [e for e in bus.history if e.event_type == EventType.MEMORY_RETRIEVE]
|
|
assert len(events) == 1
|
|
assert events[0].data["backend"] == "sqlite"
|
|
finally:
|
|
mod.get_event_bus = original
|
|
backend.close()
|