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

150 lines
4.3 KiB
Python

"""
插件实例日志等级覆盖列的持久化读写测试。
"""
from __future__ import annotations
import pytest
from sqlalchemy import delete
from sqlalchemy.orm import Session
from app.db.models.plugininstance import PluginInstance
from app.db.oper.plugininstance import PluginInstanceOper
from app.db.uow import run_sync_transaction
_INSTANCE_IDS = ("LogLevelHost", "LogLevelHost@clone1", "LogLevelNeverSet")
@pytest.fixture(autouse=True)
def purge_written_rows():
"""
删除用例写入的行,测试库在整个会话内共享,残留会干扰后续用例。
"""
yield
def purge(session: Session) -> None:
"""
按本文件使用的固定标识精确删除,不触碰其他用例的数据。
"""
session.execute(
delete(PluginInstance).where(
PluginInstance.instance_id.in_(_INSTANCE_IDS)
)
)
run_sync_transaction(purge)
def test_set_log_level_creates_host_row_when_instance_has_no_row_yet():
"""
只设过等级、从没存过参数的插件也要有一行,否则覆盖无处落盘。
"""
oper = PluginInstanceOper()
assert oper.set_log_level(
instance_id="LogLevelHost",
log_level="DEBUG",
log_expires_at="2026-01-01T00:00:00+00:00",
) is True
record = oper.get("LogLevelHost")
assert record is not None
assert record.is_host is True
assert record.log_level == "DEBUG"
assert record.log_expires_at == "2026-01-01T00:00:00+00:00"
def test_set_log_level_keeps_existing_config_and_identity_on_a_clone_row():
"""
在分身行上写等级只动两列,业务参数与归属原样保留。
"""
oper = PluginInstanceOper()
oper.save(instance_id="LogLevelHost@clone1", source_plugin_id="LogLevelHost")
oper.save_config_data(
instance_id="LogLevelHost@clone1",
source_plugin_id="LogLevelHost",
config_data={"enable": True},
)
assert oper.set_log_level(
instance_id="LogLevelHost@clone1",
log_level="ERROR",
log_expires_at=None,
) is True
record = oper.get("LogLevelHost@clone1")
assert record is not None
assert record.log_level == "ERROR"
assert record.log_expires_at is None
assert record.config_data == {"enable": True}
assert record.source_plugin_id == "LogLevelHost"
def test_clearing_log_level_recycles_a_host_row_that_carries_nothing_else():
"""
清除覆盖后只剩一对身份列的本体行要回收,不留空行堆积。
"""
oper = PluginInstanceOper()
oper.set_log_level(
instance_id="LogLevelHost",
log_level="WARNING",
log_expires_at=None,
)
assert oper.set_log_level(
instance_id="LogLevelHost",
log_level=None,
log_expires_at=None,
) is True
assert oper.get("LogLevelHost") is None
def test_clearing_log_level_keeps_a_clone_row_and_a_host_row_with_config():
"""
分身行与仍承载配置的本体行不因清除等级而消失。
"""
oper = PluginInstanceOper()
oper.save(instance_id="LogLevelHost@clone1", source_plugin_id="LogLevelHost")
oper.set_log_level(
instance_id="LogLevelHost@clone1",
log_level="DEBUG",
log_expires_at=None,
)
oper.save_config_data(
instance_id="LogLevelHost",
source_plugin_id="LogLevelHost",
config_data={"enable": False},
)
oper.set_log_level(
instance_id="LogLevelHost",
log_level="DEBUG",
log_expires_at=None,
)
oper.set_log_level(
instance_id="LogLevelHost@clone1", log_level=None, log_expires_at=None
)
oper.set_log_level(instance_id="LogLevelHost", log_level=None, log_expires_at=None)
clone = oper.get("LogLevelHost@clone1")
assert clone is not None
assert clone.log_level is None
host = oper.get("LogLevelHost")
assert host is not None
assert host.config_data == {"enable": False}
def test_clearing_log_level_for_an_unknown_instance_creates_nothing():
"""
清除一个从未落盘过的实例不得凭空建出一行。
"""
oper = PluginInstanceOper()
assert oper.set_log_level(
instance_id="LogLevelNeverSet",
log_level=None,
log_expires_at=None,
) is False
assert oper.get("LogLevelNeverSet") is None