Files
iAOP/core/template-console/_sanity_check.py

140 lines
5.0 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.
# -*- coding: utf-8 -*-
"""⑤.7 模板配置台离线基本校验(无构建环境下的离线验证)。
检查项:
1. 全部单元测试通过(unittest discover);
2. 冒烟:6 个子模块可导入;
3. 冒烟:端到端数据流跑通——
RBAC 判定(#62) → 点位导入(#63) → 配置 CRUD(#64) → 预览(#65)
→ 发布版本(#66) → 推送内核(#67) → 完整性校验通过。
用法:python _sanity_check.py
退出码:0 成功 / 1 失败。
"""
from __future__ import annotations
import os
import sys
import tempfile
import unittest
HERE = os.path.dirname(os.path.abspath(__file__))
def _run_unit_tests() -> tuple[int, int]:
"""跑 tests/ 下全部测试,返回 (run, failures+errors)。"""
# 挂载 template_console 包 + edge-gateway/point_dict(同 tests/_bootstrap.py)
sys.path.insert(0, HERE)
import types
if "template_console" not in sys.modules:
pkg = types.ModuleType("template_console")
pkg.__path__ = [HERE]
sys.modules["template_console"] = pkg
edge_gw = os.path.join(os.path.dirname(HERE), "edge-gateway")
if os.path.isdir(edge_gw) and edge_gw not in sys.path:
sys.path.insert(0, edge_gw)
loader = unittest.TestLoader()
suite = loader.discover(os.path.join(HERE, "tests"), pattern="test_*.py")
runner = unittest.TextTestRunner(verbosity=1, stream=sys.stdout)
result = runner.run(suite)
return result.testsRun, len(result.failures) + len(result.errors)
def _smoke_flow() -> list[str]:
"""端到端冒烟:返回问题列表(空=通过)。"""
problems: list[str] = []
try:
from template_console.rbac import ( # type: ignore
Action, Resource, RoleKind, User, has_permission,
)
from template_console.point_importer import ( # type: ignore
TemplateKind, import_csv_string,
)
from template_console.config_store import ConfigKind, ConfigStore # type: ignore
from template_console.preview import preview_from_store, PreviewKind # type: ignore
from template_console.release import ReleaseManager # type: ignore
from template_console.push_channel import PushChannel # type: ignore
except Exception as exc: # noqa: BLE001
problems.append(f"模块导入失败:{exc}")
return problems
# 1) RBAC:admin 可发布,readonly 不可
admin = User("a", RoleKind.ADMIN)
viewer = User("v", RoleKind.READONLY)
if not has_permission(admin, Resource.RELEASE, Action.PUBLISH).allow:
problems.append("RBAC:admin 应能发布")
if has_permission(viewer, Resource.RELEASE, Action.PUBLISH).allow:
problems.append("RBAC:readonly 不应能发布")
# 2) 点位字典导入
csv_text = (
"device_id,point_id,name,unit,dataType,sampleRate,qualityCode,opcNode,protocol\n"
"CLF-01,CLF-01.TEMP,炉温,℃,float,1000,true,ns=2;s=CLF.Temp,opcua\n"
)
_, rep = import_csv_string(csv_text, template=TemplateKind.TI)
if not rep.ok:
problems.append(f"点位导入应通过:{rep.summary()}")
# 3) 配置 CRUD + 4) 预览 + 5) 发布 + 6) 推送
tmp = tempfile.mkdtemp()
try:
store = ConfigStore(tmp)
store.upsert(ConfigKind.LAYOUT, "dashboard",
[{"type": "trend", "bind": "CLF-01.TEMP",
"x": 0, "y": 0, "w": 6, "h": 2}],
updated_by="li", reason="冒烟")
# 预览
prev = preview_from_store(store, PreviewKind.LAYOUT)
if not prev.items:
problems.append("预览:布局应渲染出 widget")
# 发布
rm = ReleaseManager(store)
rel = rm.publish("1.0.0", released_by="admin", changelog="冒烟发布")
if rm.latest().version != "1.0.0":
problems.append("发布:最新版本应为 1.0.0")
# 推送 + 完整性校验
inbox = os.path.join(tmp, "inbox")
ch = PushChannel(inbox=inbox)
manifest = ch.push(rel, pushed_by="admin")
if not PushChannel.verify(manifest):
problems.append("推送:manifest 完整性校验失败")
if not os.path.isfile(os.path.join(inbox, "manifest-1.0.0.json")):
problems.append("推送:manifest 文件未写入 inbox")
finally:
import shutil
shutil.rmtree(tmp, ignore_errors=True)
return problems
def main() -> int:
print("=" * 60)
print("⑤.7 模板配置台 离线基本校验")
print("=" * 60)
# 1) 单元测试
print("\n[1/2] 单元测试")
run_count, fail_count = _run_unit_tests()
if fail_count:
print(f"\nFAIL: 单元测试 {fail_count} 项失败(共 {run_count} 项)")
return 1
# 2) 冒烟
print("\n[2/2] 端到端冒烟")
problems = _smoke_flow()
if problems:
print("FAIL")
for p in problems:
print(" -", p)
return 1
print(f"\nOK: 单元测试 {run_count} 项全过;端到端冒烟通过(#62→#67 数据流正常)")
return 0
if __name__ == "__main__":
sys.exit(main())