Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,6 @@ exclude = ["tests"]
[[tool.mypy.overrides]]
module = ["tests.*"]
ignore_errors = true

[tool.coverage.run]
omit = ["demo.py", "__main__.py"]
125 changes: 0 additions & 125 deletions tests/test_all.py

This file was deleted.

221 changes: 1 addition & 220 deletions tests/test_auth_backup.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
"""
Tests for auth, backup, import/export, and MCP auto-start.
Tests for auth — unique tests only.
"""

import pytest
import os


# ═══════════════════════════════════════════════════════════════
# AUTH TESTS
# ═══════════════════════════════════════════════════════════════


@pytest.mark.asyncio
Expand Down Expand Up @@ -79,189 +73,6 @@ async def test_bearer_rotate():
assert ba.verify("Bearer " + new_token) is True


# ═══════════════════════════════════════════════════════════════
# BACKUP TESTS
# ═══════════════════════════════════════════════════════════════


@pytest.mark.asyncio
async def test_backup_create():
from features.backup import BackupManager

bm = BackupManager()
path = await bm.backup(label="test_backup")
assert path is not None
assert os.path.exists(path)


@pytest.mark.asyncio
async def test_backup_list():
from features.backup import BackupManager

bm = BackupManager()
await bm.backup(label="test_list")
backups = bm.list_backups()
assert len(backups) >= 1


@pytest.mark.asyncio
async def test_backup_restore():
from features.backup import BackupManager

bm = BackupManager()
path = await bm.backup(label="test_restore")
backup_name = os.path.basename(path)
result = await bm.restore(backup_name)
assert "restored" in result


@pytest.mark.asyncio
async def test_backup_cleanup():
from features.backup import BackupManager

bm = BackupManager()
removed = bm.cleanup_old()
assert isinstance(removed, int)


# ═══════════════════════════════════════════════════════════════
# IMPORT/EXPORT TESTS
# ═══════════════════════════════════════════════════════════════


@pytest.mark.asyncio
async def test_export_import():
from features.import_export import ImportExport
from core import memory_manager

# Create some data
user = memory_manager.user_memory("export_test")
await user.remember("key1", "value1", 0.8)

ie = ImportExport()

# Export
export_path = await ie.export_user("export_test")
assert export_path is not None
assert os.path.exists(export_path)

# List exports
exports = ie.list_exports()
assert len(exports) >= 1


# ═══════════════════════════════════════════════════════════════
# AUDIT TRAIL TESTS
# ═══════════════════════════════════════════════════════════════


@pytest.mark.asyncio
async def test_audit_log():
from features.audit_trail import AuditTrail

at = AuditTrail()
await at._init_db()
await at.log("audit_test", "test_action", "user", "target_1", {"key": "value"})
history = await at.get_history("audit_test")
assert len(history) >= 1
assert history[0]["action"] == "test_action"


@pytest.mark.asyncio
async def test_audit_count():
from features.audit_trail import AuditTrail

at = AuditTrail()
await at._init_db()
await at.log("count_test", "action1")
await at.log("count_test", "action2")
count = await at.count("count_test")
assert count >= 2


@pytest.mark.asyncio
async def test_audit_cleanup():
from features.audit_trail import AuditTrail

at = AuditTrail()
await at._init_db()
removed = await at.cleanup_old(retention_days=0)
assert isinstance(removed, int)


# ═══════════════════════════════════════════════════════════════
# RATE LIMITER TESTS
# ═══════════════════════════════════════════════════════════════


@pytest.mark.asyncio
async def test_rate_limiter():
from features.rate_limiting import RateLimiter

rl = RateLimiter()
result = await rl.check("rate_test")
assert "allowed" in result
assert result["allowed"] is True


@pytest.mark.asyncio
async def test_rate_limiter_stats(tmp_path):
from features.rate_limiting import RateLimiter
from shared.connection import AsyncConnectionManager

cm = AsyncConnectionManager(base_dir=str(tmp_path))
await cm.execute_script(
"memory.db",
"CREATE TABLE IF NOT EXISTS rate_limits (id INTEGER PRIMARY KEY AUTOINCREMENT, user_id TEXT NOT NULL, timestamp REAL NOT NULL);",
)
rl = RateLimiter(cm=cm)
await rl.check("stats_test")
stats = await rl.get_stats("stats_test")
assert "requests_last_minute" in stats


# ═══════════════════════════════════════════════════════════════
# MCP AUTO-START TESTS
# ═══════════════════════════════════════════════════════════════


def test_mcp_tools_count():
from mcp_server import mcp

tools = mcp._tool_manager.list_tools()
assert len(tools) >= 15


def test_mcp_tools_are_async():
import inspect
from mcp_server import mcp

tools = mcp._tool_manager.list_tools()
tool_names = [t.name for t in tools]
assert "memory_remember" in tool_names
assert "memory_backup" in tool_names
assert "memory_api_key" in tool_names
assert "memory_lucidity_purge" in tool_names
assert "memory_search" in tool_names

for tool in tools:
assert inspect.iscoroutinefunction(tool.fn), f"{tool.name} is not async"


def test_mcp_server_name():
from mcp_server import mcp

assert mcp.name == "ariel-memory"


def test_mcp_server_instructions():
from mcp_server import mcp

assert "Two-Layer" in mcp.instructions
assert "user" in mcp.instructions
assert "agent" in mcp.instructions


@pytest.mark.asyncio
async def test_mcp_lifespan():
from mcp_server.server import lifespan, mcp
Expand All @@ -271,33 +82,3 @@ async def test_mcp_lifespan():
assert hasattr(ctx, "mm")
assert hasattr(ctx, "user_wiki")
assert hasattr(ctx, "agent_wiki")


# ═══════════════════════════════════════════════════════════════
# CONFIG TESTS
# ═══════════════════════════════════════════════════════════════


def test_config_singleton():
from config import Config

c1 = Config()
c2 = Config()
assert c1 is c2


def test_config_get():
from config import Config

config = Config()
# Default values should work
assert config.get("layers", "user", "enabled", default=True) is True


def test_config_hooks():
from config import Config

config = Config()
# Should not crash
result = config.is_hook_enabled("user", "message_received")
assert isinstance(result, bool)
Loading
Loading