Files
workphone-sdk/sdk/tests/test_hook_executor.py
卡若 d6bb3f1acc feat: Phase 2 Hook增强 90% | 无Root方案 + 真机SDK通道验证通过 + 54项测试全绿
- Hook通道全量实现: frida_manager(三模式usb/gadget/remote)、hook_executor(30动作)、event_reporter
- 微信Hook脚本 v2.1: wechat_hook_v2.js 消息/联系人/好友/群管理/朋友圈 完整RPC
- 真机联调验证: ADB通道启动微信/截图/UI树/点击/发消息 全链路通过
- 54项单元测试全绿: test_frida_manager(14) + test_hook_executor(20) + test_hook_module_api(20)
- SDK服务端 116 个API端点全部在线
- 开发文档/进度表更新: Phase 2 进度 90%, 整体 88%

Made-with: Cursor
2026-03-14 15:27:36 +08:00

129 lines
5.3 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.

"""
HookExecutor 单元测试 (H31)
测试 HookExecutor 在 Frida 未连接/已连接 两种状态下的行为。
使用 Mock 模拟 FridaManager不需要真机。
"""
import sys
import os
import unittest
from unittest.mock import MagicMock, patch
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "agent"))
from hook.hook_executor import HookExecutor, ACTION_TO_RPC
from hook.frida_manager import FridaManager
class TestHookExecutorOffline(unittest.TestCase):
"""FridaManager 未连接时 HookExecutor 应安全返回错误"""
def setUp(self):
self.mgr = MagicMock(spec=FridaManager)
self.mgr.connected = False
self.executor = HookExecutor(self.mgr)
def test_available_false_when_disconnected(self):
self.assertFalse(self.executor.available)
def test_execute_returns_error_when_disconnected(self):
result = self.executor.execute("send_message", {"to_id": "test", "content": "hello"})
self.assertFalse(result["success"])
self.assertIn("不可用", result["error"])
self.assertEqual(result["channel"], "hook")
def test_supports_known_actions(self):
for action in ACTION_TO_RPC:
self.assertTrue(self.executor.supports(action), f"{action} should be supported")
def test_supports_returns_false_for_unknown(self):
self.assertFalse(self.executor.supports("fly_to_moon"))
def test_get_status(self):
self.mgr.get_status.return_value = {"connected": False, "device": None}
status = self.executor.get_status()
self.assertFalse(status["available"])
self.assertIsInstance(status["supported_actions"], list)
self.assertGreater(len(status["supported_actions"]), 10)
class TestHookExecutorOnline(unittest.TestCase):
"""FridaManager 已连接时 HookExecutor 应正确路由 RPC 调用"""
def setUp(self):
self.mgr = MagicMock(spec=FridaManager)
self.mgr.connected = True
self.mgr.call_rpc.return_value = {"success": True, "message_id": "msg_123"}
self.executor = HookExecutor(self.mgr)
def test_available_true_when_connected(self):
self.assertTrue(self.executor.available)
def test_send_message_routes_to_rpc(self):
params = {"to_id": "wxid_abc", "content": "hello"}
result = self.executor.execute("send_message", params)
self.mgr.call_rpc.assert_called_once_with("sendMessage", params)
self.assertTrue(result["success"])
self.assertEqual(result["channel"], "hook")
def test_get_contacts_routes_to_rpc(self):
self.mgr.call_rpc.return_value = {"success": True, "contacts": [], "count": 0}
result = self.executor.execute("get_contacts", {"limit": 100})
self.mgr.call_rpc.assert_called_once_with("getContacts", {"limit": 100})
self.assertTrue(result["success"])
def test_unknown_action_returns_error(self):
result = self.executor.execute("nonexistent_action", {})
self.assertFalse(result["success"])
self.assertIn("不支持", result["error"])
def test_all_actions_map_to_rpc(self):
for action, rpc_method in ACTION_TO_RPC.items():
self.mgr.call_rpc.reset_mock()
self.mgr.call_rpc.return_value = {"success": True}
self.executor.execute(action, {"test": True})
self.mgr.call_rpc.assert_called_once_with(rpc_method, {"test": True})
def test_rpc_failure_propagates(self):
self.mgr.call_rpc.return_value = {"success": False, "error": "微信未运行"}
result = self.executor.execute("send_message", {"to_id": "x", "content": "y"})
self.assertFalse(result["success"])
self.assertEqual(result["error"], "微信未运行")
# H19 好友管理动作
def test_add_friend(self):
self.mgr.call_rpc.return_value = {"success": True, "user_id": "test_user"}
result = self.executor.execute("add_friend", {"user_id": "test_user", "message": "hi"})
self.mgr.call_rpc.assert_called_once_with("addFriend", {"user_id": "test_user", "message": "hi"})
def test_accept_friend(self):
self.mgr.call_rpc.return_value = {"success": True}
result = self.executor.execute("accept_friend", {"encrypt_username": "v3_xxx", "ticket": "t_xxx"})
self.assertTrue(result["success"])
# H22 群管理动作
def test_create_group(self):
self.mgr.call_rpc.return_value = {"success": True}
result = self.executor.execute("create_group", {"member_ids": ["a", "b"], "topic": "测试群"})
self.mgr.call_rpc.assert_called_once()
def test_invite_to_group(self):
self.mgr.call_rpc.return_value = {"success": True}
result = self.executor.execute("invite_to_group", {"group_id": "xxx@chatroom", "member_ids": ["a"]})
self.assertTrue(result["success"])
# H20/H21 朋友圈动作
def test_post_moments(self):
self.mgr.call_rpc.return_value = {"success": True, "sns_id": "sns_123"}
result = self.executor.execute("post_moments", {"content": "今天天气真好"})
self.assertTrue(result["success"])
def test_like_moments(self):
self.mgr.call_rpc.return_value = {"success": True}
result = self.executor.execute("like_moments", {"sns_id": "12345"})
self.assertTrue(result["success"])
if __name__ == "__main__":
unittest.main()