"""验证 _expire_unreachable_pending 的快速放弃逻辑。 覆盖场景: 1. 有 staged_reply_text 的任务:失败 >=3 次即放弃(阈值 3) 2. 有 staged_reply_text 的任务:失败 <3 次保留 3. 无 staged_reply_text 的任务:失败 <8 次保留(原阈值 8) 4. 无 staged_reply_text 的任务:失败 >=8 次放弃 5. 放弃后任务从队列移除(_clear_reply_pending 被调用) 6. 放弃后不落档(_commit_staged_exchange 不被调用) """ import os import sys import time from unittest import mock sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)) + "/..") from wechat_bot import WeChatBot # noqa: E402 def make_bot(): bot = WeChatBot.__new__(WeChatBot) bot._pending_lock = None bot._pending_reply_sessions = {} bot._pending_reply_path = "" bot._pending_scan_progress = {} bot._pending_exchanges = {} bot._cancelled_reply_sessions = set() bot._unrepliable_sessions = {} bot._uncertain_tracking = {} bot._last_send_receipt_visible_text = "" bot._reset_pending_batch = lambda fp: None bot._forget_uncertain_tracking = lambda fp: None bot._persist_pending_replies = lambda: None bot._persist_unrepliable_sessions = lambda: None bot.store = mock.MagicMock() bot.remember_exchange = mock.MagicMock() bot._commit_staged_exchange = mock.MagicMock() return bot def run(): passed = 0 def check(name, cond): nonlocal passed if cond: passed += 1 print(f" [PASS] {name}") else: print(f" [FAIL] {name}") print("== 有 AI 回复的任务快速放弃 ==") bot = make_bot() fp = bytes.fromhex("a1" * 20) # 失败 2 次 + 有回复 → 保留 state = {"resume_failures": 2, "staged_reply_text": "在呢,有什么事你慢慢说"} bot._pending_reply_sessions[fp.hex()] = state r = bot._expire_unreachable_pending(fp, state) check("staged 回复失败2次 → 保留", r is False and fp.hex() in bot._pending_reply_sessions) # 失败 3 次 + 有回复 → 放弃 state["resume_failures"] = 3 r = bot._expire_unreachable_pending(fp, state) check("staged 回复失败3次 → 放弃", r is True and fp.hex() not in bot._pending_reply_sessions) check("放弃时不落档(回复未发出)", bot._commit_staged_exchange.call_count == 0) print("== 纯定位任务保持原阈值 8 ==") bot = make_bot() fp2 = bytes.fromhex("b2" * 20) state2 = {"resume_failures": 7} # 无 staged_reply_text bot._pending_reply_sessions[fp2.hex()] = state2 r = bot._expire_unreachable_pending(fp2, state2) check("无回复失败7次 → 保留", r is False and fp2.hex() in bot._pending_reply_sessions) state2["resume_failures"] = 8 r = bot._expire_unreachable_pending(fp2, state2) check("无回复失败8次 → 放弃", r is True and fp2.hex() not in bot._pending_reply_sessions) print("== 边界与异常 ==") bot = make_bot() fp3 = bytes.fromhex("c3" * 20) state3 = {"resume_failures": "invalid", "staged_reply_text": " "} bot._pending_reply_sessions[fp3.hex()] = state3 r = bot._expire_unreachable_pending(fp3, state3) check("非法 failures 且空回复 → 按0处理保留", r is False and fp3.hex() in bot._pending_reply_sessions) bot = make_bot() fp4 = bytes.fromhex("d4" * 20) state4 = {"resume_failures": 3, "staged_reply_text": " ", "reply_text": "x"} bot._pending_reply_sessions[fp4.hex()] = state4 r = bot._expire_unreachable_pending(fp4, state4) check("空白 staged 回复按纯定位处理(3次保留)", r is False and fp4.hex() in bot._pending_reply_sessions) print(f"\n结果: {passed}/7 通过") return passed == 7 if __name__ == "__main__": ok = run() sys.exit(0 if ok else 1)