2026-08-14 18:04:57 +08:00
|
|
|
|
"""
|
|
|
|
|
|
Worker 进程隔离性测试
|
|
|
|
|
|
|
|
|
|
|
|
验证进程插件与网关完全隔离:阻断 chongming(网关包)的两种导入路径后,
|
|
|
|
|
|
worker 侧全链路(SDK 导入 → 插件配置自读 → 插件 import → 契约校验)仍可用。
|
|
|
|
|
|
|
2026-08-25 17:03:35 +08:00
|
|
|
|
与容器行为一致:chdir 到插件项目根 workers/demo/(= 打包 zip 根),
|
|
|
|
|
|
worker_serve 即以该目录为 CWD 读配置、并把 CWD 加入 sys.path。
|
|
|
|
|
|
|
2026-08-14 18:04:57 +08:00
|
|
|
|
任何对 chongming.* / src.chongming.* 的导入都会直接触发 ImportError。
|
|
|
|
|
|
"""
|
2026-08-25 17:03:35 +08:00
|
|
|
|
import os
|
2026-08-14 18:04:57 +08:00
|
|
|
|
import sys
|
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
SRC = Path(__file__).parent
|
2026-08-25 17:03:35 +08:00
|
|
|
|
REPO = SRC.parent
|
|
|
|
|
|
|
|
|
|
|
|
# 模拟容器:CWD = 插件项目根(zip 根),并把它置于 sys.path 首位
|
|
|
|
|
|
PROJECT = REPO / "workers" / "demo"
|
|
|
|
|
|
os.chdir(PROJECT)
|
|
|
|
|
|
sys.path.insert(0, str(PROJECT))
|
2026-08-14 18:04:57 +08:00
|
|
|
|
sys.path.insert(0, str(SRC))
|
|
|
|
|
|
|
|
|
|
|
|
# 阻断网关包导入(两种访问路径)。chongming_worker / zenoh / pydantic 等不受影响。
|
|
|
|
|
|
sys.modules["chongming"] = None # type: ignore[assignment]
|
|
|
|
|
|
sys.modules["src.chongming"] = None # type: ignore[assignment]
|
|
|
|
|
|
|
|
|
|
|
|
failures = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check(name, cond, detail=""):
|
|
|
|
|
|
status = "PASS" if cond else "FAIL"
|
|
|
|
|
|
print(f"[{status}] {name}" + (f" — {detail}" if detail else ""))
|
|
|
|
|
|
if not cond:
|
|
|
|
|
|
failures.append(name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ========== 1. worker SDK 导入(若依赖网关包将在此抛 ImportError) ==========
|
|
|
|
|
|
import chongming_worker.contracts as con_mod # noqa: E402
|
|
|
|
|
|
import chongming_worker.process as proc_mod # noqa: E402
|
|
|
|
|
|
import chongming_worker.route_config as rc_mod # noqa: E402
|
|
|
|
|
|
import chongming_worker.routes_publisher as pub_mod # noqa: E402
|
2026-08-21 15:30:28 +08:00
|
|
|
|
import chongming_worker.storage as sto_mod # noqa: E402
|
2026-08-14 18:04:57 +08:00
|
|
|
|
|
|
|
|
|
|
check("worker SDK 导入(阻断 chongming 后成功)", True)
|
|
|
|
|
|
|
|
|
|
|
|
# ========== 2. 插件配置自读(不依赖网关 _discover_plugins) ==========
|
|
|
|
|
|
wc = proc_mod.load_plugin_config("demo")
|
|
|
|
|
|
check(
|
|
|
|
|
|
"插件配置自读(type/load_mode/module)",
|
|
|
|
|
|
wc["type"] == "demo"
|
|
|
|
|
|
and wc["load_mode"] == "external"
|
|
|
|
|
|
and wc["module"] == "workers.demo",
|
|
|
|
|
|
f"type={wc['type']}, load_mode={wc['load_mode']}, module={wc['module']}",
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# ========== 3. 完整 worker 启动前置链路:import 插件 + 契约校验 ==========
|
|
|
|
|
|
import workers.demo # noqa: E402,F401 触发 @rpc_method 注册
|
|
|
|
|
|
|
|
|
|
|
|
routes = con_mod.validate_worker_contracts("demo")
|
2026-08-21 15:30:28 +08:00
|
|
|
|
subjects = [r["subject"] for r in routes]
|
2026-08-14 18:04:57 +08:00
|
|
|
|
check(
|
|
|
|
|
|
"进程内契约校验通过(TOML ↔ 注册表 ↔ 模型)",
|
2026-08-21 15:30:28 +08:00
|
|
|
|
len(routes) == 5 and "demo.hello" in subjects,
|
|
|
|
|
|
f"routes={subjects}",
|
2026-08-14 18:04:57 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# ========== 4. 代码级双重保险:SDK 无对网关包的 import 语句(AST 精确检查) ==========
|
|
|
|
|
|
import ast # noqa: E402
|
|
|
|
|
|
import inspect # noqa: E402
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _imports_gateway(mod) -> list:
|
|
|
|
|
|
"""返回模块中引用 chongming(非 chongming_worker)的 import 节点列表"""
|
|
|
|
|
|
found = []
|
|
|
|
|
|
tree = ast.parse(inspect.getsource(mod))
|
|
|
|
|
|
for node in ast.walk(tree):
|
|
|
|
|
|
if isinstance(node, ast.Import):
|
|
|
|
|
|
for alias in node.names:
|
|
|
|
|
|
if alias.name == "chongming" or alias.name.startswith("chongming."):
|
|
|
|
|
|
found.append(alias.name)
|
|
|
|
|
|
elif isinstance(node, ast.ImportFrom):
|
|
|
|
|
|
if node.module and (
|
|
|
|
|
|
node.module == "chongming" or node.module.startswith("chongming.")
|
|
|
|
|
|
):
|
|
|
|
|
|
found.append(node.module)
|
|
|
|
|
|
return found
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-08-21 15:30:28 +08:00
|
|
|
|
for mod in (proc_mod, con_mod, pub_mod, rc_mod, sto_mod):
|
2026-08-14 18:04:57 +08:00
|
|
|
|
bad = _imports_gateway(mod)
|
|
|
|
|
|
if bad:
|
|
|
|
|
|
check(f"{mod.__name__} import 了网关包: {bad}", False)
|
|
|
|
|
|
break
|
|
|
|
|
|
else:
|
|
|
|
|
|
check("worker SDK 无对网关包的 import 语句", True)
|
|
|
|
|
|
|
|
|
|
|
|
print("\n" + ("=" * 40))
|
|
|
|
|
|
if failures:
|
|
|
|
|
|
print(f"❌ {len(failures)} 项未通过: {failures}")
|
|
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
print("✅ Worker 进程隔离性全部通过")
|