| import sys
|
| from pathlib import Path
|
|
|
| import pytest
|
| from unittest.mock import MagicMock, patch, AsyncMock
|
|
|
|
|
|
|
| ROOT = Path(__file__).resolve().parents[1]
|
| SRC = ROOT / "src"
|
| if str(SRC) not in sys.path:
|
| sys.path.insert(0, str(SRC))
|
|
|
|
|
|
|
|
|
|
|
|
|
| @pytest.fixture
|
| def qdrant_store():
|
| """
|
| Fixture providing a MockQdrantStore instance for offline testing.
|
|
|
| This mock provides full in-memory implementation of QdrantStore
|
| without requiring a running Qdrant server.
|
|
|
| Usage:
|
| async def test_search(qdrant_store):
|
| await qdrant_store.ensure_collections()
|
| # ... test code
|
| """
|
| from tests.mocks import MockQdrantStore
|
|
|
| store = MockQdrantStore(
|
| url="mock://localhost:6333",
|
| dimensionality=1024,
|
| collection_hot="haim_hot",
|
| collection_warm="haim_warm"
|
| )
|
| return store
|
|
|
|
|
| @pytest.fixture
|
| def redis_storage():
|
| """
|
| Fixture providing a MockAsyncRedisStorage instance for offline testing.
|
|
|
| This mock provides full in-memory implementation of AsyncRedisStorage
|
| without requiring a running Redis server.
|
|
|
| Usage:
|
| async def test_storage(redis_storage):
|
| await redis_storage.store_memory("node1", {"data": "test"})
|
| result = await redis_storage.retrieve_memory("node1")
|
| """
|
| from tests.mocks import MockAsyncRedisStorage
|
|
|
| storage = MockAsyncRedisStorage(
|
| url="redis://localhost:6379/0",
|
| stream_key="haim:subconscious"
|
| )
|
| return storage
|
|
|
|
|
| @pytest.fixture
|
| def engine(qdrant_store, redis_storage):
|
| """
|
| Fixture providing a mock cognitive engine with mocked storage backends.
|
|
|
| Creates a complete mock engine configuration suitable for unit tests
|
| that need to interact with the cognitive memory system.
|
|
|
| Usage:
|
| async def test_engine(engine):
|
| # Engine has mocked qdrant_store and redis_storage
|
| await engine.qdrant_store.ensure_collections()
|
| """
|
| from dataclasses import dataclass
|
|
|
| @dataclass
|
| class MockEngine:
|
| qdrant_store: object
|
| redis_storage: object
|
| config: dict
|
|
|
| async def initialize(self):
|
| await self.qdrant_store.ensure_collections()
|
| return True
|
|
|
| async def shutdown(self):
|
| await self.qdrant_store.close()
|
| await self.redis_storage.close()
|
|
|
| mock_config = {
|
| "qdrant_url": "mock://localhost:6333",
|
| "redis_url": "redis://localhost:6379/0",
|
| "dimensionality": 1024,
|
| }
|
|
|
| return MockEngine(
|
| qdrant_store=qdrant_store,
|
| redis_storage=redis_storage,
|
| config=mock_config
|
| )
|
|
|
|
|
|
|
|
|
|
|
|
|
| @pytest.fixture(scope="session", autouse=True)
|
| def mock_hardware_dependencies():
|
| """Globally mock Qdrant and Redis to prevent hangs during testing."""
|
|
|
| import mnemocore.core.async_storage
|
| import mnemocore.core.qdrant_store
|
|
|
|
|
| mock_redis_client = MagicMock()
|
| mock_redis_client.ping = AsyncMock(return_value=True)
|
| mock_redis_client.get = AsyncMock(return_value=None)
|
| mock_redis_client.set = AsyncMock(return_value=True)
|
| mock_redis_client.setex = AsyncMock(return_value=True)
|
| mock_redis_client.delete = AsyncMock(return_value=1)
|
| mock_redis_client.mget = AsyncMock(return_value=[])
|
| mock_redis_client.zadd = AsyncMock(return_value=1)
|
| mock_redis_client.zrange = AsyncMock(return_value=[])
|
| mock_redis_client.zrem = AsyncMock(return_value=1)
|
| mock_redis_client.xadd = AsyncMock(return_value="1234567890-0")
|
| mock_redis_client.xread = AsyncMock(return_value=[])
|
| mock_redis_client.xreadgroup = AsyncMock(return_value=[])
|
| mock_redis_client.xgroup_create = AsyncMock(return_value=True)
|
| mock_redis_client.xack = AsyncMock(return_value=True)
|
|
|
|
|
| mock_pipeline = MagicMock()
|
| mock_pipeline.__aenter__ = AsyncMock(return_value=mock_pipeline)
|
| mock_pipeline.__aexit__ = AsyncMock(return_value=None)
|
| mock_pipeline.incr = MagicMock()
|
| mock_pipeline.expire = MagicMock()
|
| mock_pipeline.execute = AsyncMock(return_value=[1, True])
|
| mock_redis_client.pipeline.return_value = mock_pipeline
|
|
|
|
|
| mock_redis_storage = MagicMock(spec=mnemocore.core.async_storage.AsyncRedisStorage)
|
| mock_redis_storage.redis_client = mock_redis_client
|
| mock_redis_storage.check_health = AsyncMock(return_value=True)
|
| mock_redis_storage.store_memory = AsyncMock(return_value=None)
|
| mock_redis_storage.retrieve_memory = AsyncMock(return_value=None)
|
| mock_redis_storage.batch_retrieve = AsyncMock(return_value=[])
|
| mock_redis_storage.delete_memory = AsyncMock(return_value=None)
|
| mock_redis_storage.get_eviction_candidates = AsyncMock(return_value=[])
|
| mock_redis_storage.update_ltp = AsyncMock(return_value=None)
|
| mock_redis_storage.publish_event = AsyncMock(return_value=None)
|
| mock_redis_storage.close = AsyncMock(return_value=None)
|
|
|
|
|
| mock_qdrant_client = MagicMock()
|
| mock_qdrant_client.collection_exists = AsyncMock(return_value=False)
|
| mock_qdrant_client.create_collection = AsyncMock(return_value=None)
|
| mock_qdrant_client.upsert = AsyncMock(return_value=None)
|
| mock_qdrant_client.search = AsyncMock(return_value=[])
|
| mock_qdrant_client.retrieve = AsyncMock(return_value=[])
|
| mock_qdrant_client.scroll = AsyncMock(return_value=([], None))
|
| mock_qdrant_client.delete = AsyncMock(return_value=None)
|
| mock_qdrant_client.get_collection = AsyncMock()
|
| mock_qdrant_client.close = AsyncMock(return_value=None)
|
|
|
|
|
| mock_qdrant_instance = MagicMock(spec=mnemocore.core.qdrant_store.QdrantStore)
|
| mock_qdrant_instance.client = mock_qdrant_client
|
| mock_qdrant_instance.ensure_collections = AsyncMock(return_value=None)
|
| mock_qdrant_instance.upsert = AsyncMock(return_value=None)
|
| mock_qdrant_instance.search = AsyncMock(return_value=[])
|
| mock_qdrant_instance.get_point = AsyncMock(return_value=None)
|
| mock_qdrant_instance.scroll = AsyncMock(return_value=([], None))
|
| mock_qdrant_instance.delete = AsyncMock(return_value=None)
|
| mock_qdrant_instance.close = AsyncMock(return_value=None)
|
|
|
|
|
| from mnemocore.core import container as container_module
|
|
|
| original_build_container = container_module.build_container
|
|
|
| def mock_build_container(config):
|
| container = MagicMock()
|
| container.config = config
|
| container.redis_storage = mock_redis_storage
|
| container.qdrant_store = mock_qdrant_instance
|
| return container
|
|
|
| container_patch = patch.object(container_module, 'build_container', side_effect=mock_build_container)
|
| container_patch.start()
|
|
|
|
|
| redis_init_patch = patch.object(
|
| mnemocore.core.async_storage.AsyncRedisStorage,
|
| '_initialize_from_pool',
|
| return_value=None
|
| )
|
| redis_init_patch.start()
|
|
|
|
|
| qdrant_client_patch = patch('mnemocore.core.qdrant_store.AsyncQdrantClient')
|
| qdrant_client_patch.start()
|
|
|
| yield (mock_qdrant_instance, mock_redis_storage)
|
|
|
|
|
| container_patch.stop()
|
| redis_init_patch.stop()
|
| qdrant_client_patch.stop()
|
|
|
|
|
| @pytest.fixture(autouse=True)
|
| def clean_config():
|
| """Reset config state between tests."""
|
| from mnemocore.core.config import reset_config
|
| reset_config()
|
| yield
|
| reset_config()
|
|
|
|
|
| @pytest.fixture
|
| def mock_container():
|
| """Create a mock container for testing."""
|
| from mnemocore.core.config import get_config
|
|
|
| config = get_config()
|
|
|
| mock_redis_client = MagicMock()
|
| mock_redis_client.ping = AsyncMock(return_value=True)
|
| mock_redis_client.pipeline.return_value.__aenter__ = AsyncMock(return_value=mock_redis_client.pipeline.return_value)
|
| mock_redis_client.pipeline.return_value.__aexit__ = AsyncMock(return_value=None)
|
| mock_redis_client.pipeline.return_value.execute = AsyncMock(return_value=[1, True])
|
|
|
| mock_redis_storage = MagicMock()
|
| mock_redis_storage.redis_client = mock_redis_client
|
| mock_redis_storage.check_health = AsyncMock(return_value=True)
|
| mock_redis_storage.publish_event = AsyncMock(return_value=None)
|
| mock_redis_storage.store_memory = AsyncMock(return_value=None)
|
| mock_redis_storage.retrieve_memory = AsyncMock(return_value=None)
|
| mock_redis_storage.delete_memory = AsyncMock(return_value=None)
|
| mock_redis_storage.close = AsyncMock(return_value=None)
|
|
|
| mock_qdrant = MagicMock()
|
| mock_qdrant.ensure_collections = AsyncMock(return_value=None)
|
| mock_qdrant.upsert = AsyncMock(return_value=None)
|
| mock_qdrant.search = AsyncMock(return_value=[])
|
| mock_qdrant.get_point = AsyncMock(return_value=None)
|
| mock_qdrant.scroll = AsyncMock(return_value=([], None))
|
| mock_qdrant.delete = AsyncMock(return_value=None)
|
| mock_qdrant.close = AsyncMock(return_value=None)
|
|
|
| container = MagicMock()
|
| container.config = config
|
| container.redis_storage = mock_redis_storage
|
| container.qdrant_store = mock_qdrant
|
|
|
| return container
|
|
|