Files
tick-stock-panel/backend/tests/test_packaging_spec.py
T
shy3130 a1301e239a fix(desktop): 修复单实例锁、窗口显示与重复启动
- 使用系统文件锁替代 PID 存活判断,崩溃后由系统释放锁并避免删除重建竞态
- 将早期预检异常统一交给启动错误提示,保证退出时释放已取得的锁
- GUI 就绪后显式显示主窗口,避免继承隐藏启动状态
- 移除安装包中重复的安装后启动条目

补充跨进程单实例锁、模拟 Windows 锁异常、早期启动失败、窗口显示与安装配置测试。
Windows 真机安装与窗口行为未在本机验证。

Signed-off-by: shy3130 <shy3130@qq.com>
2026-10-30 20:43:06 +08:00

51 lines
2.3 KiB
Python

"""tsp.spec 打包不变量 — 运行时动态发现的模块必须随冻结产物发布 (issue #459)。
app/extensions/loader.py 用 importlib.import_module + pkgutil.iter_modules 在
运行时发现 app/custom/*, 两条链路对 PyInstaller 静态分析都不可见; tsp.spec
未声明时冻结产物里扩展静默消失(桌面版 AI 对话助手 405, 且无任何日志)。
锁定双声明契约:
- hiddenimports(collect_submodules) 进 PYZ —— 保 import_module 可导入;
- datas 落盘到 app/custom —— frozen 下 app.__path__ 解析到 _internal/app,
保 pkgutil.iter_modules 可枚举(与 fuyao 插件同一处理方式)。
"""
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[2]
SPEC_TEXT = (REPO_ROOT / "packaging" / "tsp.spec").read_text(encoding="utf-8")
# 只断言代码行, 避免被注释里的字样误判为已声明
SPEC_CODE = "\n".join(
line for line in SPEC_TEXT.splitlines() if not line.lstrip().startswith("#")
)
def test_spec_declares_custom_extensions():
"""app/custom/* 双声明: PYZ 可导入 + 磁盘可枚举, 缺一冻结后扩展静默消失。"""
assert 'collect_submodules("app.custom")' in SPEC_CODE
assert '"app/custom"' in SPEC_CODE
def test_spec_declares_builtin_plugin_fuyao():
"""fuyao 插件双声明不被回归 (同类动态发现问题, 见 spec 内注释)。"""
assert "app.plugins.fuyao.provider" in SPEC_CODE
assert "app/plugins/fuyao" in SPEC_CODE
def test_spec_declares_builtin_plugin_tdx():
"""tdx 插件双声明不被回归 (与 fuyao 同一处理方式; probe 子进程入口也要可导入)。"""
assert "app.plugins.tdxquant.provider" in SPEC_CODE
assert "app.plugins.tdxquant.client" in SPEC_CODE
assert "app.plugins.tdxquant.probe" in SPEC_CODE
assert '"plugins" / "tdxquant" / "plugin.yaml"' in SPEC_CODE # 源路径必须指向现存目录
def test_installer_launches_desktop_only_once():
"""重复 postinstall 条目会同时拉起两个桌面后端。"""
text = (REPO_ROOT / "packaging" / "tsp.iss").read_text(encoding="utf-8")
section = text.split("[Run]", 1)[1].split("[UninstallRun]", 1)[0]
launches = [
line for line in section.splitlines()
if line.startswith("Filename:") and "{#MyAppExeName}" in line
]
assert len(launches) == 1