test_query_export_task_tool.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import io
  2. import unittest
  3. from unittest.mock import patch
  4. from app import GatewayApp
  5. from public_gateway import PublicGatewayApp
  6. from tools.query_export_task import QueryExportTaskTool
  7. class RecordingApiClient:
  8. def __init__(self):
  9. self.call = None
  10. def call_tool(self, tool_code, route_path, payload, request_id):
  11. self.call = (tool_code, route_path, payload, request_id)
  12. return {
  13. 'code': 'MCP_0000',
  14. 'data': {'task_ref': payload['task_ref'], 'status': 'queued'},
  15. }
  16. class QueryExportTaskToolTest(unittest.TestCase):
  17. def test_metadata_exposes_only_bounded_task_reference(self):
  18. metadata = QueryExportTaskTool().metadata()
  19. schema = metadata['input_schema']
  20. self.assertEqual('query_export_task', metadata['name'])
  21. self.assertEqual(['task_ref'], schema['required'])
  22. self.assertFalse(schema['additionalProperties'])
  23. self.assertEqual('string', schema['properties']['task_ref']['type'])
  24. self.assertEqual(1, schema['properties']['task_ref']['minLength'])
  25. self.assertEqual(512, schema['properties']['task_ref']['maxLength'])
  26. self.assertIn('单独', metadata['description'])
  27. self.assertIn('不得在同一次调用内等待', metadata['description'])
  28. def test_call_trims_and_forwards_reference(self):
  29. api = RecordingApiClient()
  30. tool = QueryExportTaskTool(api_client=api)
  31. result = tool.call(task_ref=' mexp_abc ', request_id='rq_1')
  32. self.assertEqual('queued', result['data']['status'])
  33. self.assertEqual((
  34. 'query_export_task',
  35. '/mcp/tools/queryExportTask',
  36. {'task_ref': 'mexp_abc'},
  37. 'rq_1',
  38. ), api.call)
  39. def test_invalid_references_are_rejected(self):
  40. tool = QueryExportTaskTool(api_client=RecordingApiClient())
  41. for value in (None, '', ' ', 123, 'a' * 513):
  42. with self.subTest(value=value):
  43. with self.assertRaises(ValueError):
  44. tool.call(task_ref=value)
  45. def test_api_client_is_required(self):
  46. with self.assertRaises(RuntimeError):
  47. QueryExportTaskTool().call(task_ref='mexp_abc')
  48. def test_local_and_public_registries_contain_same_thirteen_tools(self):
  49. local = GatewayApp(api_client=RecordingApiClient()).registered_tool_names()
  50. public = PublicGatewayApp(None, None).registered_tool_names()
  51. self.assertEqual(local, public)
  52. self.assertEqual(13, len(local))
  53. self.assertIn('query_export_task', local)
  54. def test_cli_forwards_only_task_reference(self):
  55. app = GatewayApp()
  56. stdout = io.StringIO()
  57. with patch.object(
  58. app,
  59. 'call_tool',
  60. return_value={'code': 'MCP_0000'},
  61. ) as call_tool:
  62. code = app.run_cli([
  63. 'call',
  64. '--tool', 'query_export_task',
  65. '--task-ref', 'mexp_abc',
  66. '--request-id', 'rq_cli',
  67. ], stdout=stdout)
  68. self.assertEqual(0, code)
  69. call_tool.assert_called_once_with(
  70. 'query_export_task',
  71. {'task_ref': 'mexp_abc'},
  72. request_id='rq_cli',
  73. )
  74. def test_cli_requires_task_reference(self):
  75. with self.assertRaises(ValueError):
  76. GatewayApp().run_cli([
  77. 'call',
  78. '--tool', 'query_export_task',
  79. ], stdout=io.StringIO())
  80. if __name__ == '__main__':
  81. unittest.main()