Files
MoviePilot/tests/test_optional_subsystem_composition.py
DDSRem 2de976f6b3 Merge pull request #7050 from DDSRem-Dev/codex-comment-migration
docs: 统一全项目中文注释和结构化契约说明
2026-10-17 19:26:29 +08:00

141 lines
4.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
可选子系统按配置装配的合同测试。
Redis 缓存只在启动时选用 Redis 后由缓存组合根接入,智能体对话记忆模型归属智能体模块;
未使用这些功能的实例不得常驻 redis 客户端库或 langchain_core。
"""
from __future__ import annotations
import json
import subprocess
import sys
from app.runtime import cache as runtime_cache
from app.runtime.config import settings
from app.startup.composition import cache as cache_composition
def _run_isolated(script: str) -> dict:
"""
在全新解释器中执行导入探针,先装测试站点垫片并隔离配置目录。
"""
prelude = (
"from app.testing.bootstrap import ensure_sites_stub, isolate_config_dir\n"
"isolate_config_dir()\n"
"ensure_sites_stub()\n"
)
completed = subprocess.run(
[sys.executable, "-c", prelude + script],
check=True,
capture_output=True,
text=True,
)
return json.loads(completed.stdout.strip().splitlines()[-1])
def test_file_cache_startup_does_not_load_redis_or_langchain() -> None:
"""
文件缓存实例导入宿主应用并完成缓存装配后,不加载 redis 与 langchain_core。
"""
result = _run_isolated(
"""
import json
import sys
import app.factory
from app.startup.composition.cache import get_cache_composition
forbidden = ("redis", "app.adapters.cache.redis", "langchain_core", "app.agent.memory")
loaded = sorted(
name
for name in sys.modules
if any(name == prefix or name.startswith(prefix + ".") for prefix in forbidden)
)
print(json.dumps({"loaded": loaded, "redis_enabled": get_cache_composition().redis_enabled}))
"""
)
assert result == {"loaded": [], "redis_enabled": False}
def test_redis_cache_composition_registers_owners_and_backends(
monkeypatch,
compose_cache_backend,
) -> None:
"""
启动时选用 Redis 才接入 Redis 后端与连接 owner。
"""
from app.adapters.cache.redis import AsyncRedisHelper, RedisBackend, RedisHelper
monkeypatch.setattr(RedisHelper, "_connect", lambda _self: None)
compose_cache_backend("redis")
composition = cache_composition.get_cache_composition()
assert composition.redis_enabled is True
assert composition.redis_owners == (RedisHelper, AsyncRedisHelper)
assert isinstance(runtime_cache.FileCache(), RedisBackend)
assert runtime_cache.probe_redis_cache() is True
def test_redis_setting_after_local_startup_waits_for_restart(
compose_cache_backend,
) -> None:
"""
启动时未接入 Redis,运行中改成 redis 继续使用本地缓存且不探测连接。
"""
compose_cache_backend("cachetools")
settings.CACHE_BACKEND_TYPE = "redis"
assert cache_composition.get_cache_composition().redis_owners == ()
assert not runtime_cache.FileCache().is_redis()
assert runtime_cache.probe_redis_cache() is None
def test_redis_module_reports_restart_when_redis_not_composed(
compose_cache_backend,
) -> None:
"""
Redis 模块健康检查不代为建连,未接入时提示重启生效。
"""
from app.modules.redis import RedisModule
compose_cache_backend("cachetools")
settings.CACHE_BACKEND_TYPE = "redis"
assert RedisModule().test() == (False, "缓存类型已改为Redis,重启后生效")
def test_legacy_redis_backend_and_conversation_memory_paths_stay_compatible() -> None:
"""
Redis 后端与对话记忆模型的旧导入路径惰性解析到同一个对象。
"""
result = _run_isolated(
"""
import json
import app.schemas
import app.sdk.cache
from app.adapters.cache.backends import RedisBackend as backends_redis
from app.adapters.cache.redis import RedisBackend
from app.agent.memory import ConversationMemory
from app.schemas.agent import ConversationMemory as legacy_memory
print(json.dumps({
"sdk": app.sdk.cache.RedisBackend is RedisBackend,
"backends": backends_redis is RedisBackend,
"schema_module": legacy_memory is ConversationMemory,
"schema_package": app.schemas.ConversationMemory is ConversationMemory,
}))
"""
)
assert result == {
"sdk": True,
"backends": True,
"schema_module": True,
"schema_package": True,
}