Files
Haocode/tests/test_debug_window.py
T
2026-09-17 16:30:02 +08:00

140 lines
5.4 KiB
Python
Raw 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 -*-
"""独立调试器窗口 + 调试日志协议 回归测试(离屏,临时文件,不碰真实 DB/日志)
运行: PYTHONIOENCODING=utf-8 QT_QPA_PLATFORM=offscreen python tests/test_debug_window.py
"""
import sys, os, re, tempfile
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
_TMPDIR = tempfile.mkdtemp(prefix="haocode_dbg_")
os.environ["HAOCODE_DEBUG_LOG"] = os.path.join(_TMPDIR, "debug_session.log")
os.environ["HAOCODE_DEBUG_CMD"] = os.path.join(_TMPDIR, "debug_window.cmd")
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
os.environ["QTWEBENGINE_CHROMIUM_FLAGS"] = "--disable-gpu"
from core import debug_log as dl
PASS, FAIL = 0, 0
def check(name, cond, extra=""):
global PASS, FAIL
if cond:
PASS += 1
print(f" PASS {name}")
else:
FAIL += 1
print(f" FAIL {name} {extra}")
def read_log():
if not os.path.exists(dl.DEBUG_LOG_PATH):
return ""
with open(dl.DEBUG_LOG_PATH, "r", encoding="utf-8") as f:
return f.read()
LINE_RE = re.compile(r"^\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}\] "
r"\[(USER|AGENT|APP|SYS)\] .+$")
# ============ T1: debug_log 三方写入 + 行格式 ============
print("T1: debug_log 行格式与三方 TAG")
dl.debug_log("hello app", "APP")
dl.debug_log("代理注入一条备注", "AGENT")
dl.debug_log("用户观察到标签 40.5k", "USER")
lines = [l for l in read_log().splitlines() if l]
check("三行全部写入", len(lines) == 3, lines)
check("行格式 [ts] [TAG] msg",
all(LINE_RE.match(l) for l in lines), lines)
check("TAG 顺序 APP/AGENT/USER",
[re.search(r"\[(USER|AGENT|APP|SYS)\]", l).group(1) for l in lines]
== ["APP", "AGENT", "USER"])
# ============ T2: poll_debug_cmd 控制协议 ============
print("T2: poll_debug_cmd 消费语义")
with open(dl.DEBUG_CMD_PATH, "w", encoding="utf-8") as f:
f.write("show\n")
check("show 被识别", dl.poll_debug_cmd() == "show")
check("文件被消费(再读为 None", dl.poll_debug_cmd() is None)
with open(dl.DEBUG_CMD_PATH, "w", encoding="utf-8") as f:
f.write(" HIDE ")
check("hide 大小写/空白容忍", dl.poll_debug_cmd() == "hide")
with open(dl.DEBUG_CMD_PATH, "w", encoding="utf-8") as f:
f.write("garbage")
check("非法内容忽略", dl.poll_debug_cmd() is None)
# ============ T3-T6: DebugWindow 行为(离屏) ============
print("T3: DebugWindow 用户输入 → [USER] 落盘")
from PyQt6.QtWidgets import QApplication
app = QApplication.instance() or QApplication(sys.argv)
import ui.views.debug_window as dw
# 应用日志 tab 指向临时文件(不读真实 diag.log)
_tmp_diag = os.path.join(_TMPDIR, "diag.log")
dw._APP_LOGS[:] = [("DIAG", _tmp_diag)]
win = dw.DebugWindow()
check("窗口标题独立", win.windowTitle() == "Haocode 调试器")
win._input.setText(" 发送后标签跳到 80k ")
win._on_submit()
check("输入框被清空", win._input.text() == "")
check("[USER] 已落盘且去首尾空白",
any(l.endswith("[USER] 发送后标签跳到 80k") for l in read_log().splitlines()))
print("T4: 首次 tick 记 [SYS] 开启事件")
win._tick()
check("[SYS] 调试窗口开启 已写入",
any("[SYS] 调试窗口开启" in l for l in read_log().splitlines()))
print("T5: 实时 tail 会话日志 + 应用日志")
dl.debug_log("tick 前注入的 APP 事件", "APP")
dl.debug_log("AGENT: 现在检查 compaction_diag.log", "AGENT")
win._tick()
txt = win._view_session.toPlainText()
check("会话视图含 APP 事件", "tick 前注入的 APP 事件" in txt, txt[-300:])
check("会话视图含 AGENT 注入", "AGENT: 现在检查 compaction_diag.log" in txt)
with open(_tmp_diag, "w", encoding="utf-8") as f:
f.write("[12:00:00.000] DIAG_TEST_LINE\n")
win._tick()
check("应用日志视图含 DIAG tail",
"DIAG_TEST_LINE" in win._view_app.toPlainText())
check("应用日志带文件头", "[DIAG]" in win._view_app.toPlainText())
print("T6: 暂停显示 + 截断重置")
win._chk_pause.setChecked(True) # 暂停
dl.debug_log("暂停期间的行不应上屏", "APP")
win._tick()
check("暂停期间不上屏", "暂停期间的行不应上屏"
not in win._view_session.toPlainText())
# 文件截断(模拟「清空会话日志」)→ 偏移重置,新行仍可读取
win._chk_pause.setChecked(False)
with open(dl.DEBUG_LOG_PATH, "w", encoding="utf-8") as f:
f.write("[2026-01-01 00:00:00.000] [SYS] 截断后新内容\n")
win._tick()
check("截断后偏移重置、新行上屏",
"截断后新内容" in win._view_session.toPlainText())
win.close()
# ============ T4: 调试窗口随程序启动(autostart_debug_window ============
print("T4: 调试窗口随程序启动")
p = dl.DEBUG_CMD_PATH
if os.path.exists(p):
os.remove(p)
# 显式 false → 不写控制文件
check("T4.autostart=False 不写控制文件",
dl.autostart_debug_window({"debug_window_autostart": False}) is False
and not os.path.exists(p))
# 缺省(键不存在)→ 默认开
check("T4.缺省(无键)写入 show",
dl.autostart_debug_window({}) is True and os.path.exists(p))
check("T4.轮询消费 show",
dl.poll_debug_cmd() == "show" and not os.path.exists(p))
# 显式 true
check("T4.autostart=true 写入 show",
dl.autostart_debug_window({"debug_window_autostart": True}) is True)
check("T4.轮询再消费 show",
dl.poll_debug_cmd() == "show")
print(f"\n===== {PASS} PASS / {FAIL} FAIL =====")
sys.exit(1 if FAIL else 0)