Files
oc_session/_test_mcpctl.py

117 lines
5.3 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 -*-
"""mcpctl 热重载前置探活单测(2026-09-25 用户反馈)。
用户场景:mcp↔wsl 开关对调后,WSL/OC 没在跑 → 报「热重载失败:… WinError 10061
连接拒绝」。期望:没有可重载的 OC 就跳过重载、按成功返回(下次冷启动自动加载),
只有「OC 在跑但重载出错」才算失败。
"""
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import mcpctl # noqa: E402
FAIL: list[str] = []
def check(name: str, cond: bool, extra: str = "") -> None:
print(("PASS " if cond else "FAIL ") + name + (" | " + extra if extra else ""))
if not cond:
FAIL.append(name)
class _A: # 最小 args 替身(只用到 _live_oc/do_reload 需要的字段)
distro = "Ubuntu-24.04"
password = ""
port = 4096
timeout = 2.0
args = _A()
_orig = (mcpctl._wsl_running, mcpctl._find_live_host, mcpctl._post)
_orig_cand = mcpctl._candidate_hosts
def _no_net(*_a, **_k):
raise AssertionError("这一步不该做网络探测")
try:
# ---------- 1. WSL 目标 + VM 未运行 -> 直接 skip,绝不探测 ----------
mcpctl._wsl_running = lambda d: False
mcpctl._find_live_host = _no_net
h, pwd, skip = mcpctl._live_oc("wsl", args)
check("WSL 未运行 -> skip 且不做探测",
h == "" and bool(skip) and "WSL 未启动" in skip, str(skip))
# ---------- 2. WSL 在跑但 OC 没在跑 -> skip 带探测原因(不再是「失败」) ----------
mcpctl._wsl_running = lambda d: True
mcpctl._find_live_host = (
lambda t, a, pw: ("", "/root/.config/opencode", "http://172.29.95.185:4096 连不上")
)
h, pwd, skip = mcpctl._live_oc("wsl", args)
check("OC 未运行 -> skip 带原因", h == "" and bool(skip) and "连不上" in skip, str(skip))
# ---------- 3. OC 在跑 -> 不 skip,host 直接复用 ----------
mcpctl._find_live_host = (
lambda t, a, pw: ("http://127.0.0.1:4096", "/root/.config/opencode", "")
)
h, pwd, skip = mcpctl._live_oc("wsl", args)
check("OC 运行中 -> 不 skip 且拿到 host",
skip is None and h.startswith("http"), str((h, skip)))
# ---------- 4. do_reload 复用 host -> 不再探测,直接 reload 成功 ----------
mcpctl._find_live_host = _no_net
mcpctl._post = lambda url, pw, timeout, data=b"{}", method="POST": (200, "{}")
ok, msg = mcpctl.do_reload("wsl", args, host="http://127.0.0.1:4096", password="x")
check("do_reload 复用 host -> 热重载成功", ok and "热重载成功" in msg, msg)
# ---------- 5. OC 在跑但 reload 返回错误 -> 仍算真实失败(不能吞) ----------
mcpctl._post = lambda url, pw, timeout, data=b"{}", method="POST": (0, "boom")
ok, msg = mcpctl.do_reload("wsl", args, host="http://127.0.0.1:4096", password="x")
check("OC 在跑但重载连不上 -> 仍报失败", (not ok) and "连不上" in msg, msg)
# ---------- 6. 本机目标 OC 没在跑 -> skip(本机目标不看 WSL 状态) ----------
mcpctl._find_live_host = (
lambda t, a, pw: ("", "C:/cfg", "没有找到运行中的 OC(4096 未监听,端口发现也未命中)")
)
h, pwd, skip = mcpctl._live_oc("local", args)
check("local OC 未运行 -> skip", h == "" and bool(skip) and "没有找到" in skip, str(skip))
# ---------- 7. 探活措辞(2026-09-25 Round 9):OC 没启动要说「未启动」 ----------
# 真实 _find_live_host + 假 _post:10061 拒绝不许再写成吓人的「连不上」
mcpctl._find_live_host = _orig[1]
mcpctl._candidate_hosts = lambda t, a: ["http://172.29.95.185:4096"]
mcpctl._post = lambda *ar, **kw: (
0, "<urlopen error [WinError 10061] 由于目标计算机积极拒绝,无法连接。>")
h, _d, why = mcpctl._find_live_host("wsl", args, "pw")
check("10061 拒绝 -> 措辞「OC 未启动」且不含「连不上」",
h == "" and "OC 未启动" in why and "连不上" not in why, why)
# ---------- 8. 超时 -> 「连接超时(OC 未启动或不可达)」 ----------
mcpctl._post = lambda *ar, **kw: (
0, "<urlopen error [WinError 10060] 连接方在一段时间后没有正确答复>")
h, _d, why = mcpctl._find_live_host("wsl", args, "pw")
check("10060 超时 -> 措辞「连接超时」", h == "" and "超时" in why, why)
# ---------- 9. 未知网络错误 -> 保留原文(真实错误不能吞) ----------
mcpctl._post = lambda *ar, **kw: (0, "weird backend exploded")
h, _d, why = mcpctl._find_live_host("wsl", args, "pw")
check("未知错误 -> 保留「连不上」原文", h == "" and "连不上" in why, why)
# ---------- 10. skip 端到端:_live_oc 拼出的整句都不该像报错 ----------
mcpctl._wsl_running = lambda d: True
mcpctl._post = lambda *ar, **kw: (
0, "<urlopen error [WinError 10061] 由于目标计算机积极拒绝,无法连接。>")
h, pwd, skip = mcpctl._live_oc("wsl", args)
check("skip 整句 = 状态描述(含「OC 未启动」,不含「连不上」)",
h == "" and bool(skip) and "OC 未启动" in skip and "连不上" not in skip,
str(skip))
finally:
mcpctl._wsl_running, mcpctl._find_live_host, mcpctl._post = _orig
mcpctl._candidate_hosts = _orig_cand
print()
print(("ALL PASS" if not FAIL else "FAILURES: " + ", ".join(FAIL)))
sys.exit(1 if FAIL else 0)