""" 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()