|
1 | 1 | import pytest |
2 | 2 | from unittest.mock import patch, MagicMock |
3 | 3 | from alibaba_cloud_ops_mcp_server.tools import api_tools |
| 4 | +import json |
4 | 5 |
|
5 | 6 | def fake_api_meta(post=False, no_summary=False): |
6 | 7 | meta = { |
@@ -127,3 +128,104 @@ def test_create_and_decorate_tool_api_meta_exception(): |
127 | 128 | with pytest.raises(Exception) as e: |
128 | 129 | api_tools._create_and_decorate_tool(mcp, 'ecs', 'DescribeInstances') |
129 | 130 | assert 'meta-fail' in str(e.value) |
| 131 | + |
| 132 | +def test_create_function_schemas_ecs_list_parameters(): |
| 133 | + # 测试ECS服务的特殊参数处理 |
| 134 | + api_meta = { |
| 135 | + 'parameters': [ |
| 136 | + {'name': 'InstanceIds', 'schema': {'type': 'string', 'description': '实例ID列表', 'example': '["i-123", "i-456"]', 'required': True}}, |
| 137 | + {'name': 'SecurityGroupIds', 'schema': {'type': 'string', 'description': '安全组ID列表', 'example': '["sg-123", "sg-456"]', 'required': False}}, |
| 138 | + {'name': 'NormalParam', 'schema': {'type': 'string', 'description': '普通参数', 'example': 'test', 'required': False}}, |
| 139 | + ], |
| 140 | + 'methods': ['get'], |
| 141 | + 'path': '/test', |
| 142 | + 'summary': '测试API' |
| 143 | + } |
| 144 | + |
| 145 | + # 测试ECS服务 |
| 146 | + schemas = api_tools._create_function_schemas('ecs', 'DescribeInstances', api_meta) |
| 147 | + assert schemas['DescribeInstances']['InstanceIds'][0] == list |
| 148 | + assert schemas['DescribeInstances']['SecurityGroupIds'][0] == list |
| 149 | + assert schemas['DescribeInstances']['NormalParam'][0] == str |
| 150 | + |
| 151 | + # 测试非ECS服务 |
| 152 | + schemas = api_tools._create_function_schemas('rds', 'DescribeInstances', api_meta) |
| 153 | + assert schemas['DescribeInstances']['InstanceIds'][0] == str |
| 154 | + assert schemas['DescribeInstances']['SecurityGroupIds'][0] == str |
| 155 | + assert schemas['DescribeInstances']['NormalParam'][0] == str |
| 156 | + |
| 157 | +def test_tools_api_call_ecs_list_parameters(): |
| 158 | + with patch('alibaba_cloud_ops_mcp_server.tools.api_tools.ApiMetaClient') as mock_ApiMetaClient, \ |
| 159 | + patch('alibaba_cloud_ops_mcp_server.tools.api_tools.create_client') as mock_create_client, \ |
| 160 | + patch('alibaba_cloud_ops_mcp_server.tools.api_tools.open_api_models') as mock_open_api_models, \ |
| 161 | + patch('alibaba_cloud_ops_mcp_server.tools.api_tools.OpenApiUtilClient') as mock_OpenApiUtilClient, \ |
| 162 | + patch('alibaba_cloud_ops_mcp_server.tools.api_tools.util_models') as mock_util_models: |
| 163 | + |
| 164 | + mock_ApiMetaClient.get_api_meta.return_value = fake_api_meta() |
| 165 | + mock_ApiMetaClient.get_service_version.return_value = '2023-01-01' |
| 166 | + mock_ApiMetaClient.get_service_style.return_value = 'RPC' |
| 167 | + mock_open_api_models.OpenApiRequest.return_value = MagicMock() |
| 168 | + mock_open_api_models.Params.return_value = MagicMock() |
| 169 | + mock_create_client.return_value.call_api.return_value = {'result': 'ok'} |
| 170 | + mock_OpenApiUtilClient.query.return_value = {} |
| 171 | + mock_util_models.RuntimeOptions.return_value = MagicMock() |
| 172 | + |
| 173 | + # 测试ECS服务的列表参数转换 |
| 174 | + params = { |
| 175 | + 'InstanceIds': ['i-123', 'i-456'], |
| 176 | + 'SecurityGroupIds': ['sg-123', 'sg-456'], |
| 177 | + 'NormalParam': 'test', |
| 178 | + 'RegionId': 'cn-hangzhou' |
| 179 | + } |
| 180 | + |
| 181 | + # 测试ECS服务 |
| 182 | + result = api_tools._tools_api_call('ecs', 'DescribeInstances', params, None) |
| 183 | + # 验证传入query方法的参数 |
| 184 | + query_args = mock_OpenApiUtilClient.query.call_args[0][0] |
| 185 | + assert isinstance(query_args['InstanceIds'], str) |
| 186 | + assert isinstance(query_args['SecurityGroupIds'], str) |
| 187 | + assert query_args['NormalParam'] == 'test' |
| 188 | + assert json.loads(query_args['InstanceIds']) == ['i-123', 'i-456'] |
| 189 | + assert json.loads(query_args['SecurityGroupIds']) == ['sg-123', 'sg-456'] |
| 190 | + |
| 191 | + # 重置mock |
| 192 | + mock_OpenApiUtilClient.query.reset_mock() |
| 193 | + |
| 194 | + # 测试非ECS服务 |
| 195 | + result = api_tools._tools_api_call('rds', 'DescribeInstances', params, None) |
| 196 | + # 验证传入query方法的参数 |
| 197 | + query_args = mock_OpenApiUtilClient.query.call_args[0][0] |
| 198 | + assert isinstance(query_args['InstanceIds'], list) |
| 199 | + assert isinstance(query_args['SecurityGroupIds'], list) |
| 200 | + assert query_args['InstanceIds'] == ['i-123', 'i-456'] |
| 201 | + assert query_args['SecurityGroupIds'] == ['sg-123', 'sg-456'] |
| 202 | + |
| 203 | +def test_tools_api_call_ecs_list_parameters_non_list(): |
| 204 | + with patch('alibaba_cloud_ops_mcp_server.tools.api_tools.ApiMetaClient') as mock_ApiMetaClient, \ |
| 205 | + patch('alibaba_cloud_ops_mcp_server.tools.api_tools.create_client') as mock_create_client, \ |
| 206 | + patch('alibaba_cloud_ops_mcp_server.tools.api_tools.open_api_models') as mock_open_api_models, \ |
| 207 | + patch('alibaba_cloud_ops_mcp_server.tools.api_tools.OpenApiUtilClient') as mock_OpenApiUtilClient, \ |
| 208 | + patch('alibaba_cloud_ops_mcp_server.tools.api_tools.util_models') as mock_util_models: |
| 209 | + |
| 210 | + mock_ApiMetaClient.get_api_meta.return_value = fake_api_meta() |
| 211 | + mock_ApiMetaClient.get_service_version.return_value = '2023-01-01' |
| 212 | + mock_ApiMetaClient.get_service_style.return_value = 'RPC' |
| 213 | + mock_open_api_models.OpenApiRequest.return_value = MagicMock() |
| 214 | + mock_open_api_models.Params.return_value = MagicMock() |
| 215 | + mock_create_client.return_value.call_api.return_value = {'result': 'ok'} |
| 216 | + mock_OpenApiUtilClient.query.return_value = {} |
| 217 | + mock_util_models.RuntimeOptions.return_value = MagicMock() |
| 218 | + |
| 219 | + # 测试非列表类型的特殊参数 |
| 220 | + params = { |
| 221 | + 'InstanceIds': 'i-123', # 字符串而不是列表 |
| 222 | + 'SecurityGroupIds': None, # None值 |
| 223 | + 'RegionId': 'cn-hangzhou' |
| 224 | + } |
| 225 | + |
| 226 | + # 测试ECS服务 |
| 227 | + result = api_tools._tools_api_call('ecs', 'DescribeInstances', params, None) |
| 228 | + # 验证传入query方法的参数 |
| 229 | + query_args = mock_OpenApiUtilClient.query.call_args[0][0] |
| 230 | + assert query_args['InstanceIds'] == 'i-123' |
| 231 | + assert query_args['SecurityGroupIds'] is None |
0 commit comments