New router intelligence modules (26 files): alert_ingest/store, audit_store, architecture_pressure, backlog_generator/store, cost_analyzer, data_governance, dependency_scanner, drift_analyzer, incident_* (5 files), llm_enrichment, platform_priority_digest, provider_budget, release_check_runner, risk_* (6 files), signature_state_store, sofiia_auto_router, tool_governance New services: - sofiia-console: Dockerfile, adapters/, monitor/nodes/ops/voice modules, launchd, react static - memory-service: integration_endpoints, integrations, voice_endpoints, static UI - aurora-service: full app suite (analysis, job_store, orchestrator, reporting, schemas, subagents) - sofiia-supervisor: new supervisor service - aistalk-bridge-lite: Telegram bridge lite - calendar-service: CalDAV calendar service with reminders - mlx-stt-service / mlx-tts-service: Apple Silicon speech services - binance-bot-monitor: market monitor service - node-worker: STT/TTS memory providers New tools (9): agent_email, browser_tool, contract_tool, observability_tool, oncall_tool, pr_reviewer_tool, repo_tool, safe_code_executor, secure_vault New crews: agromatrix_crew (10 modules: depth_classifier, doc_facts, doc_focus, farm_state, light_reply, llm_factory, memory_manager, proactivity, reflection_engine, session_context, style_adapter, telemetry) Tests: 85+ test files for all new modules Made-with: Cursor
92 lines
3.2 KiB
Python
92 lines
3.2 KiB
Python
"""Tests for in-memory state backend (Redis tested in integration)."""
|
|
|
|
import asyncio
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
from tests.conftest import _run
|
|
from app.models import EventType, RunEvent, RunRecord, RunStatus
|
|
|
|
|
|
def _make_run(run_id: str = "gr_test_001") -> RunRecord:
|
|
return RunRecord(
|
|
run_id=run_id,
|
|
graph="release_check",
|
|
status=RunStatus.QUEUED,
|
|
agent_id="sofiia",
|
|
workspace_id="daarion",
|
|
user_id="u_001",
|
|
)
|
|
|
|
|
|
class TestMemoryBackend:
|
|
def test_save_and_get_run(self):
|
|
from app.state_backend import MemoryStateBackend
|
|
backend = MemoryStateBackend()
|
|
run = _make_run("gr_001")
|
|
_run(backend.save_run(run))
|
|
fetched = _run(backend.get_run("gr_001"))
|
|
assert fetched is not None
|
|
assert fetched.run_id == "gr_001"
|
|
assert fetched.status == RunStatus.QUEUED
|
|
|
|
def test_get_missing_run_returns_none(self):
|
|
from app.state_backend import MemoryStateBackend
|
|
backend = MemoryStateBackend()
|
|
assert _run(backend.get_run("does_not_exist")) is None
|
|
|
|
def test_append_and_get_events(self):
|
|
from app.state_backend import MemoryStateBackend
|
|
backend = MemoryStateBackend()
|
|
run = _make_run("gr_002")
|
|
_run(backend.save_run(run))
|
|
|
|
ev1 = RunEvent(ts="2026-01-01T00:00:00Z", type=EventType.NODE_START, node="start_job")
|
|
ev2 = RunEvent(ts="2026-01-01T00:00:01Z", type=EventType.TOOL_CALL, tool="job_orchestrator_tool",
|
|
details={"hash": "abc123", "size": 200})
|
|
_run(backend.append_event("gr_002", ev1))
|
|
_run(backend.append_event("gr_002", ev2))
|
|
|
|
events = _run(backend.get_events("gr_002"))
|
|
assert len(events) == 2
|
|
assert events[0].type == EventType.NODE_START
|
|
assert events[1].tool == "job_orchestrator_tool"
|
|
# Events should NOT contain payload content
|
|
assert "size" in events[1].details
|
|
|
|
def test_cancel_queued_run(self):
|
|
from app.state_backend import MemoryStateBackend
|
|
backend = MemoryStateBackend()
|
|
run = _make_run("gr_003")
|
|
_run(backend.save_run(run))
|
|
|
|
ok = _run(backend.cancel_run("gr_003"))
|
|
assert ok is True
|
|
fetched = _run(backend.get_run("gr_003"))
|
|
assert fetched.status == RunStatus.CANCELLED
|
|
|
|
def test_cancel_completed_run_returns_false(self):
|
|
from app.state_backend import MemoryStateBackend
|
|
backend = MemoryStateBackend()
|
|
run = _make_run("gr_004")
|
|
run.status = RunStatus.SUCCEEDED
|
|
_run(backend.save_run(run))
|
|
|
|
ok = _run(backend.cancel_run("gr_004"))
|
|
assert ok is False
|
|
|
|
def test_update_run_status(self):
|
|
from app.state_backend import MemoryStateBackend
|
|
backend = MemoryStateBackend()
|
|
run = _make_run("gr_005")
|
|
_run(backend.save_run(run))
|
|
|
|
run.status = RunStatus.RUNNING
|
|
run.started_at = "2026-01-01T00:00:00Z"
|
|
_run(backend.save_run(run))
|
|
|
|
fetched = _run(backend.get_run("gr_005"))
|
|
assert fetched.status == RunStatus.RUNNING
|
|
assert fetched.started_at == "2026-01-01T00:00:00Z"
|