test: stabilize full test collection
This commit is contained in:
@@ -82,8 +82,7 @@ python -m uvicorn app:app --host 127.0.0.1 --port 7000
|
||||
Requirements: Python 3.11+. Cookbook also needs `tmux` for background model
|
||||
downloads and serves. The app itself is lightweight; local model serving is the
|
||||
heavy part and depends on the model, runtime, GPU, and VRAM, so small hosts can
|
||||
connect to API or remote model servers instead. Use `--host 0.0.0.0` only when
|
||||
you intentionally want LAN/reverse-proxy access.
|
||||
connect to API or remote model servers instead. Use `--host 0.0.0.0` only when you intentionally want LAN/reverse-proxy access.
|
||||
|
||||
### Apple Silicon
|
||||
Docker on macOS cannot use the Metal GPU. For GPU-accelerated Cookbook on an
|
||||
|
||||
@@ -6,6 +6,7 @@ calling do_manage_calendar with an rrule stores a single event carrying that RRU
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
import tempfile
|
||||
import uuid
|
||||
|
||||
@@ -14,6 +15,21 @@ from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.pool import NullPool
|
||||
|
||||
|
||||
def _drop_fake_core_database():
|
||||
parent = sys.modules.get("core")
|
||||
attr = getattr(parent, "database", None) if parent is not None else None
|
||||
mod = sys.modules.get("core.database") or attr
|
||||
if mod is None or isinstance(getattr(mod, "__file__", None), str):
|
||||
return
|
||||
sys.modules.pop("core.database", None)
|
||||
sys.modules.pop("src.database", None)
|
||||
if parent is not None and attr is mod:
|
||||
delattr(parent, "database")
|
||||
|
||||
|
||||
_drop_fake_core_database()
|
||||
|
||||
import core.database as cdb
|
||||
from core.database import CalendarEvent
|
||||
|
||||
@@ -32,6 +48,10 @@ def _bind_temp_db(monkeypatch):
|
||||
# do_manage_calendar does `from core.database import SessionLocal` at call
|
||||
# time, so patch the module attribute to our temp DB — via monkeypatch so it
|
||||
# is RESTORED after each test and can't leak into later tests in the process.
|
||||
monkeypatch.setitem(sys.modules, "core.database", cdb)
|
||||
parent = sys.modules.get("core")
|
||||
if parent is not None:
|
||||
monkeypatch.setattr(parent, "database", cdb, raising=False)
|
||||
monkeypatch.setattr(cdb, "SessionLocal", _TS)
|
||||
yield
|
||||
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import json
|
||||
import sys
|
||||
from types import SimpleNamespace
|
||||
|
||||
_endpoint_resolver = sys.modules.get("src.endpoint_resolver")
|
||||
if _endpoint_resolver is not None and not getattr(_endpoint_resolver, "__file__", None):
|
||||
sys.modules.pop("src.endpoint_resolver", None)
|
||||
sys.modules.pop("routes.model_routes", None)
|
||||
sys.modules.pop("routes.chat_routes", None)
|
||||
|
||||
from routes import chat_routes
|
||||
|
||||
|
||||
|
||||
@@ -78,7 +78,12 @@ from core.middleware import require_admin # noqa: E402
|
||||
|
||||
# --- token minting: shown once, hashed at rest -----------------------------
|
||||
|
||||
def test_mint_token_returns_raw_once_and_stores_only_a_hash():
|
||||
def test_mint_token_returns_raw_once_and_stores_only_a_hash(monkeypatch):
|
||||
monkeypatch.setitem(sys.modules, "core.database", _db)
|
||||
parent = sys.modules.get("core")
|
||||
if parent is not None:
|
||||
monkeypatch.setattr(parent, "database", _db, raising=False)
|
||||
|
||||
token_id, raw = P.mint_token("alice")
|
||||
assert raw.startswith("ody_")
|
||||
# The persisted row stores a bcrypt hash + prefix, never the plaintext.
|
||||
|
||||
@@ -22,7 +22,8 @@ def test_background_status_poll_reconciles_into_local_tasks():
|
||||
assert "const statusById = new Map(tasks.map(t => [t.session_id, t]));" in source
|
||||
assert "const nextStatus = live.status === 'completed'" in source
|
||||
assert "? 'done'" in source
|
||||
assert "live.status === 'error'" in source
|
||||
assert ": (live.status === 'error'" in source
|
||||
assert "? 'error'" in source
|
||||
assert "_saveTasks(localTasks);" in source
|
||||
assert "completedDeps.forEach(t => _refreshDepsAfterInstall(t));" in source
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ while completing reliably everywhere.
|
||||
"""
|
||||
|
||||
import tempfile
|
||||
import sys
|
||||
import uuid
|
||||
from types import SimpleNamespace
|
||||
|
||||
@@ -21,6 +22,21 @@ from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.pool import NullPool
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
|
||||
def _drop_fake_core_database():
|
||||
parent = sys.modules.get("core")
|
||||
attr = getattr(parent, "database", None) if parent is not None else None
|
||||
mod = sys.modules.get("core.database") or attr
|
||||
if mod is None or isinstance(getattr(mod, "__file__", None), str):
|
||||
return
|
||||
sys.modules.pop("core.database", None)
|
||||
sys.modules.pop("src.database", None)
|
||||
if parent is not None and attr is mod:
|
||||
delattr(parent, "database")
|
||||
|
||||
|
||||
_drop_fake_core_database()
|
||||
|
||||
import core.database as cdb
|
||||
import routes.document_routes as droutes
|
||||
from core.database import Document
|
||||
|
||||
@@ -141,4 +141,3 @@ def test_build_anthropic_payload_alternating_roles():
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
import pytest
|
||||
import sys
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
|
||||
def _drop_fake_core_database():
|
||||
parent = sys.modules.get("core")
|
||||
attr = getattr(parent, "database", None) if parent is not None else None
|
||||
mod = sys.modules.get("core.database") or attr
|
||||
if mod is None or isinstance(getattr(mod, "__file__", None), str):
|
||||
return
|
||||
sys.modules.pop("core.database", None)
|
||||
sys.modules.pop("src.database", None)
|
||||
if parent is not None and attr is mod:
|
||||
delattr(parent, "database")
|
||||
|
||||
|
||||
_drop_fake_core_database()
|
||||
|
||||
from core.database import Base, Session, ChatMessage
|
||||
from datetime import datetime
|
||||
|
||||
@@ -35,4 +52,3 @@ def test_sqlite_foreign_keys_cascade():
|
||||
assert db.query(ChatMessage).count() == 0
|
||||
|
||||
db.close()
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Regression tests for task-result delivery into chat sessions (issue #326)."""
|
||||
import asyncio
|
||||
import sys
|
||||
import types as _types
|
||||
|
||||
import pytest
|
||||
@@ -11,6 +12,22 @@ if not isinstance(sqlalchemy, _types.ModuleType):
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
|
||||
def _drop_fake_core_database():
|
||||
parent = sys.modules.get("core")
|
||||
attr = getattr(parent, "database", None) if parent is not None else None
|
||||
mod = sys.modules.get("core.database") or attr
|
||||
if mod is None or isinstance(getattr(mod, "__file__", None), str):
|
||||
return
|
||||
sys.modules.pop("core.database", None)
|
||||
sys.modules.pop("src.database", None)
|
||||
if parent is not None and attr is mod:
|
||||
delattr(parent, "database")
|
||||
|
||||
|
||||
_drop_fake_core_database()
|
||||
|
||||
import core.database as cdb
|
||||
from core.database import Base, Session as DbSession
|
||||
from src.task_scheduler import TaskScheduler
|
||||
|
||||
@@ -46,10 +63,15 @@ def _make_task():
|
||||
)
|
||||
|
||||
|
||||
def test_session_delivery_survives_empty_database():
|
||||
def test_session_delivery_survives_empty_database(monkeypatch):
|
||||
"""On a fresh/wiped database there is no session to inherit endpoint/model
|
||||
from, so _resolve_defaults returns None. The delivery must still persist a
|
||||
session instead of crashing on the NOT NULL constraint (issue #326)."""
|
||||
monkeypatch.setitem(sys.modules, "core.database", cdb)
|
||||
parent = sys.modules.get("core")
|
||||
if parent is not None:
|
||||
monkeypatch.setattr(parent, "database", cdb, raising=False)
|
||||
|
||||
db = _make_db()
|
||||
scheduler = TaskScheduler.__new__(TaskScheduler)
|
||||
scheduler._session_manager = None
|
||||
|
||||
@@ -1,8 +1,25 @@
|
||||
"""Tests for topic keyword matching (src/topic_analyzer.py)."""
|
||||
import sys
|
||||
from types import SimpleNamespace
|
||||
import pytest
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
|
||||
def _drop_fake_core_database():
|
||||
parent = sys.modules.get("core")
|
||||
attr = getattr(parent, "database", None) if parent is not None else None
|
||||
mod = sys.modules.get("core.database") or attr
|
||||
if mod is None or isinstance(getattr(mod, "__file__", None), str):
|
||||
return
|
||||
sys.modules.pop("core.database", None)
|
||||
sys.modules.pop("src.database", None)
|
||||
if parent is not None and attr is mod:
|
||||
delattr(parent, "database")
|
||||
|
||||
|
||||
_drop_fake_core_database()
|
||||
|
||||
from core.database import Base, Session as DbSession, ChatMessage as DbChatMessage
|
||||
from core.session_manager import SessionManager
|
||||
from src.topic_analyzer import analyze_topics
|
||||
|
||||
@@ -6,6 +6,22 @@ from datetime import datetime
|
||||
# from it, so drop the stub here to load the real module under test.
|
||||
if "src.database" in sys.modules:
|
||||
del sys.modules["src.database"]
|
||||
_core_database = sys.modules.get("core.database")
|
||||
_core_database_all = getattr(_core_database, "__all__", None) if _core_database is not None else None
|
||||
if (
|
||||
_core_database is not None
|
||||
and (
|
||||
not getattr(_core_database, "__file__", None)
|
||||
or (
|
||||
_core_database_all is not None
|
||||
and (
|
||||
not isinstance(_core_database_all, (list, tuple, set))
|
||||
or not all(isinstance(name, str) for name in _core_database_all)
|
||||
)
|
||||
)
|
||||
)
|
||||
):
|
||||
del sys.modules["core.database"]
|
||||
|
||||
import pytest
|
||||
from src.webhook_manager import validate_webhook_url
|
||||
|
||||
Reference in New Issue
Block a user